proxygen
Baton.cpp
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 
17 #include <folly/Portability.h>
18 
19 #if FOLLY_HAS_COROUTINES
20 
22 
23 #include <cassert>
24 
25 using namespace folly::coro;
26 
27 Baton::~Baton() {
28  // Should not be any waiting coroutines when the baton is destruced.
29  // Caller should ensure the baton is posted before destructing.
30  assert(
31  state_.load(std::memory_order_relaxed) == static_cast<void*>(this) ||
32  state_.load(std::memory_order_relaxed) == nullptr);
33 }
34 
35 void Baton::post() noexcept {
36  void* signalledState = static_cast<void*>(this);
37  void* oldValue = state_.exchange(signalledState, std::memory_order_acq_rel);
38  if (oldValue != signalledState && oldValue != nullptr) {
39  // We are the first thread to set the state to signalled and there is
40  // a waiting coroutine. We are responsible for resuming it.
41  WaitOperation* awaiter = static_cast<WaitOperation*>(oldValue);
42  awaiter->awaitingCoroutine_.resume();
43  }
44 }
45 
46 bool Baton::waitImpl(WaitOperation* awaiter) const noexcept {
47  void* oldValue = nullptr;
48  if (!state_.compare_exchange_strong(
49  oldValue,
50  static_cast<void*>(awaiter),
51  std::memory_order_release,
52  std::memory_order_acquire)) {
53  // If the compare-exchange fails it should be because the baton was
54  // set to the signalled state. If this not the case then this could
55  // indicate that there are two awaiting coroutines.
56  assert(oldValue == static_cast<const void*>(this));
57  return false;
58  }
59  return true;
60 }
61 
62 #endif // FOLLY_HAS_COROUTINES
bool waitImpl(WaitOperation *awaiter) const noexcept
requires E e noexcept(noexcept(s.error(std::move(e))))
void post() noexcept
std::atomic< void * > state_
Definition: Baton.h:129