Itasca C++ Interface
spinlock.h
1 #pragma once
2 
3 #include "basedef.h"
4 #include <cassert>
5 #include <atomic>
6 
7 // Spinlock implementation that matches std::mutex interface.
8 // So you can use std::lock_guard, etc.
9 //
10 // I'm aware of all the discussions of why SpinLocks are bad.
11 // The fact remains that timing tests consistently show
12 // F3 slows down considerably if you replace this with std::mutex.
13 // That said - BE CAREFUL because in medium-to-high contention scenarios this does not perform well.
14 
15 // If you define this, then the SpinLock is implemented in terms of a std::mutex
16 // shoudl be equivalent to std::mutex
17 //#define USEMUTEX
18 
19 
20 #ifdef USEMUTEX
21 #include <mutex>
22 class BASE_EXPORT SpinLock : public std::mutex {
23 public:
24  using mutex::mutex;
25 };
26 #else
28 public:
30  SpinLock() { new(buffer) std::atomic<bool>(false); }
31  SpinLock(const SpinLock &) { new(buffer) std::atomic<bool>(false); }
32  SpinLock(SpinLock &&) { new(buffer) std::atomic<bool>(false); }
33 
35  ~SpinLock() { assert(!get().load()); get().~atomic<bool>(); }
36 
38  inline void lock() { while (get().exchange(true)) { } };
39 
41  inline void unlock() { get().store(false); } // Added for standard conformity
42 
43  inline bool try_lock() { return !get().exchange(true); } // Added for standard conformity
44 
45 private:
46  void operator=(const SpinLock &) = delete;
47 
48  std::atomic<bool> &get() { return *reinterpret_cast<std::atomic<bool> *>(buffer); }
49 
50  char buffer[sizeof(std::atomic<bool>)];
51 };
52 #endif
53 
54 // Standard library looking ReverseLock for people using lock_guard, unique_lock, etc.
55 template <typename T>
56 class ReverseLock {
57 public:
58  ReverseLock(T &t) : lock_(t) { t.unlock(); }
59  ~ReverseLock() { lock_.lock(); }
60 private:
61  T &lock_;
62 };
63 
64 // Standard library looking ConditionalLock
65 template <typename T>
67 public:
68  ConditionalLock(T &t, bool use) : lock_(&t), use_(use) { if (use_) t.lock(); }
69  ConditionalLock(T *t, bool use) : lock_(t), use_(use) { if (use_&&t) t->lock(); }
70  ~ConditionalLock() { if (use_&&lock_) lock_->unlock(); }
71 private:
72  T *lock_;
73  bool use_;
74 };
75 
76 // Standard library looking ReverseLock for people using lock_guard, unique_lock, etc.
77 template <typename T>
79 public:
80  ReverseSharedLock(T &t) : lock_(t) { t.unlock_shared(); }
81  ~ReverseSharedLock() { lock_.lock_shared(); }
82 private:
83  T &lock_;
84 };
85 
86 
87 
88 // EoF
Base type definitions for the engine.
Definition: spinlock.h:66
Definition: spinlock.h:56
Definition: spinlock.h:78
Definition: spinlock.h:27
void unlock()
Release the lock.
Definition: spinlock.h:41
void lock()
Acquire a lock using the test-and-set paradigm.
Definition: spinlock.h:38
SpinLock()
By default the QAtomicInt is 0 on creation.
Definition: spinlock.h:30
~SpinLock()
A SpinLock object can only be destroyed when it has been released.
Definition: spinlock.h:35
#define BASE_EXPORT
Definition: basedef.h:24