Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
SpinLock.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include <thread>
5
7
8 /*
9 ********************************************************************************
10 ******************************** Execution::SpinLock ***************************
11 ********************************************************************************
12 */
14 : fBarrierFlag_{barrier}
15 {
16 }
17 inline bool SpinLock::try_lock ()
18 {
19 /*
20 * NOTE: I don't understand why memory_order_acquire is good enough here since if
21 * we make change we need to make sure its published to other threads.
22 *
23 * But - the example on http://en.cppreference.com/w/cpp/atomic/atomic_flag_test_and_set shows
24 * while (atomic_flag_test_and_set_explicit (&lock, memory_order_acquire))
25 * ; // spin until the lock is acquired
26 */
27 bool result = not fLock_.test_and_set (memory_order_acquire);
28 if (result) {
29 DISABLE_COMPILER_GCC_WARNING_START ("GCC diagnostic ignored \"-Wtsan\""); // Needed in g++-13 and later, it appears, with --sanitize=thread, but so far no obvious real problems
30 /*
31 * See http://stroika-bugs.sophists.com/browse/STK-494 for notes on why this is right (using eReleaseAcquire/memory_order_acquire)
32 */
33 switch (fBarrierFlag_) {
34 case BarrierType::eReleaseAcquire:
35 atomic_thread_fence (memory_order_acquire);
36 break;
37 case BarrierType::eMemoryTotalOrder:
38 atomic_thread_fence (memory_order_seq_cst);
39 break;
40 default:
41 break;
42 }
43 DISABLE_COMPILER_GCC_WARNING_END ("GCC diagnostic ignored \"-Wtsan\"");
44 }
45 return result;
46 }
47 inline void SpinLock::lock ()
48 {
49 // Acquire lock. If / when fails, yield processor to avoid too much busy waiting.
50 while (not try_lock ()) {
51 this_thread::yield (); // nb: until Stroika v2.0a209, this called Execution::Yield (), making this a cancelation point. That is principally bad because it makes SpinLock not interchangeable with mutex
52 }
53 }
54 inline void SpinLock::unlock ()
55 {
56 // See notes in try_lock () for cooresponding thread_fence calls()
57 DISABLE_COMPILER_GCC_WARNING_START ("GCC diagnostic ignored \"-Wtsan\""); // Needed in g++-13 and later, it appears, with --sanitize=thread, but so far no obvious real problems
58 switch (fBarrierFlag_) {
59 case BarrierType::eReleaseAcquire:
60 atomic_thread_fence (memory_order_release);
61 break;
62 case BarrierType::eMemoryTotalOrder:
63 atomic_thread_fence (memory_order_seq_cst);
64 break;
65 default:
66 break;
67 }
68 DISABLE_COMPILER_GCC_WARNING_END ("GCC diagnostic ignored \"-Wtsan\""); // Needed in g++-13 and later, it appears, with --sanitize=thread, but so far no obvious real problems
69 // release lock
70 fLock_.clear (memory_order_release);
71 }
72
73}
SpinLock(BarrierType barrier=BarrierType::eDEFAULT)
Definition SpinLock.inl:13