proxygen
ParkingLotTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017-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 <thread>
18 
20 
23 
24 using namespace folly;
25 
26 TEST(ParkingLot, multilot) {
27  using SmallLot = ParkingLot<bool>;
28  using LargeLot = ParkingLot<uint64_t>;
29  SmallLot smalllot;
30  LargeLot largelot;
31  folly::Baton<> sb;
32  folly::Baton<> lb;
33 
34  std::thread small([&]() {
35  smalllot.park(0, false, [] { return true; }, [&]() { sb.post(); });
36  });
37  std::thread large([&]() {
38  largelot.park(0, true, [] { return true; }, [&]() { lb.post(); });
39  });
40  sb.wait();
41  lb.wait();
42 
43  int count = 0;
44  smalllot.unpark(0, [&](bool data) {
45  count++;
46  EXPECT_EQ(data, false);
48  });
49  EXPECT_EQ(count, 1);
50  count = 0;
51  largelot.unpark(0, [&](bool data) {
52  count++;
53  EXPECT_EQ(data, true);
55  });
56  EXPECT_EQ(count, 1);
57 
58  small.join();
59  large.join();
60 }
61 
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) {
66  std::atomic<uint64_t> w{0};
67 
68  lot.park(0, false, [&]() { return w == 1; }, []() {});
69 
70  // Validate should return false, will hang otherwise.
71 }
72 
73 class WaitableMutex : public std::mutex {
75  static Lot lot;
76 
77  public:
78  void unlock() {
79  bool unparked = false;
80  lot.unpark(uint64_t(this), [&](std::function<bool(void)> wfunc) {
81  if (wfunc()) {
82  unparked = true;
84  } else {
86  }
87  });
88  if (!unparked) {
89  std::mutex::unlock();
90  }
91  // Otherwise, we pass mutex directly to waiter without needing to unlock.
92  }
93 
94  template <typename Wait>
95  void wait(Wait wfunc) {
96  lot.park(
97  uint64_t(this),
98  wfunc,
99  [&]() { return !wfunc(); },
100  [&]() { std::mutex::unlock(); });
101  }
102 };
103 
105 
106 TEST(ParkingLot, WaitableMutexTest) {
107  if (kIsSanitizeThread) {
108  return;
109  }
110  std::atomic<bool> go{false};
111  WaitableMutex mu;
112  std::thread t([&]() {
113  std::lock_guard<WaitableMutex> g(mu);
114  mu.wait([&]() { return go == true; });
115  });
116  sleep(1);
117 
118  {
119  std::lock_guard<WaitableMutex> g(mu);
120  go = true;
121  }
122  t.join();
123 }
void wait(Wait wfunc)
constexpr bool kIsSanitizeThread
Definition: Portability.h:124
static Lot lot
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
void unpark(const Key key, Unparker &&func)
auto large
Future< Unit > sleep(Duration dur, Timekeeper *tk)
Definition: Future.cpp:42
ParkingLot lot
ParkResult park(const Key key, D &&data, ToPark &&toPark, PreWait &&preWait)
Definition: ParkingLot.h:189
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
auto small
FOLLY_ALWAYS_INLINE void wait(const WaitOptions &opt=wait_options()) noexcept
Definition: Baton.h:170
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
void post() noexcept
Definition: Baton.h:123
int * count
std::mutex mutex
g_t g(f_t)
TEST(SequencedExecutor, CPUThreadPoolExecutor)