proxygen
ThreadPoolExecutorTest.cpp File Reference

Go to the source code of this file.

Classes

class  TestObserver
 
class  TestData
 
struct  SlowMover
 
struct  UBQ< T >
 

Functions

static Func burnMs (uint64_t ms)
 
template<class TPE >
static void basic ()
 
 TEST (ThreadPoolExecutorTest, CPUBasic)
 
 TEST (IOThreadPoolExecutorTest, IOBasic)
 
template<class TPE >
static void resize ()
 
 TEST (ThreadPoolExecutorTest, CPUResize)
 
 TEST (ThreadPoolExecutorTest, IOResize)
 
template<class TPE >
static void stop ()
 
template<>
void stop< IOThreadPoolExecutor > ()
 
 TEST (ThreadPoolExecutorTest, CPUStop)
 
 TEST (ThreadPoolExecutorTest, IOStop)
 
template<class TPE >
static void join ()
 
 TEST (ThreadPoolExecutorTest, CPUJoin)
 
 TEST (ThreadPoolExecutorTest, IOJoin)
 
template<class TPE >
static void destroy ()
 
template<>
void destroy< IOThreadPoolExecutor > ()
 
 TEST (ThreadPoolExecutorTest, CPUDestroy)
 
 TEST (ThreadPoolExecutorTest, IODestroy)
 
template<class TPE >
static void resizeUnderLoad ()
 
 TEST (ThreadPoolExecutorTest, CPUResizeUnderLoad)
 
 TEST (ThreadPoolExecutorTest, IOResizeUnderLoad)
 
template<class TPE >
static void poolStats ()
 
 TEST (ThreadPoolExecutorTest, CPUPoolStats)
 
 TEST (ThreadPoolExecutorTest, IOPoolStats)
 
template<class TPE >
static void taskStats ()
 
 TEST (ThreadPoolExecutorTest, CPUTaskStats)
 
 TEST (ThreadPoolExecutorTest, IOTaskStats)
 
template<class TPE >
static void expiration ()
 
 TEST (ThreadPoolExecutorTest, CPUExpiration)
 
 TEST (ThreadPoolExecutorTest, IOExpiration)
 
template<typename TPE >
static void futureExecutor ()
 
 TEST (ThreadPoolExecutorTest, CPUFuturePool)
 
 TEST (ThreadPoolExecutorTest, IOFuturePool)
 
 TEST (ThreadPoolExecutorTest, PriorityPreemptionTest)
 
 TEST (ThreadPoolExecutorTest, IOObserver)
 
 TEST (ThreadPoolExecutorTest, CPUObserver)
 
 TEST (ThreadPoolExecutorTest, AddWithPriority)
 
 TEST (ThreadPoolExecutorTest, BlockingQueue)
 
 TEST (PriorityThreadFactoryTest, ThreadPriority)
 
 TEST (InitThreadFactoryTest, InitializerCalled)
 
 TEST (InitThreadFactoryTest, InitializerAndFinalizerCalled)
 
 TEST (ThreadPoolExecutorTest, RequestContext)
 
template<typename Q >
void bugD3527722_test ()
 
 TEST (ThreadPoolExecutorTest, LifoSemMPMCQueueBugD3527722)
 
 TEST (ThreadPoolExecutorTest, UnboundedBlockingQueueBugD3527722)
 
template<typename TPE >
static void removeThreadTest ()
 
 TEST (ThreadPoolExecutorTest, RemoveThreadTestIO)
 
 TEST (ThreadPoolExecutorTest, RemoveThreadTestCPU)
 
template<typename TPE >
static void resizeThreadWhileExecutingTest ()
 
 TEST (ThreadPoolExecutorTest, resizeThreadWhileExecutingTestIO)
 
 TEST (ThreadPoolExecutorTest, resizeThreadWhileExecutingTestCPU)
 
template<typename TPE >
void keepAliveTest ()
 
 TEST (ThreadPoolExecutorTest, KeepAliveTestIO)
 
 TEST (ThreadPoolExecutorTest, KeepAliveTestCPU)
 
int getNumThreadPoolExecutors ()
 
template<typename TPE >
static void registersToExecutorListTest ()
 
 TEST (ThreadPoolExecutorTest, registersToExecutorListTestIO)
 
 TEST (ThreadPoolExecutorTest, registersToExecutorListTestCPU)
 
template<typename TPE >
static void testUsesNameFromNamedThreadFactory ()
 
 TEST (ThreadPoolExecutorTest, testUsesNameFromNamedThreadFactoryIO)
 
 TEST (ThreadPoolExecutorTest, testUsesNameFromNamedThreadFactoryCPU)
 
 TEST (ThreadPoolExecutorTest, DynamicThreadsTest)
 
 TEST (ThreadPoolExecutorTest, DynamicThreadAddRemoveRace)
 
 TEST (ThreadPoolExecutorTest, AddPerf)
 
template<typename TPE >
static void WeakRefTest ()
 
template<typename TPE >
static void virtualExecutorTest ()
 
 TEST (ThreadPoolExecutorTest, WeakRefTestIO)
 
 TEST (ThreadPoolExecutorTest, WeakRefTestCPU)
 
 TEST (ThreadPoolExecutorTest, VirtualExecutorTestIO)
 
 TEST (ThreadPoolExecutorTest, VirtualExecutorTestCPU)
 

Function Documentation

template<class TPE >
static void basic ( )
static

Definition at line 44 of file ThreadPoolExecutorTest.cpp.

44  {
45  // Create and destroy
46  TPE tpe(10);
47 }
template<typename Q >
void bugD3527722_test ( )

Definition at line 592 of file ThreadPoolExecutorTest.cpp.

592  {
593  // Test that the queue does not get stuck if writes are completed in
594  // order opposite to how they are initiated.
595  Q q(1024);
596  std::atomic<int> turn{};
597 
598  std::thread consumer1([&] {
599  ++turn;
600  q.take();
601  });
602  std::thread consumer2([&] {
603  ++turn;
604  q.take();
605  });
606 
607  std::thread producer1([&] {
608  ++turn;
609  while (turn < 4) {
610  ;
611  }
612  ++turn;
613  q.add(SlowMover(true));
614  });
615  std::thread producer2([&] {
616  ++turn;
617  while (turn < 5) {
618  ;
619  }
620  q.add(SlowMover(false));
621  });
622 
623  producer1.join();
624  producer2.join();
625  consumer1.join();
626  consumer2.join();
627 }
static Func burnMs ( uint64_t  ms)
static
template<class TPE >
static void destroy ( )
static

Definition at line 140 of file ThreadPoolExecutorTest.cpp.

References burnMs(), EXPECT_GT, f, and i.

Referenced by folly::coro::detail::InlineTask< T >::Awaiter::await_resume(), folly::coro::TaskWithExecutor< T >::Awaiter::await_resume(), folly::coro::detail::TaskPromiseBase::await_transform(), folly::portability::ssl::BIO_meth_set_destroy(), wangle::AcceptorHandshakeManager::connectionError(), wangle::AcceptorHandshakeManager::connectionReady(), wangle::ServerAcceptor< Pipeline >::ServerConnection::deletePipeline(), folly::UndelayedDestruction< HHWheelTimer >::destroy(), fizz::AsyncFizzBase::destroy(), proxygen::AsyncTimeoutSet::destroy(), folly::Try< T >::emplace(), folly::Try< T >::emplaceException(), folly::threadlocal_detail::StaticMetaBase::erase(), folly::Try< folly::folly::Unit >::get(), folly::NotificationQueue< MessageT >::Consumer::getEventBase(), folly::allocator_delete< Alloc >::operator()(), folly::Try< T >::operator=(), folly::F14VectorSet< Key, Hasher, KeyEqual, Alloc >::operator=(), folly::ThreadLocalPtr< SubscriberMap >::operator=(), folly::F14VectorMap< Key, Mapped, Hasher, KeyEqual, Alloc >::operator=(), folly::dynamic::operator=(), proxygen::PassThroughTransportFilter::readEOF(), proxygen::PassThroughTransportFilter::readErr(), folly::detail::NodeRecycler< NodeType, NodeAlloc, typename std::enable_if< !NodeType::template DestroyIsNoOp< NodeAlloc >::value >::type >::releaseRef(), folly::fbvector< HTTPHeaderCode >::S_destroy_range_a(), proxygen::HTTPSession::shutdownTransportWithReset(), TEST(), test_relinquish3(), unique_ptr_test(), folly::AtomicHashMap< int64_t, int64_t >::~AtomicHashMap(), folly::detail::NodeRecycler< NodeType, NodeAlloc, typename std::enable_if< !NodeType::template DestroyIsNoOp< NodeAlloc >::value >::type >::~NodeRecycler(), and folly::ThreadLocalPtr< SubscriberMap >::~ThreadLocalPtr().

140  {
141  TPE tpe(1);
142  std::atomic<int> completed(0);
143  auto f = [&]() {
144  burnMs(10)();
145  completed++;
146  };
147  for (int i = 0; i < 1000; i++) {
148  tpe.add(f);
149  }
150  tpe.stop();
151  EXPECT_GT(1000, completed);
152 }
auto f
static Func burnMs(uint64_t ms)
#define EXPECT_GT(val1, val2)
Definition: gtest.h:1934
template<>
void destroy< IOThreadPoolExecutor > ( )

Definition at line 158 of file ThreadPoolExecutorTest.cpp.

References folly::IOThreadPoolExecutor::add(), burnMs(), folly::Optional< Value >::clear(), EXPECT_EQ, f, i, and folly::in_place().

Referenced by TEST().

158  {
160  std::atomic<int> completed(0);
161  auto f = [&]() {
162  burnMs(10)();
163  completed++;
164  };
165  for (int i = 0; i < 10; i++) {
166  tpe->add(f);
167  }
168  tpe.clear();
169  EXPECT_EQ(10, completed);
170 }
auto f
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
in_place_tag in_place(in_place_tag={})
Definition: Utility.h:235
static Func burnMs(uint64_t ms)
template<class TPE >
static void expiration ( )
static

Definition at line 266 of file ThreadPoolExecutorTest.cpp.

References burnMs(), EXPECT_EQ, EXPECT_FALSE, EXPECT_TRUE, folly::ThreadPoolExecutor::TaskStats::expired, FAIL, and i.

Referenced by wangle::SSLSessionCacheManager::storeCacheRecord().

266  {
267  TPE tpe(1);
268  std::atomic<int> statCbCount(0);
269  tpe.subscribeToTaskStats([&](ThreadPoolExecutor::TaskStats stats) {
270  int i = statCbCount++;
271  if (i == 0) {
272  EXPECT_FALSE(stats.expired);
273  } else if (i == 1) {
274  EXPECT_TRUE(stats.expired);
275  } else {
276  FAIL();
277  }
278  });
279  std::atomic<int> expireCbCount(0);
280  auto expireCb = [&]() { expireCbCount++; };
281  tpe.add(burnMs(10), seconds(60), expireCb);
282  tpe.add(burnMs(10), milliseconds(10), expireCb);
283  tpe.join();
284  EXPECT_EQ(2, statCbCount);
285  EXPECT_EQ(1, expireCbCount);
286 }
#define FAIL()
Definition: gtest.h:1822
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
static Func burnMs(uint64_t ms)
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
template<typename TPE >
static void futureExecutor ( )
static

Definition at line 297 of file ThreadPoolExecutorTest.cpp.

References folly::FutureExecutor< ExecutorImpl >::addFuture(), burnMs(), c, EXPECT_EQ, EXPECT_NO_THROW, EXPECT_THROW, folly::makeFuture(), folly::Baton< MayBlock, Atom >::post(), folly::pushmi::detail::t, and folly::Baton< MayBlock, Atom >::wait().

297  {
298  FutureExecutor<TPE> fe(2);
299  std::atomic<int> c{0};
300  fe.addFuture([]() { return makeFuture<int>(42); }).then([&](Try<int>&& t) {
301  c++;
302  EXPECT_EQ(42, t.value());
303  });
304  fe.addFuture([]() { return 100; }).then([&](Try<int>&& t) {
305  c++;
306  EXPECT_EQ(100, t.value());
307  });
308  fe.addFuture([]() { return makeFuture(); }).then([&](Try<Unit>&& t) {
309  c++;
310  EXPECT_NO_THROW(t.value());
311  });
312  fe.addFuture([]() { return; }).then([&](Try<Unit>&& t) {
313  c++;
314  EXPECT_NO_THROW(t.value());
315  });
316  fe.addFuture([]() { throw std::runtime_error("oops"); })
317  .then([&](Try<Unit>&& t) {
318  c++;
319  EXPECT_THROW(t.value(), std::runtime_error);
320  });
321  // Test doing actual async work
322  folly::Baton<> baton;
323  fe.addFuture([&]() {
324  auto p = std::make_shared<Promise<int>>();
325  std::thread t([p]() {
326  burnMs(10)();
327  p->setValue(42);
328  });
329  t.detach();
330  return p->getFuture();
331  })
332  .then([&](Try<int>&& t) {
333  EXPECT_EQ(42, t.value());
334  c++;
335  baton.post();
336  });
337  baton.wait();
338  fe.join();
339  EXPECT_EQ(6, c);
340 }
#define EXPECT_NO_THROW(statement)
Definition: gtest.h:1845
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
FOLLY_ALWAYS_INLINE void wait(const WaitOptions &opt=wait_options()) noexcept
Definition: Baton.h:170
Definition: Try.h:51
void post() noexcept
Definition: Baton.h:123
static Func burnMs(uint64_t ms)
char c
Future< typename std::decay< T >::type > makeFuture(T &&t)
Definition: Future-inl.h:1310
int getNumThreadPoolExecutors ( )

Definition at line 731 of file ThreadPoolExecutorTest.cpp.

References count, and folly::ThreadPoolExecutor::withAll().

Referenced by registersToExecutorListTest().

731  {
732  int count = 0;
733  ThreadPoolExecutor::withAll([&count](ThreadPoolExecutor&) { count++; });
734  return count;
735 }
int * count
template<class TPE >
static void join ( )
static

Definition at line 117 of file ThreadPoolExecutorTest.cpp.

References burnMs(), EXPECT_EQ, f, and i.

117  {
118  TPE tpe(10);
119  std::atomic<int> completed(0);
120  auto f = [&]() {
121  burnMs(1)();
122  completed++;
123  };
124  for (int i = 0; i < 1000; i++) {
125  tpe.add(f);
126  }
127  tpe.join();
128  EXPECT_EQ(1000, completed);
129 }
auto f
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
static Func burnMs(uint64_t ms)
template<typename TPE >
void keepAliveTest ( )

Definition at line 708 of file ThreadPoolExecutorTest.cpp.

References folly::pushmi::executor, EXPECT_EQ, EXPECT_TRUE, f, folly::getKeepAliveToken(), folly::gen::move, folly::futures::sleep(), and folly::via().

708  {
709  auto executor = std::make_unique<TPE>(4);
710 
711  auto f = futures::sleep(std::chrono::milliseconds{100})
712  .via(executor.get())
713  .thenValue([keepAlive = getKeepAliveToken(executor.get())](
714  auto&&) { return 42; })
715  .semi();
716 
717  executor.reset();
718 
719  EXPECT_TRUE(f.isReady());
720  EXPECT_EQ(42, std::move(f).get());
721 }
auto f
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Future< Unit > sleep(Duration dur, Timekeeper *tk)
Definition: Future.cpp:42
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
PUSHMI_INLINE_VAR constexpr detail::via_fn via
Definition: via.h:166
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
Executor::KeepAlive< ExecutorT > getKeepAliveToken(ExecutorT *executor)
Definition: Executor.h:200
template<class TPE >
static void poolStats ( )
static

Definition at line 206 of file ThreadPoolExecutorTest.cpp.

References EXPECT_EQ, EXPECT_GE, folly::Baton< MayBlock, Atom >::post(), and folly::Baton< MayBlock, Atom >::wait().

206  {
207  folly::Baton<> startBaton, endBaton;
208  TPE tpe(1);
209  auto stats = tpe.getPoolStats();
210  EXPECT_GE(1, stats.threadCount);
211  EXPECT_GE(1, stats.idleThreadCount);
212  EXPECT_EQ(0, stats.activeThreadCount);
213  EXPECT_EQ(0, stats.pendingTaskCount);
214  EXPECT_EQ(0, tpe.getPendingTaskCount());
215  EXPECT_EQ(0, stats.totalTaskCount);
216  tpe.add([&]() {
217  startBaton.post();
218  endBaton.wait();
219  });
220  tpe.add([&]() {});
221  startBaton.wait();
222  stats = tpe.getPoolStats();
223  EXPECT_EQ(1, stats.threadCount);
224  EXPECT_EQ(0, stats.idleThreadCount);
225  EXPECT_EQ(1, stats.activeThreadCount);
226  EXPECT_EQ(1, stats.pendingTaskCount);
227  EXPECT_EQ(1, tpe.getPendingTaskCount());
228  EXPECT_EQ(2, stats.totalTaskCount);
229  endBaton.post();
230 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
#define EXPECT_GE(val1, val2)
Definition: gtest.h:1932
FOLLY_ALWAYS_INLINE void wait(const WaitOptions &opt=wait_options()) noexcept
Definition: Baton.h:170
void post() noexcept
Definition: Baton.h:123
template<typename TPE >
static void registersToExecutorListTest ( )
static

Definition at line 738 of file ThreadPoolExecutorTest.cpp.

References EXPECT_EQ, and getNumThreadPoolExecutors().

738  {
740  {
741  TPE tpe(10);
743  {
744  TPE tpe2(5);
746  }
748  }
750 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
int getNumThreadPoolExecutors()
template<typename TPE >
static void removeThreadTest ( )
static

Definition at line 643 of file ThreadPoolExecutorTest.cpp.

References burnMs(), EXPECT_EQ, EXPECT_NE, f, folly::makeFuture(), and folly::gen::move.

643  {
644  // test that adding a .then() after we have removed some threads
645  // doesn't cause deadlock and they are executed on different threads
647  std::thread::id id1, id2;
648  TPE fe(2);
649  f = folly::makeFuture()
650  .via(&fe)
651  .thenValue([&id1](auto&&) {
652  burnMs(100)();
653  id1 = std::this_thread::get_id();
654  })
655  .thenValue([&id2](auto&&) {
656  return 77;
657  id2 = std::this_thread::get_id();
658  });
659  fe.setNumThreads(1);
660 
661  // future::then should be fulfilled because there is other thread available
662  EXPECT_EQ(77, std::move(*f).get());
663  // two thread should be different because then part should be rescheduled to
664  // the other thread
665  EXPECT_NE(id1, id2);
666 }
auto f
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
static Func burnMs(uint64_t ms)
#define EXPECT_NE(val1, val2)
Definition: gtest.h:1926
Future< typename std::decay< T >::type > makeFuture(T &&t)
Definition: Future-inl.h:1310
template<class TPE >
static void resize ( )
static

Definition at line 58 of file ThreadPoolExecutorTest.cpp.

References EXPECT_EQ.

58  {
59  TPE tpe(100);
60  EXPECT_EQ(100, tpe.numThreads());
61  tpe.setNumThreads(50);
62  EXPECT_EQ(50, tpe.numThreads());
63  tpe.setNumThreads(150);
64  EXPECT_EQ(150, tpe.numThreads());
65 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
template<typename TPE >
static void resizeThreadWhileExecutingTest ( )
static

Definition at line 677 of file ThreadPoolExecutorTest.cpp.

References burnMs(), EXPECT_EQ, f, and i.

677  {
678  TPE tpe(10);
679  EXPECT_EQ(10, tpe.numThreads());
680 
681  std::atomic<int> completed(0);
682  auto f = [&]() {
683  burnMs(10)();
684  completed++;
685  };
686  for (int i = 0; i < 1000; i++) {
687  tpe.add(f);
688  }
689  tpe.setNumThreads(8);
690  EXPECT_EQ(8, tpe.numThreads());
691  tpe.setNumThreads(5);
692  EXPECT_EQ(5, tpe.numThreads());
693  tpe.setNumThreads(15);
694  EXPECT_EQ(15, tpe.numThreads());
695  tpe.join();
696  EXPECT_EQ(1000, completed);
697 }
auto f
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
static Func burnMs(uint64_t ms)
template<class TPE >
static void resizeUnderLoad ( )
static

Definition at line 181 of file ThreadPoolExecutorTest.cpp.

References burnMs(), EXPECT_EQ, f, and i.

181  {
182  TPE tpe(10);
183  std::atomic<int> completed(0);
184  auto f = [&]() {
185  burnMs(1)();
186  completed++;
187  };
188  for (int i = 0; i < 1000; i++) {
189  tpe.add(f);
190  }
191  tpe.setNumThreads(5);
192  tpe.setNumThreads(15);
193  tpe.join();
194  EXPECT_EQ(1000, completed);
195 }
auto f
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
static Func burnMs(uint64_t ms)
template<>
void stop< IOThreadPoolExecutor > ( )

Definition at line 94 of file ThreadPoolExecutorTest.cpp.

References folly::IOThreadPoolExecutor::add(), burnMs(), EXPECT_EQ, f, i, and folly::ThreadPoolExecutor::stop().

Referenced by TEST().

94  {
95  IOThreadPoolExecutor tpe(1);
96  std::atomic<int> completed(0);
97  auto f = [&]() {
98  burnMs(10)();
99  completed++;
100  };
101  for (int i = 0; i < 10; i++) {
102  tpe.add(f);
103  }
104  tpe.stop();
105  EXPECT_EQ(10, completed);
106 }
auto f
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
static Func burnMs(uint64_t ms)
template<class TPE >
static void taskStats ( )
static

Definition at line 241 of file ThreadPoolExecutorTest.cpp.

References burnMs(), c, EXPECT_EQ, EXPECT_LT, i, folly::ThreadPoolExecutor::TaskStats::runTime, and folly::ThreadPoolExecutor::TaskStats::waitTime.

241  {
242  TPE tpe(1);
243  std::atomic<int> c(0);
244  tpe.subscribeToTaskStats([&](ThreadPoolExecutor::TaskStats stats) {
245  int i = c++;
246  EXPECT_LT(milliseconds(0), stats.runTime);
247  if (i == 1) {
248  EXPECT_LT(milliseconds(0), stats.waitTime);
249  }
250  });
251  tpe.add(burnMs(10));
252  tpe.add(burnMs(10));
253  tpe.join();
254  EXPECT_EQ(2, c);
255 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
static Func burnMs(uint64_t ms)
#define EXPECT_LT(val1, val2)
Definition: gtest.h:1930
char c
TEST ( ThreadPoolExecutorTest  ,
CPUBasic   
)

Definition at line 49 of file ThreadPoolExecutorTest.cpp.

49  {
50  basic<CPUThreadPoolExecutor>();
51 }
TEST ( IOThreadPoolExecutorTest  ,
IOBasic   
)

Definition at line 53 of file ThreadPoolExecutorTest.cpp.

53  {
54  basic<IOThreadPoolExecutor>();
55 }
TEST ( ThreadPoolExecutorTest  ,
CPUResize   
)

Definition at line 67 of file ThreadPoolExecutorTest.cpp.

67  {
68  resize<CPUThreadPoolExecutor>();
69 }
TEST ( ThreadPoolExecutorTest  ,
IOResize   
)

Definition at line 71 of file ThreadPoolExecutorTest.cpp.

71  {
72  resize<IOThreadPoolExecutor>();
73 }
TEST ( ThreadPoolExecutorTest  ,
CPUStop   
)

Definition at line 108 of file ThreadPoolExecutorTest.cpp.

108  {
109  stop<CPUThreadPoolExecutor>();
110 }
TEST ( ThreadPoolExecutorTest  ,
IOStop   
)

Definition at line 112 of file ThreadPoolExecutorTest.cpp.

References stop< IOThreadPoolExecutor >().

112  {
114 }
void stop< IOThreadPoolExecutor >()
TEST ( ThreadPoolExecutorTest  ,
CPUJoin   
)

Definition at line 131 of file ThreadPoolExecutorTest.cpp.

131  {
132  join<CPUThreadPoolExecutor>();
133 }
TEST ( ThreadPoolExecutorTest  ,
IOJoin   
)

Definition at line 135 of file ThreadPoolExecutorTest.cpp.

135  {
136  join<IOThreadPoolExecutor>();
137 }
TEST ( ThreadPoolExecutorTest  ,
CPUDestroy   
)

Definition at line 172 of file ThreadPoolExecutorTest.cpp.

172  {
173  destroy<CPUThreadPoolExecutor>();
174 }
TEST ( ThreadPoolExecutorTest  ,
IODestroy   
)

Definition at line 176 of file ThreadPoolExecutorTest.cpp.

References destroy< IOThreadPoolExecutor >().

176  {
178 }
void destroy< IOThreadPoolExecutor >()
TEST ( ThreadPoolExecutorTest  ,
CPUResizeUnderLoad   
)

Definition at line 197 of file ThreadPoolExecutorTest.cpp.

197  {
198  resizeUnderLoad<CPUThreadPoolExecutor>();
199 }
TEST ( ThreadPoolExecutorTest  ,
IOResizeUnderLoad   
)

Definition at line 201 of file ThreadPoolExecutorTest.cpp.

201  {
202  resizeUnderLoad<IOThreadPoolExecutor>();
203 }
TEST ( ThreadPoolExecutorTest  ,
CPUPoolStats   
)

Definition at line 232 of file ThreadPoolExecutorTest.cpp.

232  {
233  poolStats<CPUThreadPoolExecutor>();
234 }
TEST ( ThreadPoolExecutorTest  ,
IOPoolStats   
)

Definition at line 236 of file ThreadPoolExecutorTest.cpp.

236  {
237  poolStats<IOThreadPoolExecutor>();
238 }
TEST ( ThreadPoolExecutorTest  ,
CPUTaskStats   
)

Definition at line 257 of file ThreadPoolExecutorTest.cpp.

257  {
258  taskStats<CPUThreadPoolExecutor>();
259 }
TEST ( ThreadPoolExecutorTest  ,
IOTaskStats   
)

Definition at line 261 of file ThreadPoolExecutorTest.cpp.

261  {
262  taskStats<IOThreadPoolExecutor>();
263 }
TEST ( ThreadPoolExecutorTest  ,
CPUExpiration   
)

Definition at line 288 of file ThreadPoolExecutorTest.cpp.

288  {
289  expiration<CPUThreadPoolExecutor>();
290 }
TEST ( ThreadPoolExecutorTest  ,
IOExpiration   
)

Definition at line 292 of file ThreadPoolExecutorTest.cpp.

292  {
293  expiration<IOThreadPoolExecutor>();
294 }
TEST ( ThreadPoolExecutorTest  ,
CPUFuturePool   
)

Definition at line 342 of file ThreadPoolExecutorTest.cpp.

342  {
343  futureExecutor<CPUThreadPoolExecutor>();
344 }
TEST ( ThreadPoolExecutorTest  ,
IOFuturePool   
)

Definition at line 346 of file ThreadPoolExecutorTest.cpp.

346  {
347  futureExecutor<IOThreadPoolExecutor>();
348 }
TEST ( ThreadPoolExecutorTest  ,
PriorityPreemptionTest   
)

Definition at line 350 of file ThreadPoolExecutorTest.cpp.

References folly::VirtualExecutor::addWithPriority(), EXPECT_EQ, EXPECT_FALSE, folly::Executor::HI_PRI, i, folly::Executor::LO_PRI, and folly::ThreadPoolExecutor::setNumThreads().

350  {
351  bool tookLopri = false;
352  auto completed = 0;
353  auto hipri = [&] {
354  EXPECT_FALSE(tookLopri);
355  completed++;
356  };
357  auto lopri = [&] {
358  tookLopri = true;
359  completed++;
360  };
361  CPUThreadPoolExecutor pool(0, 2);
362  {
363  VirtualExecutor ve(pool);
364  for (int i = 0; i < 50; i++) {
365  ve.addWithPriority(lopri, Executor::LO_PRI);
366  }
367  for (int i = 0; i < 50; i++) {
368  ve.addWithPriority(hipri, Executor::HI_PRI);
369  }
370  pool.setNumThreads(1);
371  }
372  EXPECT_EQ(100, completed);
373 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( ThreadPoolExecutorTest  ,
IOObserver   
)

Definition at line 397 of file ThreadPoolExecutorTest.cpp.

References folly::ThreadPoolExecutor::addObserver(), exe, folly::ThreadPoolExecutor::removeObserver(), and folly::ThreadPoolExecutor::setNumThreads().

397  {
398  auto observer = std::make_shared<TestObserver>();
399 
400  {
402  exe.addObserver(observer);
403  exe.setNumThreads(3);
404  exe.setNumThreads(0);
405  exe.setNumThreads(7);
406  exe.removeObserver(observer);
407  exe.setNumThreads(10);
408  }
409 
410  observer->checkCalls();
411 }
InlineExecutor exe
Definition: Benchmark.cpp:337
TEST ( ThreadPoolExecutorTest  ,
CPUObserver   
)

Definition at line 413 of file ThreadPoolExecutorTest.cpp.

References folly::ThreadPoolExecutor::addObserver(), exe, folly::ThreadPoolExecutor::removeObserver(), and folly::ThreadPoolExecutor::setNumThreads().

413  {
414  auto observer = std::make_shared<TestObserver>();
415 
416  {
418  exe.addObserver(observer);
419  exe.setNumThreads(3);
420  exe.setNumThreads(0);
421  exe.setNumThreads(7);
422  exe.removeObserver(observer);
423  exe.setNumThreads(10);
424  }
425 
426  observer->checkCalls();
427 }
InlineExecutor exe
Definition: Benchmark.cpp:337
TEST ( ThreadPoolExecutorTest  ,
AddWithPriority   
)

Definition at line 429 of file ThreadPoolExecutorTest.cpp.

References folly::Executor::addWithPriority(), c, EXPECT_EQ, EXPECT_THROW, f, folly::Executor::HI_PRI, and folly::Executor::LO_PRI.

429  {
430  std::atomic_int c{0};
431  auto f = [&] { c++; };
432 
433  // IO exe doesn't support priorities
434  IOThreadPoolExecutor ioExe(10);
435  EXPECT_THROW(ioExe.addWithPriority(f, 0), std::runtime_error);
436 
437  CPUThreadPoolExecutor cpuExe(10, 3);
438  cpuExe.addWithPriority(f, -1);
439  cpuExe.addWithPriority(f, 0);
440  cpuExe.addWithPriority(f, 1);
441  cpuExe.addWithPriority(f, -2); // will add at the lowest priority
442  cpuExe.addWithPriority(f, 2); // will add at the highest priority
443  cpuExe.addWithPriority(f, Executor::LO_PRI);
444  cpuExe.addWithPriority(f, Executor::HI_PRI);
445  cpuExe.join();
446 
447  EXPECT_EQ(7, c);
448 }
auto f
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
char c
TEST ( ThreadPoolExecutorTest  ,
BlockingQueue   
)

Definition at line 450 of file ThreadPoolExecutorTest.cpp.

References folly::BLOCK, burnMs(), c, EXPECT_EQ, EXPECT_NO_THROW, f, i, folly::make_unique(), and folly::gen::move.

450  {
451  std::atomic_int c{0};
452  auto f = [&] {
453  burnMs(1)();
454  c++;
455  };
456  const int kQueueCapacity = 1;
457  const int kThreads = 1;
458 
459  auto queue = std::make_unique<LifoSemMPMCQueue<
461  QueueBehaviorIfFull::BLOCK>>(kQueueCapacity);
462 
463  CPUThreadPoolExecutor cpuExe(
464  kThreads,
465  std::move(queue),
466  std::make_shared<NamedThreadFactory>("CPUThreadPool"));
467 
468  // Add `f` five times. It sleeps for 1ms every time. Calling
469  // `cppExec.add()` is *almost* guaranteed to block because there's
470  // only 1 cpu worker thread.
471  for (int i = 0; i < 5; i++) {
472  EXPECT_NO_THROW(cpuExe.add(f));
473  }
474  cpuExe.join();
475 
476  EXPECT_EQ(5, c);
477 }
auto f
#define EXPECT_NO_THROW(statement)
Definition: gtest.h:1845
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::enable_if<!std::is_array< T >::value, std::unique_ptr< T > >::type make_unique(Args &&...args)
Definition: Memory.h:259
static Func burnMs(uint64_t ms)
char c
TEST ( PriorityThreadFactoryTest  ,
ThreadPriority   
)

Definition at line 479 of file ThreadPoolExecutorTest.cpp.

References EXPECT_EQ, folly::join(), min, folly::PriorityThreadFactory::newThread(), and folly::throwSystemError().

479  {
480  errno = 0;
481  auto currentPriority = getpriority(PRIO_PROCESS, 0);
482  if (errno != 0) {
483  throwSystemError("failed to get current priority");
484  }
485 
486  // Non-root users can only increase the priority value. Make sure we are
487  // trying to go to a higher priority than we are currently running as, up to
488  // the maximum allowed of 20.
489  int desiredPriority = std::min(20, currentPriority + 1);
490 
491  PriorityThreadFactory factory(
492  std::make_shared<NamedThreadFactory>("stuff"), desiredPriority);
493  int actualPriority = -21;
494  factory.newThread([&]() { actualPriority = getpriority(PRIO_PROCESS, 0); })
495  .join();
496  EXPECT_EQ(desiredPriority, actualPriority);
497 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
static void join()
LogLevel min
Definition: LogLevel.cpp:30
void throwSystemError(Args &&...args)
Definition: Exception.h:76
TEST ( InitThreadFactoryTest  ,
InitializerCalled   
)

Definition at line 499 of file ThreadPoolExecutorTest.cpp.

References EXPECT_EQ, folly::join(), and folly::InitThreadFactory::newThread().

499  {
500  int initializerCalledCount = 0;
501  InitThreadFactory factory(
502  std::make_shared<NamedThreadFactory>("test"),
503  [&initializerCalledCount] { initializerCalledCount++; });
504  factory
505  .newThread(
506  [&initializerCalledCount]() { EXPECT_EQ(initializerCalledCount, 1); })
507  .join();
508  EXPECT_EQ(initializerCalledCount, 1);
509 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
static void join()
std::thread newThread(Func &&func) override
TEST ( InitThreadFactoryTest  ,
InitializerAndFinalizerCalled   
)

Definition at line 511 of file ThreadPoolExecutorTest.cpp.

References EXPECT_FALSE, EXPECT_TRUE, folly::join(), and folly::InitThreadFactory::newThread().

511  {
512  bool initializerCalled = false;
513  bool taskBodyCalled = false;
514  bool finalizerCalled = false;
515 
516  InitThreadFactory factory(
517  std::make_shared<NamedThreadFactory>("test"),
518  [&] {
519  // thread initializer
520  EXPECT_FALSE(initializerCalled);
521  EXPECT_FALSE(taskBodyCalled);
522  EXPECT_FALSE(finalizerCalled);
523  initializerCalled = true;
524  },
525  [&] {
526  // thread finalizer
527  EXPECT_TRUE(initializerCalled);
528  EXPECT_TRUE(taskBodyCalled);
529  EXPECT_FALSE(finalizerCalled);
530  finalizerCalled = true;
531  });
532 
533  factory
534  .newThread([&]() {
535  EXPECT_TRUE(initializerCalled);
536  EXPECT_FALSE(taskBodyCalled);
537  EXPECT_FALSE(finalizerCalled);
538  taskBodyCalled = true;
539  })
540  .join();
541 
542  EXPECT_TRUE(initializerCalled);
543  EXPECT_TRUE(taskBodyCalled);
544  EXPECT_TRUE(finalizerCalled);
545 }
static void join()
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
std::thread newThread(Func &&func) override
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( ThreadPoolExecutorTest  ,
RequestContext   
)

Definition at line 559 of file ThreadPoolExecutorTest.cpp.

References folly::CPUThreadPoolExecutor::add(), ASSERT_TRUE, folly::data(), data_, folly::pushmi::executor, EXPECT_EQ, folly::RequestContext::get(), folly::RequestContext::getContextData(), and folly::RequestContext::setContextData().

559  {
561 
562  RequestContextScopeGuard rctx; // create new request context for this scope
563  EXPECT_EQ(nullptr, RequestContext::get()->getContextData("test"));
564  RequestContext::get()->setContextData("test", std::make_unique<TestData>(42));
565  auto data = RequestContext::get()->getContextData("test");
566  EXPECT_EQ(42, dynamic_cast<TestData*>(data)->data_);
567 
568  executor.add([] {
569  auto data2 = RequestContext::get()->getContextData("test");
570  ASSERT_TRUE(data2 != nullptr);
571  EXPECT_EQ(42, dynamic_cast<TestData*>(data2)->data_);
572  });
573 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
PUSHMI_INLINE_VAR constexpr detail::get_fn< T > get
Definition: submit.h:391
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
StringPiece data_
TEST ( ThreadPoolExecutorTest  ,
LifoSemMPMCQueueBugD3527722   
)

Definition at line 629 of file ThreadPoolExecutorTest.cpp.

629  {
630  bugD3527722_test<LifoSemMPMCQueue<SlowMover>>();
631 }
TEST ( ThreadPoolExecutorTest  ,
UnboundedBlockingQueueBugD3527722   
)

Definition at line 638 of file ThreadPoolExecutorTest.cpp.

638  {
639  bugD3527722_test<UBQ<SlowMover>>();
640 }
TEST ( ThreadPoolExecutorTest  ,
RemoveThreadTestIO   
)

Definition at line 668 of file ThreadPoolExecutorTest.cpp.

668  {
669  removeThreadTest<IOThreadPoolExecutor>();
670 }
TEST ( ThreadPoolExecutorTest  ,
RemoveThreadTestCPU   
)

Definition at line 672 of file ThreadPoolExecutorTest.cpp.

672  {
673  removeThreadTest<CPUThreadPoolExecutor>();
674 }
TEST ( ThreadPoolExecutorTest  ,
resizeThreadWhileExecutingTestIO   
)

Definition at line 699 of file ThreadPoolExecutorTest.cpp.

699  {
700  resizeThreadWhileExecutingTest<IOThreadPoolExecutor>();
701 }
TEST ( ThreadPoolExecutorTest  ,
resizeThreadWhileExecutingTestCPU   
)

Definition at line 703 of file ThreadPoolExecutorTest.cpp.

703  {
704  resizeThreadWhileExecutingTest<CPUThreadPoolExecutor>();
705 }
TEST ( ThreadPoolExecutorTest  ,
KeepAliveTestIO   
)

Definition at line 723 of file ThreadPoolExecutorTest.cpp.

723  {
724  keepAliveTest<IOThreadPoolExecutor>();
725 }
TEST ( ThreadPoolExecutorTest  ,
KeepAliveTestCPU   
)

Definition at line 727 of file ThreadPoolExecutorTest.cpp.

727  {
728  keepAliveTest<CPUThreadPoolExecutor>();
729 }
TEST ( ThreadPoolExecutorTest  ,
registersToExecutorListTestIO   
)

Definition at line 752 of file ThreadPoolExecutorTest.cpp.

752  {
753  registersToExecutorListTest<IOThreadPoolExecutor>();
754 }
TEST ( ThreadPoolExecutorTest  ,
registersToExecutorListTestCPU   
)

Definition at line 756 of file ThreadPoolExecutorTest.cpp.

756  {
757  registersToExecutorListTest<CPUThreadPoolExecutor>();
758 }
TEST ( ThreadPoolExecutorTest  ,
testUsesNameFromNamedThreadFactoryIO   
)

Definition at line 767 of file ThreadPoolExecutorTest.cpp.

767  {
768  testUsesNameFromNamedThreadFactory<IOThreadPoolExecutor>();
769 }
TEST ( ThreadPoolExecutorTest  ,
testUsesNameFromNamedThreadFactoryCPU   
)

Definition at line 771 of file ThreadPoolExecutorTest.cpp.

771  {
772  testUsesNameFromNamedThreadFactory<CPUThreadPoolExecutor>();
773 }
TEST ( ThreadPoolExecutorTest  ,
DynamicThreadsTest   
)

Definition at line 775 of file ThreadPoolExecutorTest.cpp.

References folly::ThreadPoolExecutor::PoolStats::activeThreadCount, folly::CPUThreadPoolExecutor::add(), EXPECT_EQ, EXPECT_FALSE, folly::ThreadPoolExecutor::getPoolStats(), now(), folly::ThreadPoolExecutor::setThreadDeathTimeout(), folly::detail::spin_yield_until(), and folly::detail::success.

775  {
776  boost::barrier barrier{3};
777  auto twice_waiting_task = [&] { barrier.wait(), barrier.wait(); };
779  e.setThreadDeathTimeout(std::chrono::milliseconds(100));
780  e.add(twice_waiting_task);
781  e.add(twice_waiting_task);
782  barrier.wait(); // ensure both tasks are mid-flight
783  EXPECT_EQ(2, e.getPoolStats().activeThreadCount) << "sanity check";
784 
785  auto pred = [&] { return e.getPoolStats().activeThreadCount == 0; };
786  EXPECT_FALSE(pred()) << "sanity check";
787  barrier.wait(); // let both mid-flight tasks complete
788  EXPECT_EQ(
791  std::chrono::steady_clock::now() + std::chrono::seconds(1), pred));
792 }
spin_result spin_yield_until(std::chrono::time_point< Clock, Duration > const &deadline, F f)
Definition: Spin.h:70
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
std::chrono::steady_clock::time_point now()
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( ThreadPoolExecutorTest  ,
DynamicThreadAddRemoveRace   
)

Definition at line 794 of file ThreadPoolExecutorTest.cpp.

References folly::CPUThreadPoolExecutor::add(), b, count, EXPECT_EQ, i, folly::ThreadPoolExecutor::join(), folly::Baton< MayBlock, Atom >::post(), folly::ThreadPoolExecutor::setThreadDeathTimeout(), and folly::Baton< MayBlock, Atom >::wait().

794  {
796  e.setThreadDeathTimeout(std::chrono::milliseconds(0));
797  std::atomic<uint64_t> count{0};
798  for (int i = 0; i < 10000; i++) {
799  Baton<> b;
800  e.add([&]() {
801  count.fetch_add(1, std::memory_order_relaxed);
802  b.post();
803  });
804  b.wait();
805  }
806  e.join();
807  EXPECT_EQ(count, 10000);
808 }
char b
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
FOLLY_ALWAYS_INLINE void wait(const WaitOptions &opt=wait_options()) noexcept
Definition: Baton.h:170
void post() noexcept
Definition: Baton.h:123
int * count
TEST ( ThreadPoolExecutorTest  ,
AddPerf   
)

Definition at line 810 of file ThreadPoolExecutorTest.cpp.

References i, folly::make_unique(), and folly::gen::move.

810  {
811  auto queue = std::make_unique<
814  1000,
815  std::move(queue),
816  std::make_shared<NamedThreadFactory>("CPUThreadPool"));
817  e.setThreadDeathTimeout(std::chrono::milliseconds(1));
818  for (int i = 0; i < 10000; i++) {
819  e.add([&]() { e.add([]() { /* sleep override */ usleep(1000); }); });
820  }
821  e.stop();
822 }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::enable_if<!std::is_array< T >::value, std::unique_ptr< T > >::type make_unique(Args &&...args)
Definition: Memory.h:259
TEST ( ThreadPoolExecutorTest  ,
WeakRefTestIO   
)

Definition at line 886 of file ThreadPoolExecutorTest.cpp.

886  {
887  WeakRefTest<IOThreadPoolExecutor>();
888 }
TEST ( ThreadPoolExecutorTest  ,
WeakRefTestCPU   
)

Definition at line 890 of file ThreadPoolExecutorTest.cpp.

890  {
891  WeakRefTest<CPUThreadPoolExecutor>();
892 }
TEST ( ThreadPoolExecutorTest  ,
VirtualExecutorTestIO   
)

Definition at line 894 of file ThreadPoolExecutorTest.cpp.

894  {
895  virtualExecutorTest<IOThreadPoolExecutor>();
896 }
TEST ( ThreadPoolExecutorTest  ,
VirtualExecutorTestCPU   
)

Definition at line 898 of file ThreadPoolExecutorTest.cpp.

898  {
899  virtualExecutorTest<CPUThreadPoolExecutor>();
900 }
template<typename TPE >
static void testUsesNameFromNamedThreadFactory ( )
static

Definition at line 761 of file ThreadPoolExecutorTest.cpp.

References EXPECT_EQ.

761  {
762  auto ntf = std::make_shared<NamedThreadFactory>("my_executor");
763  TPE tpe(10, ntf);
764  EXPECT_EQ("my_executor", tpe.getName());
765 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
template<typename TPE >
static void virtualExecutorTest ( )
static

Definition at line 845 of file ThreadPoolExecutorTest.cpp.

References folly::VirtualExecutor::add(), counter, EXPECT_EQ, EXPECT_NO_THROW, EXPECT_TRUE, f, folly::gen::guard(), folly::makeGuard(), folly::gen::move, folly::futures::sleep(), and folly::via().

845  {
846  using namespace std::literals;
847 
849  int counter{0};
850  {
851  TPE fe(1);
852  {
853  VirtualExecutor ve(fe);
854  f = futures::sleep(100ms)
855  .via(&ve)
856  .thenValue([&](auto&&) {
857  ++counter;
858  return futures::sleep(100ms);
859  })
860  .via(&fe)
861  .thenValue([&](auto&&) { ++counter; })
862  .semi();
863  }
864  EXPECT_EQ(1, counter);
865 
866  bool functionDestroyed{false};
867  bool functionCalled{false};
868  {
869  VirtualExecutor ve(fe);
870  auto guard = makeGuard([&functionDestroyed] {
871  std::this_thread::sleep_for(100ms);
872  functionDestroyed = true;
873  });
874  ve.add([&functionCalled, guard = std::move(guard)] {
875  functionCalled = true;
876  });
877  }
878  EXPECT_TRUE(functionCalled);
879  EXPECT_TRUE(functionDestroyed);
880  }
881  EXPECT_TRUE(f->isReady());
882  EXPECT_NO_THROW(std::move(*f).get());
883  EXPECT_EQ(2, counter);
884 }
auto f
#define EXPECT_NO_THROW(statement)
Definition: gtest.h:1845
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Future< Unit > sleep(Duration dur, Timekeeper *tk)
Definition: Future.cpp:42
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
PUSHMI_INLINE_VAR constexpr detail::via_fn via
Definition: via.h:166
GuardImpl guard(ErrorHandler &&handler)
Definition: Base.h:840
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
FOLLY_NODISCARD detail::ScopeGuardImplDecay< F, true > makeGuard(F &&f) noexcept(noexcept(detail::ScopeGuardImplDecay< F, true >(static_cast< F && >(f))))
Definition: ScopeGuard.h:184
std::atomic< int > counter
template<typename TPE >
static void WeakRefTest ( )
static

Definition at line 825 of file ThreadPoolExecutorTest.cpp.

References burnMs(), counter, EXPECT_EQ, EXPECT_THROW, f, folly::makeFuture(), folly::gen::move, and folly::via().

825  {
826  // test that adding a .then() after we have
827  // started shutting down does not deadlock
829  int counter{0};
830  {
831  TPE fe(1);
832  f = folly::makeFuture()
833  .via(&fe)
834  .thenValue([](auto&&) { burnMs(100)(); })
835  .thenValue([&](auto&&) { ++counter; })
836  .via(fe.weakRef())
837  .thenValue([](auto&&) { burnMs(100)(); })
838  .thenValue([&](auto&&) { ++counter; });
839  }
841  EXPECT_EQ(1, counter);
842 }
auto f
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
PUSHMI_INLINE_VAR constexpr detail::via_fn via
Definition: via.h:166
static Func burnMs(uint64_t ms)
std::atomic< int > counter
Future< typename std::decay< T >::type > makeFuture(T &&t)
Definition: Future-inl.h:1310