27 template <
typename WaitFunc>
29 std::unique_lock<folly::SpinLock>
ulock(
lock_);
35 const auto isOnFiber =
onFiber();
58 if (!waitFunc(waiter)) {
63 auto lockStolen = [&] {
64 std::lock_guard<folly::SpinLock> lg(
lock_);
94 template <
typename Rep,
typename Period>
96 const std::chrono::duration<Rep, Period>& duration) {
105 std::lock_guard<folly::SpinLock> lg(
lock_);
106 if (waiter.
hook.is_linked()) {
107 waiter.
hook.unlink();
128 std::lock_guard<folly::SpinLock> lg(
lock_);
137 std::lock_guard<folly::SpinLock> lg(
lock_);
141 to_wake.baton.post();
156 template <
typename BatonType>
158 std::unique_lock<folly::SpinLock>
ulock{
lock_};
159 if (state_ == State::WRITE_LOCKED) {
161 read_waiters_.push_back(waiter);
164 assert(state_ == State::READ_LOCKED);
168 (state_ == State::UNLOCKED && readers_ == 0) ||
169 (state_ == State::READ_LOCKED && readers_ > 0));
170 assert(read_waiters_.empty());
171 state_ = State::READ_LOCKED;
175 template <
typename BatonType>
176 template <
typename Rep,
typename Period>
178 const std::chrono::duration<Rep, Period>& duration) {
179 std::unique_lock<folly::SpinLock>
ulock{
lock_};
180 if (state_ == State::WRITE_LOCKED) {
182 read_waiters_.push_back(waiter);
185 if (!waiter.
baton.try_wait_for(duration)) {
192 if (waiter.
hook.is_linked()) {
193 read_waiters_.erase(read_waiters_.iterator_to(waiter));
200 (state_ == State::UNLOCKED && readers_ == 0) ||
201 (state_ == State::READ_LOCKED && readers_ > 0));
202 assert(read_waiters_.empty());
203 state_ = State::READ_LOCKED;
208 template <
typename BatonType>
211 if (state_ != State::WRITE_LOCKED) {
213 (state_ == State::UNLOCKED && readers_ == 0) ||
214 (state_ == State::READ_LOCKED && readers_ > 0));
215 assert(read_waiters_.empty());
216 state_ = State::READ_LOCKED;
223 template <
typename BatonType>
225 std::unique_lock<folly::SpinLock>
ulock{
lock_};
226 if (state_ == State::UNLOCKED) {
227 verify_unlocked_properties();
228 state_ = State::WRITE_LOCKED;
232 write_waiters_.push_back(waiter);
237 template <
typename BatonType>
238 template <
typename Rep,
typename Period>
240 const std::chrono::duration<Rep, Period>& duration) {
241 std::unique_lock<folly::SpinLock>
ulock{
lock_};
242 if (state_ == State::UNLOCKED) {
243 verify_unlocked_properties();
244 state_ = State::WRITE_LOCKED;
248 write_waiters_.push_back(waiter);
251 if (!waiter.
baton.try_wait_for(duration)) {
258 if (waiter.
hook.is_linked()) {
259 write_waiters_.erase(write_waiters_.iterator_to(waiter));
263 assert(state_ == State::WRITE_LOCKED);
267 template <
typename BatonType>
270 if (state_ == State::UNLOCKED) {
271 verify_unlocked_properties();
272 state_ = State::WRITE_LOCKED;
278 template <
typename BatonType>
281 assert(state_ != State::UNLOCKED);
283 (state_ == State::READ_LOCKED && readers_ > 0) ||
284 (state_ == State::WRITE_LOCKED && readers_ == 0));
285 if (state_ == State::READ_LOCKED) {
289 if (!read_waiters_.empty()) {
291 state_ == State::WRITE_LOCKED && readers_ == 0 &&
292 "read waiters can only accumulate while write locked");
293 state_ = State::READ_LOCKED;
294 readers_ = read_waiters_.size();
296 while (!read_waiters_.empty()) {
298 read_waiters_.pop_front();
299 to_wake.
baton.post();
301 }
else if (readers_ == 0) {
302 if (!write_waiters_.empty()) {
303 assert(read_waiters_.empty());
304 state_ = State::WRITE_LOCKED;
308 write_waiters_.pop_front();
309 to_wake.
baton.post();
311 verify_unlocked_properties();
312 state_ = State::UNLOCKED;
315 assert(state_ == State::READ_LOCKED);
319 template <
typename BatonType>
322 assert(state_ == State::WRITE_LOCKED && readers_ == 0);
323 state_ = State::READ_LOCKED;
326 if (!read_waiters_.empty()) {
327 readers_ += read_waiters_.size();
329 while (!read_waiters_.empty()) {
331 read_waiters_.pop_front();
332 to_wake.
baton.post();
bool timed_read_lock(const std::chrono::duration< Rep, Period > &duration)
bool timed_write_lock(const std::chrono::duration< Rep, Period > &duration)
MutexWaiterList fiberWaiters_
folly::IntrusiveListHook hook
—— Concurrent Priority Queue Implementation ——
FOLLY_ALWAYS_INLINE void assume_unreachable()
GuardImpl guard(ErrorHandler &&handler)
LockResult lockHelper(WaitFunc &&waitFunc)
MutexWaiterList threadWaiters_
auto ulock(Synchronized< D, M > &synchronized, Args &&...args)
bool timed_lock(const std::chrono::duration< Rep, Period > &duration)
MutexWaiter * notifiedFiber_
bool try_wait_for(const std::chrono::duration< Rep, Period > &timeout)