-
Notifications
You must be signed in to change notification settings - Fork 10
/
SpinMutex.hpp
83 lines (69 loc) · 2.63 KB
/
SpinMutex.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
**/
#ifndef QUICKSTEP_THREADING_SPIN_MUTEX_HPP_
#define QUICKSTEP_THREADING_SPIN_MUTEX_HPP_
#include <atomic>
#include "threading/Mutex.hpp"
#include "utility/Macros.hpp"
namespace quickstep {
/** \addtogroup Threading
* @{
*/
/**
* @brief Mutex implementation as a pure user-space spinlock. May be more
* efficient than an ordinary Mutex if locks are usually held briefly.
*
* @note Unlike a regular Mutex, SpinMutex can not create condition variables.
* @note In some cases, SpinMutex will perform better if it is aligned on its
* own cache line to avoid false sharing.
**/
class SpinMutex {
public:
SpinMutex() : locked_(false) {
}
/**
* @note This call does NOT yield when contended. SpinMutex is intended
* mainly for cases where locks are held briefly and it is better to
* simply spin for a short time rather than involving the kernel's
* scheduler. Otherwise, a regular Mutex (using the futex mechanism on
* Linux) is a more appropriate choice.
**/
inline void lock() {
bool previous_locked = false;
while (!locked_.compare_exchange_weak(previous_locked,
true,
std::memory_order_acquire,
std::memory_order_relaxed)) {
previous_locked = false;
}
}
inline void unlock() {
locked_.store(false, std::memory_order_release);
}
private:
std::atomic<bool> locked_;
DISALLOW_COPY_AND_ASSIGN(SpinMutex);
};
typedef MutexLockImpl<SpinMutex, true> SpinMutexLock;
template <bool actually_lock> using StaticConditionalSpinMutexLock
= MutexLockImpl<SpinMutex, actually_lock>;
typedef DynamicConditionalMutexLockImpl<SpinMutex> DynamicConditionalSpinMutexLock;
/** @} */
} // namespace quickstep
#endif // QUICKSTEP_THREADING_SPIN_MUTEX_HPP_