Itasca C++ Interface
Loading...
Searching...
No Matches
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>
22class BASE_EXPORT SpinLock : public std::mutex {
23public:
24 using mutex::mutex;
25};
26#else
28public:
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
45private:
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.
55template <typename T>
57public:
58 ReverseLock(T &t) : lock_(t) { t.unlock(); }
59 ~ReverseLock() { lock_.lock(); }
60private:
61 T &lock_;
62};
63
64// Standard library looking ConditionalLock
65template <typename T>
67public:
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(); }
71private:
72 T *lock_;
73 bool use_;
74};
75
76// Standard library looking ReverseLock for people using lock_guard, unique_lock, etc.
77template <typename T>
79public:
80 ReverseSharedLock(T &t) : lock_(t) { t.unlock_shared(); }
81 ~ReverseSharedLock() { lock_.lock_shared(); }
82private:
83 T &lock_;
84};
85
86// Update Maximum
87template <typename T>
88void atomicMax(std::atomic<T> &maxValue, T const &value) noexcept {
89 T pvalue = maxValue.load();
90 while (pvalue < value and not maxValue.compare_exchange_weak(pvalue, value)) { }
91}
92
93// Update Minimum
94template <typename T>
95void atomicMin(std::atomic<T> &minValue, T const &value) noexcept {
96 T pvalue = minValue.load();
97 while (pvalue > value and not minValue.compare_exchange_weak(pvalue, value)) { }
98}
99
100// 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