2323
2424#pragma once
2525
26+ #include < atomic>
2627#include < mutex>
2728#include " cell.h"
2829#include " point.h"
@@ -77,7 +78,7 @@ struct grid {
7778 tableT* table=NULL ;
7879 treeT* tree=NULL ;
7980 intT totalPoints;
80- cellBuf ** nbrCache;
81+ std::atomic< cellBuf*>* nbrCache;
8182 std::mutex* cacheLocks;
8283
8384 /* *
@@ -90,11 +91,11 @@ struct grid {
9091 r (rr), pMin(pMinn), cellCapacity(cellMax), totalPoints(0 ) {
9192
9293 cells = newA (cellT, cellCapacity);
93- nbrCache = newA ( cellBuf*, cellCapacity) ;
94+ nbrCache = new std::atomic< cellBuf*>[ cellCapacity] ;
9495 cacheLocks = (std::mutex*) malloc (cellCapacity * sizeof (std::mutex));
9596 parallel_for (0 , cellCapacity, [&](intT i) {
9697 new (&cacheLocks[i]) std::mutex ();
97- nbrCache[i] = NULL ;
98+ nbrCache[i]. store ( nullptr , std::memory_order_relaxed) ;
9899 cells[i].init ();
99100 });
100101 numCells = 0 ;
@@ -107,9 +108,10 @@ struct grid {
107108 free (cells);
108109 free (cacheLocks);
109110 parallel_for (0 , cellCapacity, [&](intT i) {
110- if (nbrCache[i]) delete nbrCache[i];
111+ auto cached = nbrCache[i].load (std::memory_order_relaxed);
112+ if (cached) delete cached;
111113 });
112- free ( nbrCache) ;
114+ delete[] nbrCache;
113115 if (myHash) delete myHash;
114116 if (table) {
115117 table->del ();
@@ -147,22 +149,24 @@ struct grid {
147149 }
148150 return false ;};// todo, optimize
149151 int idx = bait - cells;
150- if (nbrCache[idx]) {
151- auto accum = nbrCache[idx];
152- for (auto accum_i : *accum) {
152+ // Acquire ensures vector contents are visible if pointer is non-null
153+ auto cached = nbrCache[idx].load (std::memory_order_acquire);
154+ if (cached) {
155+ for (auto accum_i : *cached) {
153156 if (fWrap (accum_i)) break ;
154157 }
155158 } else {
156- // wait for other threads to do their thing then try again
157159 std::lock_guard<std::mutex> lock (cacheLocks[idx]);
158- if ( nbrCache[idx]) {
159- auto accum = nbrCache[idx];
160- for (auto accum_i : *accum ) {
160+ cached = nbrCache[idx]. load (std::memory_order_relaxed);
161+ if (cached) {
162+ for (auto accum_i : *cached ) {
161163 if (fWrap (accum_i)) break ;
162164 }
163165 } else {
164166 floatT hop = sqrt (dim + 3 ) * 1.0000001 ;
165- nbrCache[idx] = tree->rangeNeighbor (bait, r * hop, fStop , fWrap , true , nbrCache[idx]);
167+ auto result = tree->rangeNeighbor (bait, r * hop, fStop , fWrap , true , (cellBuf*)nullptr );
168+ // Release ensures vector contents are fully written before pointer is visible
169+ nbrCache[idx].store (result, std::memory_order_release);
166170 }
167171 }
168172 }
@@ -176,22 +180,22 @@ struct grid {
176180 return false ;
177181 };
178182 int idx = bait - cells;
179- if ( nbrCache[idx]) {
180- auto accum = nbrCache[idx];
181- for (auto accum_i : *accum ) {
183+ auto cached = nbrCache[idx]. load (std::memory_order_acquire);
184+ if (cached) {
185+ for (auto accum_i : *cached ) {
182186 if (fWrap (accum_i)) break ;
183187 }
184188 } else {
185- // wait for other threads to do their thing then try again
186189 std::lock_guard<std::mutex> lock (cacheLocks[idx]);
187- if ( nbrCache[idx]) {
188- auto accum = nbrCache[idx];
189- for (auto accum_i : *accum ) {
190+ cached = nbrCache[idx]. load (std::memory_order_relaxed);
191+ if (cached) {
192+ for (auto accum_i : *cached ) {
190193 if (fWrap (accum_i)) break ;
191194 }
192195 } else {
193196 floatT hop = sqrt (dim + 3 ) * 1.0000001 ;
194- nbrCache[bait-cells] = tree->rangeNeighbor (bait, r * hop, fStop , fWrap , true , nbrCache[idx]);
197+ auto result = tree->rangeNeighbor (bait, r * hop, fStop , fWrap , true , (cellBuf*)nullptr );
198+ nbrCache[idx].store (result, std::memory_order_release);
195199 }
196200 }
197201 }
0 commit comments