2 * Copyright 2016 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include "Semaphore.h"
21 bool Semaphore::signalSlow() {
22 // If we signalled a release, notify the waitlist
23 SYNCHRONIZED(waitList_) {
24 auto testVal = tokens_.load(std::memory_order_acquire);
29 if (waitList_.empty()) {
30 // If the waitlist is now empty, ensure the token count increments
31 // No need for CAS here as we will always be under the mutex
32 CHECK(tokens_.compare_exchange_strong(
33 testVal, testVal + 1, std::memory_order_relaxed));
35 // trigger waiter if there is one
36 waitList_.front()->post();
39 } // SYNCHRONIZED(waitList_)
43 void Semaphore::signal() {
44 auto oldVal = tokens_.load(std::memory_order_acquire);
51 } while (!tokens_.compare_exchange_weak(
54 std::memory_order_release,
55 std::memory_order_acquire));
58 bool Semaphore::waitSlow() {
59 // Slow path, create a baton and acquire a mutex to update the wait list
60 folly::fibers::Baton waitBaton;
62 SYNCHRONIZED(waitList_) {
63 auto testVal = tokens_.load(std::memory_order_acquire);
67 // prepare baton and add to queue
68 waitList_.push(&waitBaton);
70 // If we managed to create a baton, wait on it
71 // This has to be done here so the mutex has been released
76 void Semaphore::wait() {
77 auto oldVal = tokens_.load(std::memory_order_acquire);
80 // If waitSlow fails it is because the token is non-zero by the time
81 // the lock is taken, so we can just continue round the loop
86 } while (!tokens_.compare_exchange_weak(
89 std::memory_order_release,
90 std::memory_order_acquire));