2 * Copyright 2017-present 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.
19 #include <folly/synchronization/ParkingLot.h>
21 #include <folly/portability/GTest.h>
22 #include <folly/synchronization/Baton.h>
24 using namespace folly;
26 TEST(ParkingLot, multilot) {
27 using SmallLot = ParkingLot<bool>;
28 using LargeLot = ParkingLot<uint64_t>;
34 std::thread small([&]() {
35 smalllot.park(0, false, [] { return true; }, [&]() { sb.post(); });
37 std::thread large([&]() {
38 largelot.park(0, true, [] { return true; }, [&]() { lb.post(); });
44 smalllot.unpark(0, [&](bool data) {
46 EXPECT_EQ(data, false);
47 return UnparkControl::RemoveContinue;
51 largelot.unpark(0, [&](bool data) {
53 EXPECT_EQ(data, true);
54 return UnparkControl::RemoveContinue;
62 // This is not possible to implement with Futex, because futex
63 // and the native linux syscall are 32-bit only.
64 TEST(ParkingLot, LargeWord) {
65 ParkingLot<uint64_t> lot;
66 std::atomic<uint64_t> w{0};
68 lot.park(0, false, [&]() { return w == 1; }, []() {});
70 // Validate should return false, will hang otherwise.
73 class WaitableMutex : public std::mutex {
74 using Lot = ParkingLot<std::function<bool(void)>>;
79 bool unparked = false;
80 lot.unpark(uint64_t(this), [&](std::function<bool(void)> wfunc) {
83 return UnparkControl::RemoveBreak;
85 return UnparkControl::RemoveContinue;
91 // Otherwise, we pass mutex directly to waiter without needing to unlock.
94 template <typename Wait>
95 void wait(Wait wfunc) {
99 [&]() { return !wfunc(); },
100 [&]() { std::mutex::unlock(); });
104 WaitableMutex::Lot WaitableMutex::lot;
106 TEST(ParkingLot, WaitableMutexTest) {
107 std::atomic<bool> go{false};
109 std::thread t([&]() {
110 std::lock_guard<WaitableMutex> g(mu);
111 mu.wait([&]() { return go == true; });
116 std::lock_guard<WaitableMutex> g(mu);