proxygen
Mutex.h
Go to the documentation of this file.
1 /*
2  * Copyright 2018-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include <atomic>
19 #include <experimental/coroutine>
20 #include <mutex>
21 
22 namespace folly {
23 namespace coro {
24 
84 class Mutex {
85  class ScopedLockOperation;
86  class LockOperation;
87 
88  public:
91 
92  Mutex(const Mutex&) = delete;
93  Mutex(Mutex&&) = delete;
94  Mutex& operator=(const Mutex&) = delete;
95  Mutex& operator=(Mutex&&) = delete;
96 
97  ~Mutex();
98 
107  void* oldValue = unlockedState();
108  return state_.compare_exchange_strong(
109  oldValue,
110  nullptr,
111  std::memory_order_acquire,
112  std::memory_order_relaxed);
113  }
114 
129 
145  [[nodiscard]] LockOperation co_lock() noexcept;
146 
151  void unlock() noexcept;
152 
153  private:
155  public:
156  bool await_ready() noexcept {
157  return mutex_.try_lock();
158  }
159 
161  std::experimental::coroutine_handle<> awaitingCoroutine) noexcept {
162  awaitingCoroutine_ = awaitingCoroutine;
163  return mutex_.lockAsyncImpl(this);
164  }
165 
166  void await_resume() noexcept {}
167 
168  protected:
169  friend class Mutex;
170 
171  explicit LockOperation(Mutex& mutex) noexcept : mutex_(mutex) {}
172 
174  std::experimental::coroutine_handle<> awaitingCoroutine_;
176  };
177 
179  public:
180  std::unique_lock<Mutex> await_resume() noexcept {
181  return std::unique_lock<Mutex>{mutex_, std::adopt_lock};
182  }
183 
184  private:
185  friend class Mutex;
187  };
188 
189  friend class LockOperation;
190 
191  // Special value for state_ that indicates the mutex is not locked.
192  void* unlockedState() noexcept {
193  return this;
194  }
195 
196  // Try to lock the mutex.
197  //
198  // Returns true if the lock could not be acquired synchronously and awaiting
199  // coroutine should suspend. In this case the coroutine will be resumed later
200  // once it acquires the mutex. Returns false if the lock was acquired
201  // synchronously and the awaiting coroutine should continue without
202  // suspending.
203  bool lockAsyncImpl(LockOperation* awaiter);
204 
205  // This contains either:
206  // - this => Not locked
207  // - nullptr => Locked, no newly queued waiters (ie. empty list of waiters)
208  // - other => Pointer to first LockAwaiterBase* in a linked-list of newly
209  // queued awaiters in LIFO order.
210  std::atomic<void*> state_;
211 
212  // Linked-list of waiters in FIFO order.
213  // Only the current lock holder is allowed to access this member.
215 };
216 
218  return ScopedLockOperation{*this};
219 }
220 
222  return LockOperation{*this};
223 }
224 
225 } // namespace coro
226 } // namespace folly
LockOperation co_lock() noexcept
Definition: Mutex.h:221
std::atomic< void * > state_
Definition: Mutex.h:210
bool await_suspend(std::experimental::coroutine_handle<> awaitingCoroutine) noexcept
Definition: Mutex.h:160
LockOperation * waiters_
Definition: Mutex.h:214
bool await_ready() noexcept
Definition: Mutex.h:156
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
std::unique_lock< Mutex > await_resume() noexcept
Definition: Mutex.h:180
requires E e noexcept(noexcept(s.error(std::move(e))))
bool try_lock() noexcept
Definition: Mutex.h:106
Mutex() noexcept
Construct a new async mutex that is initially unlocked.
Definition: Mutex.h:90
void * unlockedState() noexcept
Definition: Mutex.h:192
Mutex & operator=(const Mutex &)=delete
void unlock() noexcept
std::mutex mutex
LockOperation(Mutex &mutex) noexcept
Definition: Mutex.h:171
ScopedLockOperation co_scoped_lock() noexcept
Definition: Mutex.h:217
bool lockAsyncImpl(LockOperation *awaiter)
void await_resume() noexcept
Definition: Mutex.h:166
std::experimental::coroutine_handle awaitingCoroutine_
Definition: Mutex.h:174