proxygen
SaturatingSemaphoreTest.cpp File Reference

Go to the source code of this file.

Typedefs

using DSched = folly::test::DeterministicSchedule
 

Functions

template<bool MayBlock, template< typename > class Atom = std::atomic>
void run_basic_test ()
 
template<bool MayBlock, template< typename > class Atom = std::atomic>
void run_pingpong_test (int numRounds)
 
template<bool MayBlock, template< typename > class Atom = std::atomic>
void run_multi_poster_multi_waiter_test (int np, int nw)
 
 TEST (SaturatingSemaphore, basic_spin_only)
 Tests. More...
 
 TEST (SaturatingSemaphore, basic_may_block)
 
 TEST (SaturatingSemaphore, pingpong_spin_only)
 
 TEST (SaturatingSemaphore, pingpong_may_block)
 
 TEST (SaturatingSemaphore, multi_poster_multi_waiter_spin_only)
 
 TEST (SaturatingSemaphore, multi_poster_multi_waiter_may_block)
 

Typedef Documentation

Function Documentation

template<bool MayBlock, template< typename > class Atom = std::atomic>
void run_basic_test ( )

Definition at line 27 of file SaturatingSemaphoreTest.cpp.

References ASSERT_FALSE, ASSERT_TRUE, Atom, f, now(), folly::SaturatingSemaphore< MayBlock, Atom >::post(), folly::SaturatingSemaphore< MayBlock, Atom >::ready(), folly::SaturatingSemaphore< MayBlock, Atom >::reset(), folly::SaturatingSemaphore< MayBlock, Atom >::try_wait(), folly::SaturatingSemaphore< MayBlock, Atom >::try_wait_until(), folly::SaturatingSemaphore< MayBlock, Atom >::wait(), and folly::SaturatingSemaphore< MayBlock, Atom >::wait_options().

27  {
29  ASSERT_FALSE(f.ready());
32  std::chrono::steady_clock::now() + std::chrono::microseconds(1)));
34  std::chrono::steady_clock::now() + std::chrono::microseconds(1),
35  f.wait_options().spin_max(std::chrono::microseconds(1))));
36  f.post();
37  f.post();
38  f.wait();
39  f.wait(f.wait_options().spin_max(std::chrono::nanoseconds(100)));
40  ASSERT_TRUE(f.ready());
41  ASSERT_TRUE(f.try_wait());
43  std::chrono::steady_clock::now() + std::chrono::microseconds(1)));
44  f.wait();
45  f.reset();
47 }
FOLLY_ALWAYS_INLINE bool ready() const noexcept
FOLLY_ALWAYS_INLINE void wait(const WaitOptions &opt=wait_options()) noexcept
auto f
std::chrono::steady_clock::time_point now()
static FOLLY_ALWAYS_INLINE WaitOptions wait_options()
FOLLY_ALWAYS_INLINE void post() noexcept
FOLLY_ALWAYS_INLINE bool try_wait_until(const std::chrono::time_point< Clock, Duration > &deadline, const WaitOptions &opt=wait_options()) noexcept
FOLLY_ALWAYS_INLINE bool try_wait() noexcept
#define ASSERT_FALSE(condition)
Definition: gtest.h:1868
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
template<bool MayBlock, template< typename > class Atom = std::atomic>
void run_multi_poster_multi_waiter_test ( int  np,
int  nw 
)

Definition at line 73 of file SaturatingSemaphoreTest.cpp.

References ASSERT_FALSE, ASSERT_TRUE, f, i, folly::test::DeterministicSchedule::join(), now(), folly::SaturatingSemaphore< MayBlock, Atom >::post(), folly::SaturatingSemaphore< MayBlock, Atom >::ready(), folly::pushmi::detail::t, folly::test::DeterministicSchedule::thread(), folly::SaturatingSemaphore< MayBlock, Atom >::try_wait(), folly::SaturatingSemaphore< MayBlock, Atom >::try_wait_for(), folly::SaturatingSemaphore< MayBlock, Atom >::try_wait_until(), folly::SaturatingSemaphore< MayBlock, Atom >::wait(), and folly::SaturatingSemaphore< MayBlock, Atom >::wait_options().

73  {
75  std::atomic<int> posted{0};
76  std::atomic<int> waited{0};
77  std::atomic<bool> go_post{false};
78  std::atomic<bool> go_wait{false};
79 
80  std::vector<std::thread> prod(np);
81  std::vector<std::thread> cons(nw);
82  for (int i = 0; i < np; ++i) {
83  prod[i] = DSched::thread([&] {
84  while (!go_post.load()) {
85  /* spin */;
86  }
87  f.post();
88  posted.fetch_add(1);
89  });
90  }
91 
92  for (int i = 0; i < nw; ++i) {
93  cons[i] = DSched::thread([&] {
94  ASSERT_FALSE(f.ready());
96  ASSERT_FALSE(f.try_wait_for(std::chrono::microseconds(1)));
98  std::chrono::steady_clock::now() + std::chrono::microseconds(1)));
100  std::chrono::steady_clock::now() + std::chrono::microseconds(1),
101  f.wait_options().spin_max(std::chrono::microseconds(0))));
102  waited.fetch_add(1);
103  while (!go_wait.load()) {
104  /* spin */;
105  }
106  ASSERT_TRUE(f.ready());
107  ASSERT_TRUE(f.try_wait());
108  ASSERT_TRUE(f.try_wait_for(std::chrono::microseconds(1)));
110  std::chrono::steady_clock::now() + std::chrono::microseconds(1)));
112  std::chrono::steady_clock::now() + std::chrono::microseconds(1),
113  f.wait_options().spin_max(std::chrono::microseconds(0))));
114  f.wait();
115  });
116  }
117 
118  while (waited.load() < nw) {
119  /* spin */;
120  }
121  go_post.store(true);
122  while (posted.load() < np) {
123  /* spin */;
124  }
125  go_wait.store(true);
126 
127  for (auto& t : prod) {
128  DSched::join(t);
129  }
130  for (auto& t : cons) {
131  DSched::join(t);
132  }
133 }
FOLLY_ALWAYS_INLINE bool ready() const noexcept
FOLLY_ALWAYS_INLINE void wait(const WaitOptions &opt=wait_options()) noexcept
auto f
std::chrono::steady_clock::time_point now()
static std::thread thread(Func &&func, Args &&...args)
static FOLLY_ALWAYS_INLINE WaitOptions wait_options()
FOLLY_ALWAYS_INLINE void post() noexcept
FOLLY_ALWAYS_INLINE bool try_wait_until(const std::chrono::time_point< Clock, Duration > &deadline, const WaitOptions &opt=wait_options()) noexcept
FOLLY_ALWAYS_INLINE bool try_wait_for(const std::chrono::duration< Rep, Period > &duration, const WaitOptions &opt=wait_options()) noexcept
FOLLY_ALWAYS_INLINE bool try_wait() noexcept
#define ASSERT_FALSE(condition)
Definition: gtest.h:1868
static void join(std::thread &child)
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
template<bool MayBlock, template< typename > class Atom = std::atomic>
void run_pingpong_test ( int  numRounds)

Definition at line 50 of file SaturatingSemaphoreTest.cpp.

References a, Atom, b, i, folly::test::DeterministicSchedule::join(), and folly::test::DeterministicSchedule::thread().

50  {
52  std::array<WF, 17> flags;
53  WF& a = flags[0];
54  WF& b = flags[16]; // different cache line
55  auto thr = DSched::thread([&] {
56  for (int i = 0; i < numRounds; ++i) {
57  a.try_wait();
58  a.wait();
59  a.reset();
60  b.post();
61  }
62  });
63  for (int i = 0; i < numRounds; ++i) {
64  a.post();
65  b.try_wait();
66  b.wait();
67  b.reset();
68  }
69  DSched::join(thr);
70 }
flags
Definition: http_parser.h:127
char b
static std::thread thread(Func &&func, Args &&...args)
char a
static void join(std::thread &child)
TEST ( SaturatingSemaphore  ,
basic_spin_only   
)

Tests.

Definition at line 137 of file SaturatingSemaphoreTest.cpp.

137  {
138  run_basic_test<false>();
139 }
TEST ( SaturatingSemaphore  ,
basic_may_block   
)

Definition at line 141 of file SaturatingSemaphoreTest.cpp.

141  {
142  run_basic_test<true>();
143 }
TEST ( SaturatingSemaphore  ,
pingpong_spin_only   
)

Definition at line 145 of file SaturatingSemaphoreTest.cpp.

145  {
146  run_pingpong_test<false>(1000);
147 }
TEST ( SaturatingSemaphore  ,
pingpong_may_block   
)

Definition at line 149 of file SaturatingSemaphoreTest.cpp.

149  {
150  run_pingpong_test<true>(1000);
151 }
TEST ( SaturatingSemaphore  ,
multi_poster_multi_waiter_spin_only   
)

Definition at line 153 of file SaturatingSemaphoreTest.cpp.

153  {
154  run_multi_poster_multi_waiter_test<false>(1, 1);
155  run_multi_poster_multi_waiter_test<false>(1, 10);
156  run_multi_poster_multi_waiter_test<false>(10, 1);
157  run_multi_poster_multi_waiter_test<false>(10, 10);
158 }
TEST ( SaturatingSemaphore  ,
multi_poster_multi_waiter_may_block   
)

Definition at line 160 of file SaturatingSemaphoreTest.cpp.

160  {
161  run_multi_poster_multi_waiter_test<true>(1, 1);
162  run_multi_poster_multi_waiter_test<true>(1, 10);
163  run_multi_poster_multi_waiter_test<true>(10, 1);
164  run_multi_poster_multi_waiter_test<true>(10, 10);
165 }