3
3
#include < assert.h>
4
4
5
5
#include < algorithm>
6
- #include < atomic> // for std::atomic_thread_fence
7
6
8
- #include < windows.h>
9
7
10
8
namespace
11
9
{
@@ -251,14 +249,14 @@ bool CScanFile::LockFreecInit()
251
249
return false ;
252
250
}
253
251
254
- this ->_threadFinishSpinlock = false ;
255
- this ->_threadOperationReadStartSpinlock = false ;
256
- this ->_threadOperationReadCompletedSpinlock = false ;
252
+ this ->_threadFinishSpinlock . store ( false , std::memory_order_relaxed) ;
253
+ this ->_threadOperationReadStartSpinlock . store ( false , std::memory_order_relaxed) ;
254
+ this ->_threadOperationReadCompletedSpinlock . store ( false , std::memory_order_relaxed) ;
257
255
this ->_pThreadReadBuffer = nullptr ;
258
256
this ->_threadReadBufferSize = 0 ;
259
257
this ->_threadActuallyReadBytes = 0 ;
260
258
this ->_threadReadSucceeded = false ;
261
- std::atomic_thread_fence (std::memory_order_release);
259
+ // no need to synchronize before worker thread is started
262
260
263
261
// This is a dirty hack for speedup inter-thread communication on hyperthreading CPUs
264
262
#if ENABLE_THREAD_PREFERRED_AFFINITY
@@ -305,7 +303,7 @@ void CScanFile::LockFreecClean()
305
303
{
306
304
if (this ->_hThread != nullptr )
307
305
{
308
- this ->_threadFinishSpinlock = true ;
306
+ this ->_threadFinishSpinlock . store ( true , std::memory_order_relaxed); // we won't reorder after WaitForSingleObject
309
307
WaitForSingleObject (this ->_hThread , INFINITE); // ignore return value in this case
310
308
this ->_hThread = nullptr ;
311
309
}
@@ -318,17 +316,17 @@ bool CScanFile::LockFreeReadStart(char* const buffer, const size_t bufferLength)
318
316
{
319
317
return false ;
320
318
}
321
-
322
319
this ->_threadOperationInProgress = true ;
323
- this ->_threadOperationReadCompletedSpinlock = false ;
320
+
321
+ assert (this ->_threadOperationReadStartSpinlock .load (std::memory_order_relaxed) == false );
322
+ assert (this ->_threadOperationReadCompletedSpinlock .load (std::memory_order_relaxed) == false );
323
+
324
324
this ->_pThreadReadBuffer = buffer;
325
325
this ->_threadReadBufferSize = bufferLength;
326
326
this ->_threadActuallyReadBytes = 0 ;
327
327
this ->_threadReadSucceeded = false ;
328
- std::atomic_thread_fence (std::memory_order_release);
329
328
330
- this ->_threadOperationReadStartSpinlock = true ;
331
- std::atomic_thread_fence (std::memory_order_release);
329
+ this ->_threadOperationReadStartSpinlock .store (true , std::memory_order_release);
332
330
333
331
return true ;
334
332
}
@@ -340,18 +338,18 @@ bool CScanFile::LockFreeReadWait(size_t& readBytes)
340
338
{
341
339
return false ;
342
340
}
343
-
344
341
this ->_threadOperationInProgress = false ;
345
- std::atomic_thread_fence (std::memory_order_release);
346
342
347
- std::atomic_thread_fence (std::memory_order_acquire);
348
- while (! this -> _threadOperationReadCompletedSpinlock )
343
+ // Wait for _threadOperationReadCompletedSpinlock == True and reset it:
344
+ while (true )
349
345
{
350
- // nothing
351
- std::atomic_thread_fence (std::memory_order_acquire);
346
+ bool operationCompleted = true ;
347
+ if (this ->_threadOperationReadCompletedSpinlock .compare_exchange_weak (operationCompleted, false , std::memory_order_acquire, std::memory_order_relaxed))
348
+ {
349
+ break ;
350
+ }
352
351
}
353
352
354
- std::atomic_thread_fence (std::memory_order_acquire);
355
353
readBytes = this ->_threadActuallyReadBytes ;
356
354
if (!this ->_threadReadSucceeded )
357
355
{
@@ -365,31 +363,27 @@ void CScanFile::LockFreeThreadProc()
365
363
{
366
364
while (true )
367
365
{
368
- std::atomic_thread_fence (std::memory_order_acquire);
369
- if (this ->_threadFinishSpinlock )
366
+ if (this ->_threadFinishSpinlock .load (std::memory_order_relaxed))
370
367
{
371
368
// thread exit signal is caught
372
369
break ;
373
370
}
374
371
375
- if (!this ->_threadOperationReadStartSpinlock )
372
+ // Check for _threadOperationReadStartSpinlock == True and reset it:
373
+ bool operationStarted = true ;
374
+ if (!this ->_threadOperationReadStartSpinlock .compare_exchange_weak (operationStarted, false , std::memory_order_acquire, std::memory_order_relaxed))
376
375
{
377
376
// nothing to do
378
377
continue ;
379
378
}
380
379
381
- std::atomic_thread_fence (std::memory_order_acquire);
382
-
383
380
size_t readBytes = 0 ;
384
381
const bool readOk = this ->Read (this ->_pThreadReadBuffer , this ->_threadReadBufferSize , readBytes);
385
382
386
- this ->_threadOperationReadStartSpinlock = false ;
387
383
this ->_threadActuallyReadBytes = readBytes;
388
384
this ->_threadReadSucceeded = readOk;
389
- std::atomic_thread_fence (std::memory_order_release);
390
385
391
- this ->_threadOperationReadCompletedSpinlock = true ;
392
- std::atomic_thread_fence (std::memory_order_release);
386
+ this ->_threadOperationReadCompletedSpinlock .store (true , std::memory_order_release);
393
387
}
394
388
}
395
389
0 commit comments