-
Notifications
You must be signed in to change notification settings - Fork 0
/
SharedMutex.hpp
173 lines (145 loc) · 5.35 KB
/
SharedMutex.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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/**
* 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_SHARED_MUTEX_HPP_
#define QUICKSTEP_THREADING_SHARED_MUTEX_HPP_
#include "threading/Mutex.hpp"
#include "threading/ThreadingConfig.h"
#include "utility/Macros.hpp"
namespace quickstep {
/** \addtogroup Threading
* @{
*/
/**
* @brief A shared mutex, also known as an RW-lock. May be locked in exclusive
* (write) mode, which prevents any other thread from locking, or shared
* (read) mode, which allows an unlimited number of threads to share the
* mutex, so long as none are in exclusive mode.
* @note This interface exists to provide a central point of documentation for
* platform-specific SharedMutex implementations, you should never use it
* directly. Instead, simply use the SharedMutex class, which will be
* typedefed to the appropriate implementation.
**/
class SharedMutexInterface : public MutexInterface {
public:
/**
* @brief Lock this mutex in shared mode. If the mutex is locked in exclusive
* mode by another thread, execution will block until the mutex
* becomes available. Any number of threads may simultaneously lock
* the mutex in shared mode.
**/
virtual void lockShared() = 0;
/**
* @brief Release a shared-mode lock on this mutex. It is an error to call
* this from a thread that does not hold a shared-mode lock on this
* mutex.
**/
virtual void unlockShared() = 0;
};
/** @} */
} // namespace quickstep
#ifdef QUICKSTEP_HAVE_CPP11_THREADS
# if defined(QUICKSTEP_HAVE_CPP17_SHARED_MUTEX)
# include "threading/cpp11/cpp17/SharedMutex.hpp"
# elif defined(QUICKSTEP_HAVE_CPP14_SHARED_TIMED_MUTEX)
# include "threading/cpp11/cpp14/SharedMutex.hpp"
# else
# include "threading/cpp11/SharedMutex.hpp"
# endif
#endif
#ifdef QUICKSTEP_HAVE_POSIX_THREADS
#include "threading/posix/SharedMutex.hpp"
#endif
#ifdef QUICKSTEP_HAVE_WINDOWS_THREADS
#include "threading/windows/SharedMutex.hpp"
#endif
namespace quickstep {
/** \addtogroup Threading
* @{
*/
/**
* @brief A scoped exclusive lock-holder for a SharedMutex. Locks a SharedMutex
* in exclusive mode when it is constructed, and unlocks when it goes
* out of scope.
**/
typedef MutexLockImpl<SharedMutex, true> SharedMutexExclusiveLock;
template <bool actually_lock> using StaticConditionalSharedMutexExclusiveLock
= MutexLockImpl<SharedMutex, actually_lock>;
typedef DynamicConditionalMutexLockImpl<SharedMutex>
DynamicConditionalSharedMutexExclusiveLock;
/**
* @brief A scoped shared lock-holder for a SharedMutex. Locks a SharedMutex in
* shared mode when it is constructed, and unlocks when it goes out of
* scope.
**/
template <typename SharedMutexT, bool actually_lock>
class SharedMutexSharedLockImpl {
public:
explicit inline SharedMutexSharedLockImpl(SharedMutexT &mutex) // NOLINT(runtime/references)
: mutex_ptr_(&mutex) {
if (actually_lock) {
mutex_ptr_->lockShared();
}
}
inline ~SharedMutexSharedLockImpl() {
if (actually_lock) {
mutex_ptr_->unlockShared();
}
}
private:
SharedMutexT *mutex_ptr_;
DISALLOW_COPY_AND_ASSIGN(SharedMutexSharedLockImpl);
};
// Partial specialization: do nothing and store nothing if actually_lock = false.
template <typename SharedMutexT>
class SharedMutexSharedLockImpl<SharedMutexT, false> {
public:
explicit inline SharedMutexSharedLockImpl(SharedMutexT &mutex) { // NOLINT(runtime/references)
}
private:
DISALLOW_COPY_AND_ASSIGN(SharedMutexSharedLockImpl);
};
template <typename SharedMutexT>
class DynamicConditionalSharedMutexSharedLockImpl {
public:
inline DynamicConditionalSharedMutexSharedLockImpl(SharedMutexT &mutex, // NOLINT(runtime/references)
const bool actually_lock)
: mutex_ptr_(&mutex),
actually_lock_(actually_lock) {
if (actually_lock_) {
mutex_ptr_->lockShared();
}
}
inline ~DynamicConditionalSharedMutexSharedLockImpl() {
if (actually_lock_) {
mutex_ptr_->unlockShared();
}
}
private:
SharedMutexT *mutex_ptr_;
const bool actually_lock_;
DISALLOW_COPY_AND_ASSIGN(DynamicConditionalSharedMutexSharedLockImpl);
};
typedef SharedMutexSharedLockImpl<SharedMutex, true> SharedMutexSharedLock;
template <bool actually_lock> using StaticConditionalSharedMutexSharedLock
= SharedMutexSharedLockImpl<SharedMutex, actually_lock>;
typedef DynamicConditionalSharedMutexSharedLockImpl<SharedMutex>
DynamicConditionalSharedMutexSharedLock;
/** @} */
} // namespace quickstep
#endif // QUICKSTEP_THREADING_SHARED_MUTEX_HPP_