proxygen
FibersTest.cpp File Reference

Go to the source code of this file.

Classes

struct  AtomicBatchDispatcherTesting::DevNullPiper
 
struct  AtomicBatchDispatcherTesting::Job
 

Namespaces

 AtomicBatchDispatcherTesting
 

Macros

#define ENABLE_TRACE_IN_TEST   0
 
#define OUTPUT_TRACE   devNullPiper
 
#define SET_UP_TEST_FUNC
 

Typedefs

using AtomicBatchDispatcherTesting::ValueT = size_t
 
using AtomicBatchDispatcherTesting::ResultT = std::string
 
using AtomicBatchDispatcherTesting::DispatchFunctionT = folly::Function< std::vector< ResultT >(std::vector< ValueT > &&)>
 

Enumerations

enum  AtomicBatchDispatcherTesting::DispatchProblem { AtomicBatchDispatcherTesting::DispatchProblem::None, AtomicBatchDispatcherTesting::DispatchProblem::PreprocessThrows, AtomicBatchDispatcherTesting::DispatchProblem::DuplicateDispatch }
 

Functions

 TEST (FiberManager, batonTimedWaitTimeout)
 
 TEST (FiberManager, batonTimedWaitPost)
 
 TEST (FiberManager, batonTimedWaitTimeoutEvb)
 
 TEST (FiberManager, batonTimedWaitPostEvb)
 
 TEST (FiberManager, batonTryWait)
 
 TEST (FiberManager, genericBatonFiberWait)
 
 TEST (FiberManager, genericBatonThreadWait)
 
 TEST (FiberManager, addTasksNoncopyable)
 
 TEST (FiberManager, awaitThrow)
 
 TEST (FiberManager, addTasksThrow)
 
 TEST (FiberManager, addTasksVoid)
 
 TEST (FiberManager, addTasksVoidThrow)
 
 TEST (FiberManager, addTasksReserve)
 
 TEST (FiberManager, addTaskDynamic)
 
 TEST (FiberManager, forEach)
 
 TEST (FiberManager, collectN)
 
 TEST (FiberManager, collectNThrow)
 
 TEST (FiberManager, collectNVoid)
 
 TEST (FiberManager, collectNVoidThrow)
 
 TEST (FiberManager, collectAll)
 
 TEST (FiberManager, collectAllVoid)
 
 TEST (FiberManager, collectAny)
 
 TEST (FiberManager, runInMainContext)
 
 TEST (FiberManager, addTaskFinally)
 
 TEST (FiberManager, fibersPoolWithinLimit)
 
 TEST (FiberManager, fibersPoolOverLimit)
 
 TEST (FiberManager, remoteFiberBasic)
 
 TEST (FiberManager, addTaskRemoteBasic)
 
 TEST (FiberManager, remoteHasTasks)
 
 TEST (FiberManager, remoteHasReadyTasks)
 
template<typename Data >
void testFiberLocal ()
 
 TEST (FiberManager, fiberLocal)
 
 TEST (FiberManager, fiberLocalHeap)
 
 TEST (FiberManager, fiberLocalDestructor)
 
 TEST (FiberManager, yieldTest)
 
 TEST (FiberManager, RequestContext)
 
 TEST (FiberManager, resizePeriodically)
 
 TEST (FiberManager, batonWaitTimeoutHandler)
 
 TEST (FiberManager, batonWaitTimeoutMany)
 
 TEST (FiberManager, remoteFutureTest)
 
 TEST (FiberManager, remoteFutureVoidUnitTest)
 
 TEST (FiberManager, nestedFiberManagers)
 
 TEST (FiberManager, semaphore)
 
template<typename ExecutorT >
void singleBatchDispatch (ExecutorT &executor, int batchSize, int index)
 
 TEST (FiberManager, batchDispatchTest)
 
template<typename ExecutorT >
folly::Future< std::vector< std::string > > doubleBatchInnerDispatch (ExecutorT &executor, int totalNumberOfElements, std::vector< int > input)
 
template<typename ExecutorT >
void doubleBatchOuterDispatch (ExecutorT &executor, int totalNumberOfElements, int index)
 
 TEST (FiberManager, doubleBatchDispatchTest)
 
template<typename ExecutorT >
void batchDispatchExceptionHandling (ExecutorT &executor, int i)
 
 TEST (FiberManager, batchDispatchExceptionHandlingTest)
 
ResultT AtomicBatchDispatcherTesting::processSingleInput (ValueT &&input)
 
std::vector< ResultT > AtomicBatchDispatcherTesting::userDispatchFunc (std::vector< ValueT > &&inputs)
 
void AtomicBatchDispatcherTesting::createJobs (AtomicBatchDispatcher< ValueT, ResultT > &atomicBatchDispatcher, std::vector< Job > &jobs, size_t count)
 
void AtomicBatchDispatcherTesting::dispatchJobs (FiberManager &executor, std::vector< Job > &jobs, std::vector< folly::Optional< folly::Future< ResultT >>> &results, DispatchProblem dispatchProblem=DispatchProblem::None, size_t problemIndex=size_t(-1))
 
void AtomicBatchDispatcherTesting::validateResult (std::vector< folly::Optional< folly::Future< ResultT >>> &results, size_t i)
 
template<typename TException >
void AtomicBatchDispatcherTesting::validateResults (std::vector< folly::Optional< folly::Future< ResultT >>> &results, size_t expectedNumResults)
 
 TEST (FiberManager, ABD_Test)
 
 TEST (FiberManager, ABD_DispatcherDestroyedBeforeCallingCommit)
 
 TEST (FiberManager, ABD_PreprocessingFailureTest)
 
 TEST (FiberManager, ABD_MultipleDispatchOnSameTokenErrorTest)
 
 TEST (FiberManager, ABD_GetTokenCalledAfterCommitTest)
 
 TEST (FiberManager, ABD_UserProvidedBatchDispatchThrowsTest)
 
 TEST (FiberManager, VirtualEventBase)
 
 TEST (TimedMutex, ThreadsAndFibersDontDeadlock)
 
 TEST (TimedMutex, ThreadFiberDeadlockOrder)
 
 TEST (TimedMutex, ThreadFiberDeadlockRace)
 
 TEST (FiberManager, highWaterMarkViaRecordStackEvery)
 
 TEST (FiberManager, highWaterMarkViaRecordCurrentPosition)
 

Variables

struct AtomicBatchDispatcherTesting::DevNullPiper AtomicBatchDispatcherTesting::devNullPiper
 

Macro Definition Documentation

#define ENABLE_TRACE_IN_TEST   0

Definition at line 1773 of file FibersTest.cpp.

#define OUTPUT_TRACE   devNullPiper
#define SET_UP_TEST_FUNC
Value:
using namespace AtomicBatchDispatcherTesting; \
folly::EventBase evb; \
auto& executor = getFiberManager(evb); \
const size_t COUNT = 11; \
std::vector<Job> jobs; \
jobs.reserve(COUNT); \
std::vector<folly::Optional<folly::Future<ResultT>>> results; \
results.reserve(COUNT); \
DispatchFunctionT dispatchFunc
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
folly::Function< std::vector< ResultT >(std::vector< ValueT > &&)> DispatchFunctionT
const
Definition: upload.py:398
FiberManager & getFiberManager(EventBase &evb, const FiberManager::Options &opts)

Definition at line 1930 of file FibersTest.cpp.

Referenced by TEST().

Function Documentation

template<typename ExecutorT >
void batchDispatchExceptionHandling ( ExecutorT &  executor,
int  i 
)

Definition at line 1742 of file FibersTest.cpp.

References EXPECT_THROW.

Referenced by TEST().

1742  {
1743  thread_local BatchDispatcher<int, int, ExecutorT> batchDispatcher(
1744  executor, [](std::vector<int> &&) -> std::vector<int> {
1745  throw std::runtime_error("Surprise!!");
1746  });
1747 
1748  EXPECT_THROW(batchDispatcher.add(i).get(), std::runtime_error);
1749 }
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
template<typename ExecutorT >
folly::Future<std::vector<std::string> > doubleBatchInnerDispatch ( ExecutorT &  executor,
int  totalNumberOfElements,
std::vector< int >  input 
)

Definition at line 1651 of file FibersTest.cpp.

References folly::fibers::BatchDispatcher< ValueT, ResultT, ExecutorT >::add(), folly::gen::batch(), EXPECT_EQ, folly::gen::move, and folly::unit.

Referenced by doubleBatchOuterDispatch().

1654  {
1655  thread_local BatchDispatcher<
1656  std::vector<int>,
1657  std::vector<std::string>,
1658  ExecutorT>
1659  batchDispatcher(executor, [=](std::vector<std::vector<int>>&& batch) {
1660  std::vector<std::vector<std::string>> results;
1661  int numberOfElements = 0;
1662  for (auto& unit : batch) {
1663  numberOfElements += unit.size();
1664  std::vector<std::string> result;
1665  for (auto& element : unit) {
1666  result.push_back(folly::to<std::string>(element));
1667  }
1668  results.push_back(std::move(result));
1669  }
1670  EXPECT_EQ(totalNumberOfElements, numberOfElements);
1671  return results;
1672  });
1673 
1674  return batchDispatcher.add(std::move(input));
1675 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Future< ResultT > add(ValueT value)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
detail::Batch batch(size_t batchSize)
Definition: Base-inl.h:2602
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
constexpr Unit unit
Definition: Unit.h:45
template<typename ExecutorT >
void doubleBatchOuterDispatch ( ExecutorT &  executor,
int  totalNumberOfElements,
int  index 
)

Batch values in groups of 5, and then call inner dispatch.

Definition at line 1681 of file FibersTest.cpp.

References folly::fibers::BatchDispatcher< ValueT, ResultT, ExecutorT >::add(), folly::gen::batch(), folly::collectAllSemiFuture(), doubleBatchInnerDispatch(), EXPECT_EQ, group, folly::gen::move, and folly::unit.

Referenced by TEST().

1684  {
1685  thread_local BatchDispatcher<int, std::string, ExecutorT> batchDispatcher(
1686  executor, [=, &executor](std::vector<int>&& batch) {
1687  EXPECT_EQ(totalNumberOfElements, batch.size());
1688  std::vector<std::string> results;
1689  std::vector<folly::Future<std::vector<std::string>>>
1690  innerDispatchResultFutures;
1691 
1692  std::vector<int> group;
1693  for (auto unit : batch) {
1694  group.push_back(unit);
1695  if (group.size() == 5) {
1696  auto localGroup = group;
1697  group.clear();
1698 
1699  innerDispatchResultFutures.push_back(doubleBatchInnerDispatch(
1700  executor, totalNumberOfElements, localGroup));
1701  }
1702  }
1703 
1705  innerDispatchResultFutures.begin(),
1706  innerDispatchResultFutures.end())
1707  .toUnsafeFuture()
1708  .then([&](std::vector<Try<std::vector<std::string>>>
1709  innerDispatchResults) {
1710  for (auto& unit : innerDispatchResults) {
1711  for (auto& element : unit.value()) {
1712  results.push_back(element);
1713  }
1714  }
1715  })
1716  .get();
1717  return results;
1718  });
1719 
1720  auto indexCopy = index;
1721  auto result = batchDispatcher.add(std::move(indexCopy));
1722  EXPECT_EQ(folly::to<std::string>(index), std::move(result).get());
1723 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Future< ResultT > add(ValueT value)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
folly::Future< std::vector< std::string > > doubleBatchInnerDispatch(ExecutorT &executor, int totalNumberOfElements, std::vector< int > input)
detail::Batch batch(size_t batchSize)
Definition: Base-inl.h:2602
SemiFuture< std::tuple< Try< typename remove_cvref_t< Fs >::value_type >... > > collectAllSemiFuture(Fs &&...fs)
Definition: Future-inl.h:1441
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
constexpr Unit unit
Definition: Unit.h:45
Definition: Try.h:51
Optional< NamedGroup > group
template<typename ExecutorT >
void singleBatchDispatch ( ExecutorT &  executor,
int  batchSize,
int  index 
)

Definition at line 1609 of file FibersTest.cpp.

References folly::fibers::BatchDispatcher< ValueT, ResultT, ExecutorT >::add(), folly::gen::batch(), EXPECT_EQ, and folly::gen::move.

Referenced by TEST().

1609  {
1610  thread_local BatchDispatcher<int, std::string, ExecutorT> batchDispatcher(
1611  executor, [=](std::vector<int>&& batch) {
1612  EXPECT_EQ(batchSize, batch.size());
1613  std::vector<std::string> results;
1614  for (auto& it : batch) {
1615  results.push_back(folly::to<std::string>(it));
1616  }
1617  return results;
1618  });
1619 
1620  auto indexCopy = index;
1621  auto result = batchDispatcher.add(std::move(indexCopy));
1622  EXPECT_EQ(folly::to<std::string>(index), std::move(result).get());
1623 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Future< ResultT > add(ValueT value)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
detail::Batch batch(size_t batchSize)
Definition: Base-inl.h:2602
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
TEST ( FiberManager  ,
batonTimedWaitTimeout   
)

Definition at line 43 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), EXPECT_EQ, EXPECT_FALSE, folly::fibers::FiberManager::loopController(), folly::gen::move, now(), and folly::fibers::Baton::try_wait_for().

43  {
44  bool taskAdded = false;
45  size_t iterations = 0;
46 
47  FiberManager manager(std::make_unique<SimpleLoopController>());
48  auto& loopController =
49  dynamic_cast<SimpleLoopController&>(manager.loopController());
50 
52  loopController.setTimeFunc([&] { return now; });
53 
54  auto loopFunc = [&]() {
55  if (!taskAdded) {
56  manager.addTask([&]() {
57  Baton baton;
58 
59  auto res = baton.try_wait_for(std::chrono::milliseconds(230));
60 
61  EXPECT_FALSE(res);
62  EXPECT_EQ(5, iterations);
63 
64  loopController.stop();
65  });
66  manager.addTask([&]() {
67  Baton baton;
68 
69  auto res = baton.try_wait_for(std::chrono::milliseconds(130));
70 
71  EXPECT_FALSE(res);
72  EXPECT_EQ(3, iterations);
73 
74  loopController.stop();
75  });
76  taskAdded = true;
77  } else {
78  now += std::chrono::milliseconds(50);
79  iterations++;
80  }
81  };
82 
83  loopController.loop(std::move(loopFunc));
84 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::chrono::steady_clock::time_point now()
Single-threaded task execution engine.
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
bool try_wait_for(const std::chrono::duration< Rep, Period > &timeout)
Definition: Baton.h:105
TEST ( FiberManager  ,
batonTimedWaitPost   
)

Definition at line 86 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), EXPECT_EQ, EXPECT_TRUE, folly::fibers::FiberManager::loopController(), folly::gen::move, folly::fibers::Baton::post(), and folly::fibers::Baton::try_wait_for().

86  {
87  bool taskAdded = false;
88  size_t iterations = 0;
89  Baton* baton_ptr;
90 
91  FiberManager manager(std::make_unique<SimpleLoopController>());
92  auto& loopController =
93  dynamic_cast<SimpleLoopController&>(manager.loopController());
94 
95  auto loopFunc = [&]() {
96  if (!taskAdded) {
97  manager.addTask([&]() {
98  Baton baton;
99  baton_ptr = &baton;
100 
101  auto res = baton.try_wait_for(std::chrono::milliseconds(130));
102 
103  EXPECT_TRUE(res);
104  EXPECT_EQ(2, iterations);
105 
106  loopController.stop();
107  });
108  taskAdded = true;
109  } else {
110  std::this_thread::sleep_for(std::chrono::milliseconds(50));
111  iterations++;
112  if (iterations == 2) {
113  baton_ptr->post();
114  }
115  }
116  };
117 
118  loopController.loop(std::move(loopFunc));
119 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
Single-threaded task execution engine.
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
bool try_wait_for(const std::chrono::duration< Rep, Period > &timeout)
Definition: Baton.h:105
TEST ( FiberManager  ,
batonTimedWaitTimeoutEvb   
)

Definition at line 121 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), EXPECT_EQ, EXPECT_FALSE, EXPECT_GT, EXPECT_LT, folly::fibers::FiberManager::loopController(), folly::EventBase::loopForever(), now(), folly::EventBase::runInEventBaseThread(), start, folly::EventBase::terminateLoopSoon(), and folly::fibers::Baton::try_wait_for().

121  {
122  size_t tasksComplete = 0;
123 
124  folly::EventBase evb;
125 
126  FiberManager manager(std::make_unique<EventBaseLoopController>());
127  dynamic_cast<EventBaseLoopController&>(manager.loopController())
128  .attachEventBase(evb);
129 
130  auto task = [&](size_t timeout_ms) {
131  Baton baton;
132 
134  auto res = baton.try_wait_for(std::chrono::milliseconds(timeout_ms));
135  auto finish = EventBaseLoopController::Clock::now();
136 
137  EXPECT_FALSE(res);
138 
139  auto duration_ms =
140  std::chrono::duration_cast<std::chrono::milliseconds>(finish - start);
141 
142  EXPECT_GT(duration_ms.count(), timeout_ms - 50);
143  EXPECT_LT(duration_ms.count(), timeout_ms + 50);
144 
145  if (++tasksComplete == 2) {
146  evb.terminateLoopSoon();
147  }
148  };
149 
150  evb.runInEventBaseThread([&]() {
151  manager.addTask([&]() { task(500); });
152  manager.addTask([&]() { task(250); });
153  });
154 
155  evb.loopForever();
156 
157  EXPECT_EQ(2, tasksComplete);
158 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
std::chrono::steady_clock::time_point now()
Single-threaded task execution engine.
void terminateLoopSoon()
Definition: EventBase.cpp:493
bool runInEventBaseThread(void(*fn)(T *), T *arg)
Definition: EventBase.h:794
auto start
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
#define EXPECT_LT(val1, val2)
Definition: gtest.h:1930
bool try_wait_for(const std::chrono::duration< Rep, Period > &timeout)
Definition: Baton.h:105
#define EXPECT_GT(val1, val2)
Definition: gtest.h:1934
TEST ( FiberManager  ,
batonTimedWaitPostEvb   
)

Definition at line 160 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), EXPECT_EQ, EXPECT_TRUE, folly::fibers::FiberManager::loopController(), folly::EventBase::loopForever(), now(), folly::fibers::Baton::post(), folly::EventBase::runInEventBaseThread(), start, folly::EventBase::terminateLoopSoon(), folly::fibers::Baton::try_wait_for(), and folly::TimeoutManager::tryRunAfterDelay().

160  {
161  size_t tasksComplete = 0;
162 
163  folly::EventBase evb;
164 
165  FiberManager manager(std::make_unique<EventBaseLoopController>());
166  dynamic_cast<EventBaseLoopController&>(manager.loopController())
167  .attachEventBase(evb);
168 
169  evb.runInEventBaseThread([&]() {
170  manager.addTask([&]() {
171  Baton baton;
172 
173  evb.tryRunAfterDelay([&]() { baton.post(); }, 100);
174 
176  auto res = baton.try_wait_for(std::chrono::milliseconds(130));
177  auto finish = EventBaseLoopController::Clock::now();
178 
179  EXPECT_TRUE(res);
180 
181  auto duration_ms =
182  std::chrono::duration_cast<std::chrono::milliseconds>(finish - start);
183 
184  EXPECT_TRUE(duration_ms.count() > 95 && duration_ms.count() < 110);
185 
186  if (++tasksComplete == 1) {
187  evb.terminateLoopSoon();
188  }
189  });
190  });
191 
192  evb.loopForever();
193 
194  EXPECT_EQ(1, tasksComplete);
195 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
std::chrono::steady_clock::time_point now()
bool tryRunAfterDelay(Func cob, uint32_t milliseconds, InternalEnum internal=InternalEnum::NORMAL)
Single-threaded task execution engine.
void terminateLoopSoon()
Definition: EventBase.cpp:493
bool runInEventBaseThread(void(*fn)(T *), T *arg)
Definition: EventBase.h:794
auto start
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
bool try_wait_for(const std::chrono::duration< Rep, Period > &timeout)
Definition: Baton.h:105
TEST ( FiberManager  ,
batonTryWait   
)

Definition at line 197 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), b, c, EXPECT_EQ, EXPECT_TRUE, folly::fibers::FiberManager::loopUntilNoReady(), folly::fibers::Baton::post(), and folly::fibers::Baton::try_wait().

197  {
198  FiberManager manager(std::make_unique<SimpleLoopController>());
199 
200  // Check if try_wait and post work as expected
201  Baton b;
202 
203  manager.addTask([&]() {
204  while (!b.try_wait()) {
205  }
206  });
207  auto thr = std::thread([&]() {
208  std::this_thread::sleep_for(std::chrono::milliseconds(300));
209  b.post();
210  });
211 
212  manager.loopUntilNoReady();
213  thr.join();
214 
215  Baton c;
216 
217  // Check try_wait without post
218  manager.addTask([&]() {
219  int cnt = 100;
220  while (cnt && !c.try_wait()) {
221  cnt--;
222  }
223  EXPECT_TRUE(!c.try_wait()); // must still hold
224  EXPECT_EQ(cnt, 0);
225  });
226 
227  manager.loopUntilNoReady();
228 }
char b
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Single-threaded task execution engine.
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
char c
TEST ( FiberManager  ,
genericBatonFiberWait   
)

Definition at line 230 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), b, EXPECT_EQ, EXPECT_FALSE, EXPECT_TRUE, folly::fibers::FiberManager::hasActiveFiber(), folly::fibers::FiberManager::loopUntilNoReady(), folly::fibers::Baton::post(), and folly::fibers::Baton::wait().

230  {
231  FiberManager manager(std::make_unique<SimpleLoopController>());
232 
233  GenericBaton b;
234  bool fiberRunning = false;
235 
236  manager.addTask([&]() {
237  EXPECT_EQ(manager.hasActiveFiber(), true);
238  fiberRunning = true;
239  b.wait();
240  fiberRunning = false;
241  });
242 
243  EXPECT_FALSE(fiberRunning);
244  manager.loopUntilNoReady();
245  EXPECT_TRUE(fiberRunning); // ensure fiber still active
246 
247  auto thr = std::thread([&]() {
248  std::this_thread::sleep_for(std::chrono::milliseconds(300));
249  b.post();
250  });
251 
252  while (fiberRunning) {
253  manager.loopUntilNoReady();
254  }
255 
256  thr.join();
257 }
char b
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Single-threaded task execution engine.
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( FiberManager  ,
genericBatonThreadWait   
)

Definition at line 259 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), b, EXPECT_EQ, EXPECT_TRUE, folly::fibers::FiberManager::hasActiveFiber(), folly::fibers::FiberManager::loopUntilNoReady(), folly::fibers::Baton::post(), and folly::fibers::Baton::wait().

259  {
260  FiberManager manager(std::make_unique<SimpleLoopController>());
261  GenericBaton b;
262  std::atomic<bool> threadWaiting(false);
263 
264  auto thr = std::thread([&]() {
265  threadWaiting = true;
266  b.wait();
267  threadWaiting = false;
268  });
269 
270  while (!threadWaiting) {
271  }
272  std::this_thread::sleep_for(std::chrono::milliseconds(300));
273 
274  manager.addTask([&]() {
275  EXPECT_EQ(manager.hasActiveFiber(), true);
276  EXPECT_TRUE(threadWaiting);
277  b.post();
278  while (threadWaiting) {
279  }
280  });
281 
282  manager.loopUntilNoReady();
283  thr.join();
284 }
char b
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Single-threaded task execution engine.
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
TEST ( FiberManager  ,
addTasksNoncopyable   
)

Definition at line 286 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), folly::fibers::addTasks(), folly::fibers::await(), EXPECT_EQ, EXPECT_GE, i, folly::fibers::FiberManager::loopController(), and folly::gen::move.

286  {
287  std::vector<Promise<int>> pendingFibers;
288  bool taskAdded = false;
289 
290  FiberManager manager(std::make_unique<SimpleLoopController>());
291  auto& loopController =
292  dynamic_cast<SimpleLoopController&>(manager.loopController());
293 
294  auto loopFunc = [&]() {
295  if (!taskAdded) {
296  manager.addTask([&]() {
297  std::vector<std::function<std::unique_ptr<int>()>> funcs;
298  for (int i = 0; i < 3; ++i) {
299  funcs.push_back([i, &pendingFibers]() {
300  await([&pendingFibers](Promise<int> promise) {
301  pendingFibers.push_back(std::move(promise));
302  });
303  return std::make_unique<int>(i * 2 + 1);
304  });
305  }
306 
307  auto iter = addTasks(funcs.begin(), funcs.end());
308 
309  size_t n = 0;
310  while (iter.hasNext()) {
311  auto result = iter.awaitNext();
312  EXPECT_EQ(2 * iter.getTaskID() + 1, *result);
313  EXPECT_GE(2 - n, pendingFibers.size());
314  ++n;
315  }
316  EXPECT_EQ(3, n);
317  });
318  taskAdded = true;
319  } else if (pendingFibers.size()) {
320  pendingFibers.back().setValue(0);
321  pendingFibers.pop_back();
322  } else {
323  loopController.stop();
324  }
325  };
326 
327  loopController.loop(std::move(loopFunc));
328 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
#define EXPECT_GE(val1, val2)
Definition: gtest.h:1932
Single-threaded task execution engine.
TaskIterator< invoke_result_t< typename std::iterator_traits< InputIterator >::value_type > > addTasks(InputIterator first, InputIterator last)
Definition: AddTasks-inl.h:114
FirstArgOf< F >::type::value_type await(F &&func)
TEST ( FiberManager  ,
awaitThrow   
)

Definition at line 330 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTaskFuture(), folly::fibers::await(), EXPECT_THROW, folly::fibers::getFiberManager(), folly::gen::move, folly::EventBase::runInEventBaseThread(), and folly::fibers::Promise< T, BatonT >::setValue().

330  {
331  folly::EventBase evb;
332  struct ExpectedException {};
333  getFiberManager(evb)
334  .addTaskFuture([&] {
335  EXPECT_THROW(
336  await([](Promise<int> p) {
337  p.setValue(42);
338  throw ExpectedException();
339  }),
340  ExpectedException);
341 
342  EXPECT_THROW(
343  await([&](Promise<int> p) {
345  [p = std::move(p)]() mutable { p.setValue(42); });
346  throw ExpectedException();
347  }),
348  ExpectedException);
349  })
350  .waitVia(&evb);
351 }
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
auto addTaskFuture(F &&func) -> folly::Future< typename folly::lift_unit< invoke_result_t< F >>::type >
bool runInEventBaseThread(void(*fn)(T *), T *arg)
Definition: EventBase.h:794
FirstArgOf< F >::type::value_type await(F &&func)
FiberManager & getFiberManager(EventBase &evb, const FiberManager::Options &opts)
TEST ( FiberManager  ,
addTasksThrow   
)

Definition at line 353 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), folly::fibers::addTasks(), folly::fibers::await(), EXPECT_EQ, EXPECT_GE, i, folly::fibers::FiberManager::loopController(), and folly::gen::move.

353  {
354  std::vector<Promise<int>> pendingFibers;
355  bool taskAdded = false;
356 
357  FiberManager manager(std::make_unique<SimpleLoopController>());
358  auto& loopController =
359  dynamic_cast<SimpleLoopController&>(manager.loopController());
360 
361  auto loopFunc = [&]() {
362  if (!taskAdded) {
363  manager.addTask([&]() {
364  std::vector<std::function<int()>> funcs;
365  for (size_t i = 0; i < 3; ++i) {
366  funcs.push_back([i, &pendingFibers]() {
367  await([&pendingFibers](Promise<int> promise) {
368  pendingFibers.push_back(std::move(promise));
369  });
370  if (i % 2 == 0) {
371  throw std::runtime_error("Runtime");
372  }
373  return i * 2 + 1;
374  });
375  }
376 
377  auto iter = addTasks(funcs.begin(), funcs.end());
378 
379  size_t n = 0;
380  while (iter.hasNext()) {
381  try {
382  int result = iter.awaitNext();
383  EXPECT_EQ(1, iter.getTaskID() % 2);
384  EXPECT_EQ(2 * iter.getTaskID() + 1, result);
385  } catch (...) {
386  EXPECT_EQ(0, iter.getTaskID() % 2);
387  }
388  EXPECT_GE(2 - n, pendingFibers.size());
389  ++n;
390  }
391  EXPECT_EQ(3, n);
392  });
393  taskAdded = true;
394  } else if (pendingFibers.size()) {
395  pendingFibers.back().setValue(0);
396  pendingFibers.pop_back();
397  } else {
398  loopController.stop();
399  }
400  };
401 
402  loopController.loop(std::move(loopFunc));
403 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
#define EXPECT_GE(val1, val2)
Definition: gtest.h:1932
Single-threaded task execution engine.
TaskIterator< invoke_result_t< typename std::iterator_traits< InputIterator >::value_type > > addTasks(InputIterator first, InputIterator last)
Definition: AddTasks-inl.h:114
FirstArgOf< F >::type::value_type await(F &&func)
TEST ( FiberManager  ,
addTasksVoid   
)

Definition at line 405 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), folly::fibers::addTasks(), folly::fibers::await(), EXPECT_EQ, EXPECT_GE, i, folly::fibers::FiberManager::loopController(), and folly::gen::move.

405  {
406  std::vector<Promise<int>> pendingFibers;
407  bool taskAdded = false;
408 
409  FiberManager manager(std::make_unique<SimpleLoopController>());
410  auto& loopController =
411  dynamic_cast<SimpleLoopController&>(manager.loopController());
412 
413  auto loopFunc = [&]() {
414  if (!taskAdded) {
415  manager.addTask([&]() {
416  std::vector<std::function<void()>> funcs;
417  for (size_t i = 0; i < 3; ++i) {
418  funcs.push_back([&pendingFibers]() {
419  await([&pendingFibers](Promise<int> promise) {
420  pendingFibers.push_back(std::move(promise));
421  });
422  });
423  }
424 
425  auto iter = addTasks(funcs.begin(), funcs.end());
426 
427  size_t n = 0;
428  while (iter.hasNext()) {
429  iter.awaitNext();
430  EXPECT_GE(2 - n, pendingFibers.size());
431  ++n;
432  }
433  EXPECT_EQ(3, n);
434  });
435  taskAdded = true;
436  } else if (pendingFibers.size()) {
437  pendingFibers.back().setValue(0);
438  pendingFibers.pop_back();
439  } else {
440  loopController.stop();
441  }
442  };
443 
444  loopController.loop(std::move(loopFunc));
445 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
#define EXPECT_GE(val1, val2)
Definition: gtest.h:1932
Single-threaded task execution engine.
TaskIterator< invoke_result_t< typename std::iterator_traits< InputIterator >::value_type > > addTasks(InputIterator first, InputIterator last)
Definition: AddTasks-inl.h:114
FirstArgOf< F >::type::value_type await(F &&func)
TEST ( FiberManager  ,
addTasksVoidThrow   
)

Definition at line 447 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), folly::fibers::addTasks(), folly::fibers::await(), EXPECT_EQ, EXPECT_GE, i, folly::fibers::FiberManager::loopController(), and folly::gen::move.

447  {
448  std::vector<Promise<int>> pendingFibers;
449  bool taskAdded = false;
450 
451  FiberManager manager(std::make_unique<SimpleLoopController>());
452  auto& loopController =
453  dynamic_cast<SimpleLoopController&>(manager.loopController());
454 
455  auto loopFunc = [&]() {
456  if (!taskAdded) {
457  manager.addTask([&]() {
458  std::vector<std::function<void()>> funcs;
459  for (size_t i = 0; i < 3; ++i) {
460  funcs.push_back([i, &pendingFibers]() {
461  await([&pendingFibers](Promise<int> promise) {
462  pendingFibers.push_back(std::move(promise));
463  });
464  if (i % 2 == 0) {
465  throw std::runtime_error("");
466  }
467  });
468  }
469 
470  auto iter = addTasks(funcs.begin(), funcs.end());
471 
472  size_t n = 0;
473  while (iter.hasNext()) {
474  try {
475  iter.awaitNext();
476  EXPECT_EQ(1, iter.getTaskID() % 2);
477  } catch (...) {
478  EXPECT_EQ(0, iter.getTaskID() % 2);
479  }
480  EXPECT_GE(2 - n, pendingFibers.size());
481  ++n;
482  }
483  EXPECT_EQ(3, n);
484  });
485  taskAdded = true;
486  } else if (pendingFibers.size()) {
487  pendingFibers.back().setValue(0);
488  pendingFibers.pop_back();
489  } else {
490  loopController.stop();
491  }
492  };
493 
494  loopController.loop(std::move(loopFunc));
495 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
#define EXPECT_GE(val1, val2)
Definition: gtest.h:1932
Single-threaded task execution engine.
TaskIterator< invoke_result_t< typename std::iterator_traits< InputIterator >::value_type > > addTasks(InputIterator first, InputIterator last)
Definition: AddTasks-inl.h:114
FirstArgOf< F >::type::value_type await(F &&func)
TEST ( FiberManager  ,
addTasksReserve   
)

Definition at line 497 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), folly::fibers::addTasks(), folly::fibers::await(), EXPECT_FALSE, EXPECT_TRUE, i, folly::fibers::FiberManager::loopController(), and folly::gen::move.

497  {
498  std::vector<Promise<int>> pendingFibers;
499  bool taskAdded = false;
500 
501  FiberManager manager(std::make_unique<SimpleLoopController>());
502  auto& loopController =
503  dynamic_cast<SimpleLoopController&>(manager.loopController());
504 
505  auto loopFunc = [&]() {
506  if (!taskAdded) {
507  manager.addTask([&]() {
508  std::vector<std::function<void()>> funcs;
509  for (size_t i = 0; i < 3; ++i) {
510  funcs.push_back([&pendingFibers]() {
511  await([&pendingFibers](Promise<int> promise) {
512  pendingFibers.push_back(std::move(promise));
513  });
514  });
515  }
516 
517  auto iter = addTasks(funcs.begin(), funcs.end());
518 
519  iter.reserve(2);
520  EXPECT_TRUE(iter.hasCompleted());
521  EXPECT_TRUE(iter.hasPending());
522  EXPECT_TRUE(iter.hasNext());
523 
524  iter.awaitNext();
525  EXPECT_TRUE(iter.hasCompleted());
526  EXPECT_TRUE(iter.hasPending());
527  EXPECT_TRUE(iter.hasNext());
528 
529  iter.awaitNext();
530  EXPECT_FALSE(iter.hasCompleted());
531  EXPECT_TRUE(iter.hasPending());
532  EXPECT_TRUE(iter.hasNext());
533 
534  iter.awaitNext();
535  EXPECT_FALSE(iter.hasCompleted());
536  EXPECT_FALSE(iter.hasPending());
537  EXPECT_FALSE(iter.hasNext());
538  });
539  taskAdded = true;
540  } else if (pendingFibers.size()) {
541  pendingFibers.back().setValue(0);
542  pendingFibers.pop_back();
543  } else {
544  loopController.stop();
545  }
546  };
547 
548  loopController.loop(std::move(loopFunc));
549 }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
Single-threaded task execution engine.
TaskIterator< invoke_result_t< typename std::iterator_traits< InputIterator >::value_type > > addTasks(InputIterator first, InputIterator last)
Definition: AddTasks-inl.h:114
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
FirstArgOf< F >::type::value_type await(F &&func)
TEST ( FiberManager  ,
addTaskDynamic   
)

Definition at line 551 of file FibersTest.cpp.

References folly::fibers::TaskIterator< T >::addTask(), folly::fibers::FiberManager::addTaskFuture(), folly::fibers::TaskIterator< T >::awaitNext(), EXPECT_EQ, folly::fibers::getFiberManager(), folly::fibers::Baton::post(), and folly::fibers::Baton::wait().

551  {
552  folly::EventBase evb;
553 
554  Baton batons[3];
555 
556  auto makeTask = [&](size_t taskId) {
557  return [&, taskId]() -> size_t {
558  batons[taskId].wait();
559  return taskId;
560  };
561  };
562 
563  getFiberManager(evb)
564  .addTaskFuture([&]() {
565  TaskIterator<size_t> iterator;
566 
567  iterator.addTask(makeTask(0));
568  iterator.addTask(makeTask(1));
569 
570  batons[1].post();
571 
572  EXPECT_EQ(1, iterator.awaitNext());
573 
574  iterator.addTask(makeTask(2));
575 
576  batons[2].post();
577 
578  EXPECT_EQ(2, iterator.awaitNext());
579 
580  batons[0].post();
581 
582  EXPECT_EQ(0, iterator.awaitNext());
583  })
584  .waitVia(&evb);
585 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
auto addTaskFuture(F &&func) -> folly::Future< typename folly::lift_unit< invoke_result_t< F >>::type >
FiberManager & getFiberManager(EventBase &evb, const FiberManager::Options &opts)
TEST ( FiberManager  ,
forEach   
)

Definition at line 587 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), folly::fibers::await(), EXPECT_EQ, EXPECT_TRUE, folly::gen::first, folly::fibers::forEach(), i, folly::fibers::FiberManager::loopController(), and folly::gen::move.

587  {
588  std::vector<Promise<int>> pendingFibers;
589  bool taskAdded = false;
590 
591  FiberManager manager(std::make_unique<SimpleLoopController>());
592  auto& loopController =
593  dynamic_cast<SimpleLoopController&>(manager.loopController());
594 
595  auto loopFunc = [&]() {
596  if (!taskAdded) {
597  manager.addTask([&]() {
598  std::vector<std::function<int()>> funcs;
599  for (size_t i = 0; i < 3; ++i) {
600  funcs.push_back([i, &pendingFibers]() {
601  await([&pendingFibers](Promise<int> promise) {
602  pendingFibers.push_back(std::move(promise));
603  });
604  return i * 2 + 1;
605  });
606  }
607 
608  std::vector<std::pair<size_t, int>> results;
609  forEach(funcs.begin(), funcs.end(), [&results](size_t id, int result) {
610  results.emplace_back(id, result);
611  });
612  EXPECT_EQ(3, results.size());
613  EXPECT_TRUE(pendingFibers.empty());
614  for (size_t i = 0; i < 3; ++i) {
615  EXPECT_EQ(results[i].first * 2 + 1, results[i].second);
616  }
617  });
618  taskAdded = true;
619  } else if (pendingFibers.size()) {
620  pendingFibers.back().setValue(0);
621  pendingFibers.pop_back();
622  } else {
623  loopController.stop();
624  }
625  };
626 
627  loopController.loop(std::move(loopFunc));
628 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
Single-threaded task execution engine.
void forEach(InputIterator first, InputIterator last, F &&f)
Definition: ForEach-inl.h:41
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
constexpr detail::First first
Definition: Base-inl.h:2553
FirstArgOf< F >::type::value_type await(F &&func)
TEST ( FiberManager  ,
collectN   
)

Definition at line 630 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), folly::fibers::await(), folly::fibers::collectN(), EXPECT_EQ, folly::gen::first, i, folly::fibers::FiberManager::loopController(), and folly::gen::move.

630  {
631  std::vector<Promise<int>> pendingFibers;
632  bool taskAdded = false;
633 
634  FiberManager manager(std::make_unique<SimpleLoopController>());
635  auto& loopController =
636  dynamic_cast<SimpleLoopController&>(manager.loopController());
637 
638  auto loopFunc = [&]() {
639  if (!taskAdded) {
640  manager.addTask([&]() {
641  std::vector<std::function<int()>> funcs;
642  for (size_t i = 0; i < 3; ++i) {
643  funcs.push_back([i, &pendingFibers]() {
644  await([&pendingFibers](Promise<int> promise) {
645  pendingFibers.push_back(std::move(promise));
646  });
647  return i * 2 + 1;
648  });
649  }
650 
651  auto results = collectN(funcs.begin(), funcs.end(), 2);
652  EXPECT_EQ(2, results.size());
653  EXPECT_EQ(1, pendingFibers.size());
654  for (size_t i = 0; i < 2; ++i) {
655  EXPECT_EQ(results[i].first * 2 + 1, results[i].second);
656  }
657  });
658  taskAdded = true;
659  } else if (pendingFibers.size()) {
660  pendingFibers.back().setValue(0);
661  pendingFibers.pop_back();
662  } else {
663  loopController.stop();
664  }
665  };
666 
667  loopController.loop(std::move(loopFunc));
668 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::vector< typename std::enable_if< !std::is_same< invoke_result_t< typename std::iterator_traits< InputIterator >::value_type >, void >::value, typename std::pair< size_t, invoke_result_t< typename std::iterator_traits< InputIterator >::value_type > > >::type > collectN(InputIterator first, InputIterator last, size_t n)
Definition: WhenN-inl.h:34
Single-threaded task execution engine.
constexpr detail::First first
Definition: Base-inl.h:2553
FirstArgOf< F >::type::value_type await(F &&func)
TEST ( FiberManager  ,
collectNThrow   
)

Definition at line 670 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), folly::fibers::await(), folly::fibers::collectN(), EXPECT_EQ, i, folly::fibers::FiberManager::loopController(), and folly::gen::move.

670  {
671  std::vector<Promise<int>> pendingFibers;
672  bool taskAdded = false;
673 
674  FiberManager manager(std::make_unique<SimpleLoopController>());
675  auto& loopController =
676  dynamic_cast<SimpleLoopController&>(manager.loopController());
677 
678  auto loopFunc = [&]() {
679  if (!taskAdded) {
680  manager.addTask([&]() {
681  std::vector<std::function<int()>> funcs;
682  for (size_t i = 0; i < 3; ++i) {
683  funcs.push_back([&pendingFibers]() -> size_t {
684  await([&pendingFibers](Promise<int> promise) {
685  pendingFibers.push_back(std::move(promise));
686  });
687  throw std::runtime_error("Runtime");
688  });
689  }
690 
691  try {
692  collectN(funcs.begin(), funcs.end(), 2);
693  } catch (...) {
694  EXPECT_EQ(1, pendingFibers.size());
695  }
696  });
697  taskAdded = true;
698  } else if (pendingFibers.size()) {
699  pendingFibers.back().setValue(0);
700  pendingFibers.pop_back();
701  } else {
702  loopController.stop();
703  }
704  };
705 
706  loopController.loop(std::move(loopFunc));
707 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::vector< typename std::enable_if< !std::is_same< invoke_result_t< typename std::iterator_traits< InputIterator >::value_type >, void >::value, typename std::pair< size_t, invoke_result_t< typename std::iterator_traits< InputIterator >::value_type > > >::type > collectN(InputIterator first, InputIterator last, size_t n)
Definition: WhenN-inl.h:34
Single-threaded task execution engine.
FirstArgOf< F >::type::value_type await(F &&func)
TEST ( FiberManager  ,
collectNVoid   
)

Definition at line 709 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), folly::fibers::await(), folly::fibers::collectN(), EXPECT_EQ, i, folly::fibers::FiberManager::loopController(), and folly::gen::move.

709  {
710  std::vector<Promise<int>> pendingFibers;
711  bool taskAdded = false;
712 
713  FiberManager manager(std::make_unique<SimpleLoopController>());
714  auto& loopController =
715  dynamic_cast<SimpleLoopController&>(manager.loopController());
716 
717  auto loopFunc = [&]() {
718  if (!taskAdded) {
719  manager.addTask([&]() {
720  std::vector<std::function<void()>> funcs;
721  for (size_t i = 0; i < 3; ++i) {
722  funcs.push_back([&pendingFibers]() {
723  await([&pendingFibers](Promise<int> promise) {
724  pendingFibers.push_back(std::move(promise));
725  });
726  });
727  }
728 
729  auto results = collectN(funcs.begin(), funcs.end(), 2);
730  EXPECT_EQ(2, results.size());
731  EXPECT_EQ(1, pendingFibers.size());
732  });
733  taskAdded = true;
734  } else if (pendingFibers.size()) {
735  pendingFibers.back().setValue(0);
736  pendingFibers.pop_back();
737  } else {
738  loopController.stop();
739  }
740  };
741 
742  loopController.loop(std::move(loopFunc));
743 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::vector< typename std::enable_if< !std::is_same< invoke_result_t< typename std::iterator_traits< InputIterator >::value_type >, void >::value, typename std::pair< size_t, invoke_result_t< typename std::iterator_traits< InputIterator >::value_type > > >::type > collectN(InputIterator first, InputIterator last, size_t n)
Definition: WhenN-inl.h:34
Single-threaded task execution engine.
FirstArgOf< F >::type::value_type await(F &&func)
TEST ( FiberManager  ,
collectNVoidThrow   
)

Definition at line 745 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), folly::fibers::await(), folly::fibers::collectN(), EXPECT_EQ, i, folly::fibers::FiberManager::loopController(), and folly::gen::move.

745  {
746  std::vector<Promise<int>> pendingFibers;
747  bool taskAdded = false;
748 
749  FiberManager manager(std::make_unique<SimpleLoopController>());
750  auto& loopController =
751  dynamic_cast<SimpleLoopController&>(manager.loopController());
752 
753  auto loopFunc = [&]() {
754  if (!taskAdded) {
755  manager.addTask([&]() {
756  std::vector<std::function<void()>> funcs;
757  for (size_t i = 0; i < 3; ++i) {
758  funcs.push_back([&pendingFibers]() {
759  await([&pendingFibers](Promise<int> promise) {
760  pendingFibers.push_back(std::move(promise));
761  });
762  throw std::runtime_error("Runtime");
763  });
764  }
765 
766  try {
767  collectN(funcs.begin(), funcs.end(), 2);
768  } catch (...) {
769  EXPECT_EQ(1, pendingFibers.size());
770  }
771  });
772  taskAdded = true;
773  } else if (pendingFibers.size()) {
774  pendingFibers.back().setValue(0);
775  pendingFibers.pop_back();
776  } else {
777  loopController.stop();
778  }
779  };
780 
781  loopController.loop(std::move(loopFunc));
782 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::vector< typename std::enable_if< !std::is_same< invoke_result_t< typename std::iterator_traits< InputIterator >::value_type >, void >::value, typename std::pair< size_t, invoke_result_t< typename std::iterator_traits< InputIterator >::value_type > > >::type > collectN(InputIterator first, InputIterator last, size_t n)
Definition: WhenN-inl.h:34
Single-threaded task execution engine.
FirstArgOf< F >::type::value_type await(F &&func)
TEST ( FiberManager  ,
collectAll   
)

Definition at line 784 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), folly::fibers::await(), folly::fibers::collectAll(), EXPECT_EQ, EXPECT_TRUE, i, folly::fibers::FiberManager::loopController(), and folly::gen::move.

784  {
785  std::vector<Promise<int>> pendingFibers;
786  bool taskAdded = false;
787 
788  FiberManager manager(std::make_unique<SimpleLoopController>());
789  auto& loopController =
790  dynamic_cast<SimpleLoopController&>(manager.loopController());
791 
792  auto loopFunc = [&]() {
793  if (!taskAdded) {
794  manager.addTask([&]() {
795  std::vector<std::function<int()>> funcs;
796  for (size_t i = 0; i < 3; ++i) {
797  funcs.push_back([i, &pendingFibers]() {
798  await([&pendingFibers](Promise<int> promise) {
799  pendingFibers.push_back(std::move(promise));
800  });
801  return i * 2 + 1;
802  });
803  }
804 
805  auto results = collectAll(funcs.begin(), funcs.end());
806  EXPECT_TRUE(pendingFibers.empty());
807  for (size_t i = 0; i < 3; ++i) {
808  EXPECT_EQ(i * 2 + 1, results[i]);
809  }
810  });
811  taskAdded = true;
812  } else if (pendingFibers.size()) {
813  pendingFibers.back().setValue(0);
814  pendingFibers.pop_back();
815  } else {
816  loopController.stop();
817  }
818  };
819 
820  loopController.loop(std::move(loopFunc));
821 }
std::vector< typename std::enable_if< !std::is_same< invoke_result_t< typename std::iterator_traits< InputIterator >::value_type >, void >::value, invoke_result_t< typename std::iterator_traits< InputIterator >::value_type > >::type > collectAll(InputIterator first, InputIterator last)
Definition: WhenN-inl.h:147
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
Single-threaded task execution engine.
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
FirstArgOf< F >::type::value_type await(F &&func)
TEST ( FiberManager  ,
collectAllVoid   
)

Definition at line 823 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), folly::fibers::await(), folly::fibers::collectAll(), EXPECT_TRUE, i, folly::fibers::FiberManager::loopController(), and folly::gen::move.

823  {
824  std::vector<Promise<int>> pendingFibers;
825  bool taskAdded = false;
826 
827  FiberManager manager(std::make_unique<SimpleLoopController>());
828  auto& loopController =
829  dynamic_cast<SimpleLoopController&>(manager.loopController());
830 
831  auto loopFunc = [&]() {
832  if (!taskAdded) {
833  manager.addTask([&]() {
834  std::vector<std::function<void()>> funcs;
835  for (size_t i = 0; i < 3; ++i) {
836  funcs.push_back([&pendingFibers]() {
837  await([&pendingFibers](Promise<int> promise) {
838  pendingFibers.push_back(std::move(promise));
839  });
840  });
841  }
842 
843  collectAll(funcs.begin(), funcs.end());
844  EXPECT_TRUE(pendingFibers.empty());
845  });
846  taskAdded = true;
847  } else if (pendingFibers.size()) {
848  pendingFibers.back().setValue(0);
849  pendingFibers.pop_back();
850  } else {
851  loopController.stop();
852  }
853  };
854 
855  loopController.loop(std::move(loopFunc));
856 }
std::vector< typename std::enable_if< !std::is_same< invoke_result_t< typename std::iterator_traits< InputIterator >::value_type >, void >::value, invoke_result_t< typename std::iterator_traits< InputIterator >::value_type > >::type > collectAll(InputIterator first, InputIterator last)
Definition: WhenN-inl.h:147
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
Single-threaded task execution engine.
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
FirstArgOf< F >::type::value_type await(F &&func)
TEST ( FiberManager  ,
collectAny   
)

Definition at line 858 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), folly::fibers::await(), folly::fibers::collectAny(), EXPECT_EQ, EXPECT_FALSE, EXPECT_GT, EXPECT_LT, i, folly::kIsSanitizeAddress, folly::fibers::FiberManager::loopController(), and folly::gen::move.

858  {
859  std::vector<Promise<int>> pendingFibers;
860  bool taskAdded = false;
861 
862  FiberManager manager(std::make_unique<SimpleLoopController>());
863  auto& loopController =
864  dynamic_cast<SimpleLoopController&>(manager.loopController());
865 
866  auto loopFunc = [&]() {
867  if (!taskAdded) {
868  manager.addTask([&]() {
869  std::vector<std::function<int()>> funcs;
870  for (size_t i = 0; i < 3; ++i) {
871  funcs.push_back([i, &pendingFibers]() {
872  await([&pendingFibers](Promise<int> promise) {
873  pendingFibers.push_back(std::move(promise));
874  });
875  if (i == 1) {
876  throw std::runtime_error("This exception will be ignored");
877  }
878  return i * 2 + 1;
879  });
880  }
881 
882  auto result = collectAny(funcs.begin(), funcs.end());
883  EXPECT_EQ(2, pendingFibers.size());
884  EXPECT_EQ(2, result.first);
885  EXPECT_EQ(2 * 2 + 1, result.second);
886  });
887  taskAdded = true;
888  } else if (pendingFibers.size()) {
889  pendingFibers.back().setValue(0);
890  pendingFibers.pop_back();
891  } else {
892  loopController.stop();
893  }
894  };
895 
896  loopController.loop(std::move(loopFunc));
897 }
std::enable_if< !std::is_same< invoke_result_t< typename std::iterator_traits< InputIterator >::value_type >, void >::value, typename std::pair< size_t, invoke_result_t< typename std::iterator_traits< InputIterator >::value_type > > >::type collectAny(InputIterator first, InputIterator last)
Definition: WhenN-inl.h:192
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
Single-threaded task execution engine.
FirstArgOf< F >::type::value_type await(F &&func)
TEST ( FiberManager  ,
runInMainContext   
)

Definition at line 927 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), EXPECT_EQ, EXPECT_TRUE, folly::fibers::FiberManager::loopController(), folly::fibers::FiberManager::runInMainContext(), folly::fibers::runInMainContext(), and folly::value().

927  {
928  FiberManager manager(std::make_unique<SimpleLoopController>());
929  auto& loopController =
930  dynamic_cast<SimpleLoopController&>(manager.loopController());
931 
932  bool checkRan = false;
933 
934  int mainLocation;
935  manager.runInMainContext(
936  [&]() { expectMainContext(checkRan, &mainLocation, nullptr); });
937  EXPECT_TRUE(checkRan);
938 
939  checkRan = false;
940 
941  manager.addTask([&]() {
942  struct A {
943  explicit A(int value_) : value(value_) {}
944  A(const A&) = delete;
945  A(A&&) = default;
946 
947  int value;
948  };
949  int stackLocation;
950  auto ret = runInMainContext([&]() {
951  expectMainContext(checkRan, &mainLocation, &stackLocation);
952  return A(42);
953  });
954  EXPECT_TRUE(checkRan);
955  EXPECT_EQ(42, ret.value);
956  });
957 
958  loopController.loop([&]() { loopController.stop(); });
959 
960  EXPECT_TRUE(checkRan);
961 }
std::unique_ptr< int > A
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Single-threaded task execution engine.
static const char *const value
Definition: Conv.cpp:50
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
invoke_result_t< F > runInMainContext(F &&func)
TEST ( FiberManager  ,
addTaskFinally   
)

Definition at line 963 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTaskFinally(), EXPECT_EQ, EXPECT_FALSE, EXPECT_TRUE, and folly::fibers::FiberManager::loopController().

963  {
964  FiberManager manager(std::make_unique<SimpleLoopController>());
965  auto& loopController =
966  dynamic_cast<SimpleLoopController&>(manager.loopController());
967 
968  bool checkRan = false;
969 
970  int mainLocation;
971 
972  manager.addTaskFinally(
973  [&]() { return 1234; },
974  [&](Try<int>&& result) {
975  EXPECT_EQ(result.value(), 1234);
976 
977  expectMainContext(checkRan, &mainLocation, nullptr);
978  });
979 
980  EXPECT_FALSE(checkRan);
981 
982  loopController.loop([&]() { loopController.stop(); });
983 
984  EXPECT_TRUE(checkRan);
985 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Single-threaded task execution engine.
Definition: Try.h:51
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( FiberManager  ,
fibersPoolWithinLimit   
)

Definition at line 987 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), EXPECT_EQ, folly::fibers::FiberManager::fibersAllocated(), folly::fibers::FiberManager::fibersPoolSize(), i, folly::fibers::FiberManager::loopController(), and folly::fibers::FiberManager::Options::maxFibersPoolSize.

987  {
989  opts.maxFibersPoolSize = 5;
990 
991  FiberManager manager(std::make_unique<SimpleLoopController>(), opts);
992  auto& loopController =
993  dynamic_cast<SimpleLoopController&>(manager.loopController());
994 
995  size_t fibersRun = 0;
996 
997  for (size_t i = 0; i < 5; ++i) {
998  manager.addTask([&]() { ++fibersRun; });
999  }
1000  loopController.loop([&]() { loopController.stop(); });
1001 
1002  EXPECT_EQ(5, fibersRun);
1003  EXPECT_EQ(5, manager.fibersAllocated());
1004  EXPECT_EQ(5, manager.fibersPoolSize());
1005 
1006  for (size_t i = 0; i < 5; ++i) {
1007  manager.addTask([&]() { ++fibersRun; });
1008  }
1009  loopController.loop([&]() { loopController.stop(); });
1010 
1011  EXPECT_EQ(10, fibersRun);
1012  EXPECT_EQ(5, manager.fibersAllocated());
1013  EXPECT_EQ(5, manager.fibersPoolSize());
1014 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Single-threaded task execution engine.
TEST ( FiberManager  ,
fibersPoolOverLimit   
)

Definition at line 1016 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), EXPECT_EQ, folly::fibers::FiberManager::fibersAllocated(), folly::fibers::FiberManager::fibersPoolSize(), i, folly::fibers::FiberManager::loopController(), and folly::fibers::FiberManager::Options::maxFibersPoolSize.

1016  {
1017  FiberManager::Options opts;
1018  opts.maxFibersPoolSize = 5;
1019 
1020  FiberManager manager(std::make_unique<SimpleLoopController>(), opts);
1021  auto& loopController =
1022  dynamic_cast<SimpleLoopController&>(manager.loopController());
1023 
1024  size_t fibersRun = 0;
1025 
1026  for (size_t i = 0; i < 10; ++i) {
1027  manager.addTask([&]() { ++fibersRun; });
1028  }
1029 
1030  EXPECT_EQ(0, fibersRun);
1031  EXPECT_EQ(10, manager.fibersAllocated());
1032  EXPECT_EQ(0, manager.fibersPoolSize());
1033 
1034  loopController.loop([&]() { loopController.stop(); });
1035 
1036  EXPECT_EQ(10, fibersRun);
1037  EXPECT_EQ(5, manager.fibersAllocated());
1038  EXPECT_EQ(5, manager.fibersPoolSize());
1039 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Single-threaded task execution engine.
TEST ( FiberManager  ,
remoteFiberBasic   
)

Definition at line 1041 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), folly::fibers::await(), EXPECT_EQ, EXPECT_TRUE, folly::fibers::FiberManager::loopController(), folly::fibers::FiberManager::loopUntilNoReady(), and folly::gen::move.

1041  {
1042  FiberManager manager(std::make_unique<SimpleLoopController>());
1043  auto& loopController =
1044  dynamic_cast<SimpleLoopController&>(manager.loopController());
1045 
1046  int result[2];
1047  result[0] = result[1] = 0;
1048  folly::Optional<Promise<int>> savedPromise[2];
1049  manager.addTask([&]() {
1050  result[0] = await(
1051  [&](Promise<int> promise) { savedPromise[0] = std::move(promise); });
1052  });
1053  manager.addTask([&]() {
1054  result[1] = await(
1055  [&](Promise<int> promise) { savedPromise[1] = std::move(promise); });
1056  });
1057 
1058  manager.loopUntilNoReady();
1059 
1060  EXPECT_TRUE(savedPromise[0].hasValue());
1061  EXPECT_TRUE(savedPromise[1].hasValue());
1062  EXPECT_EQ(0, result[0]);
1063  EXPECT_EQ(0, result[1]);
1064 
1065  std::thread remoteThread0{[&]() { savedPromise[0]->setValue(42); }};
1066  std::thread remoteThread1{[&]() { savedPromise[1]->setValue(43); }};
1067  remoteThread0.join();
1068  remoteThread1.join();
1069  EXPECT_EQ(0, result[0]);
1070  EXPECT_EQ(0, result[1]);
1071  /* Should only have scheduled once */
1072  EXPECT_EQ(1, loopController.remoteScheduleCalled());
1073 
1074  manager.loopUntilNoReady();
1075  EXPECT_EQ(42, result[0]);
1076  EXPECT_EQ(43, result[1]);
1077 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
Single-threaded task execution engine.
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
FirstArgOf< F >::type::value_type await(F &&func)
TEST ( FiberManager  ,
addTaskRemoteBasic   
)

Definition at line 1079 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTaskRemote(), folly::fibers::await(), EXPECT_EQ, EXPECT_TRUE, folly::fibers::FiberManager::loopUntilNoReady(), and folly::gen::move.

1079  {
1080  FiberManager manager(std::make_unique<SimpleLoopController>());
1081 
1082  int result[2];
1083  result[0] = result[1] = 0;
1084  folly::Optional<Promise<int>> savedPromise[2];
1085 
1086  std::thread remoteThread0{[&]() {
1087  manager.addTaskRemote([&]() {
1088  result[0] = await(
1089  [&](Promise<int> promise) { savedPromise[0] = std::move(promise); });
1090  });
1091  }};
1092  std::thread remoteThread1{[&]() {
1093  manager.addTaskRemote([&]() {
1094  result[1] = await(
1095  [&](Promise<int> promise) { savedPromise[1] = std::move(promise); });
1096  });
1097  }};
1098  remoteThread0.join();
1099  remoteThread1.join();
1100 
1101  manager.loopUntilNoReady();
1102 
1103  EXPECT_TRUE(savedPromise[0].hasValue());
1104  EXPECT_TRUE(savedPromise[1].hasValue());
1105  EXPECT_EQ(0, result[0]);
1106  EXPECT_EQ(0, result[1]);
1107 
1108  savedPromise[0]->setValue(42);
1109  savedPromise[1]->setValue(43);
1110 
1111  EXPECT_EQ(0, result[0]);
1112  EXPECT_EQ(0, result[1]);
1113 
1114  manager.loopUntilNoReady();
1115  EXPECT_EQ(42, result[0]);
1116  EXPECT_EQ(43, result[1]);
1117 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
Single-threaded task execution engine.
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
FirstArgOf< F >::type::value_type await(F &&func)
TEST ( FiberManager  ,
remoteHasTasks   
)

Definition at line 1119 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTaskRemote(), counter, EXPECT_EQ, EXPECT_FALSE, folly::fibers::FiberManager::hasTasks(), and folly::fibers::FiberManager::loopUntilNoReady().

1119  {
1120  size_t counter = 0;
1121  FiberManager fm(std::make_unique<SimpleLoopController>());
1122  std::thread remote([&]() { fm.addTaskRemote([&]() { ++counter; }); });
1123 
1124  remote.join();
1125 
1126  while (fm.hasTasks()) {
1127  fm.loopUntilNoReady();
1128  }
1129 
1130  EXPECT_FALSE(fm.hasTasks());
1131  EXPECT_EQ(counter, 1);
1132 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Single-threaded task execution engine.
std::atomic< int > counter
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( FiberManager  ,
remoteHasReadyTasks   
)

Definition at line 1134 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTaskRemote(), folly::fibers::await(), EXPECT_EQ, EXPECT_FALSE, EXPECT_TRUE, folly::fibers::FiberManager::hasTasks(), folly::fibers::FiberManager::loopUntilNoReady(), and folly::gen::move.

1134  {
1135  int result = 0;
1136  folly::Optional<Promise<int>> savedPromise;
1137  FiberManager fm(std::make_unique<SimpleLoopController>());
1138  std::thread remote([&]() {
1139  fm.addTaskRemote([&]() {
1140  result = await(
1141  [&](Promise<int> promise) { savedPromise = std::move(promise); });
1142  EXPECT_TRUE(fm.hasTasks());
1143  });
1144  });
1145 
1146  remote.join();
1147  EXPECT_TRUE(fm.hasTasks());
1148 
1149  fm.loopUntilNoReady();
1150  EXPECT_TRUE(fm.hasTasks());
1151 
1152  std::thread remote2([&]() { savedPromise->setValue(47); });
1153  remote2.join();
1154  EXPECT_TRUE(fm.hasTasks());
1155 
1156  fm.loopUntilNoReady();
1157  EXPECT_FALSE(fm.hasTasks());
1158 
1159  EXPECT_EQ(result, 47);
1160 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
Single-threaded task execution engine.
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
FirstArgOf< F >::type::value_type await(F &&func)
TEST ( FiberManager  ,
fiberLocal   
)

Definition at line 1206 of file FibersTest.cpp.

References folly::value().

1206  {
1207  struct SimpleData {
1208  int value{42};
1209  };
1210 
1211  testFiberLocal<SimpleData>();
1212 }
static const char *const value
Definition: Conv.cpp:50
TEST ( FiberManager  ,
fiberLocalHeap   
)

Definition at line 1214 of file FibersTest.cpp.

References testing::_, and folly::value().

1214  {
1215  struct LargeData {
1216  char _[1024 * 1024];
1217  int value{42};
1218  };
1219 
1220  testFiberLocal<LargeData>();
1221 }
static const char *const value
Definition: Conv.cpp:50
const internal::AnythingMatcher _
TEST ( FiberManager  ,
fiberLocalDestructor   
)

Definition at line 1223 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), folly::fibers::addTask(), folly::data(), EXPECT_EQ, EXPECT_FALSE, folly::fibers::FiberManager::hasTasks(), and folly::fibers::FiberManager::loopUntilNoReady().

1223  {
1224  struct CrazyData {
1225  size_t data{42};
1226 
1227  ~CrazyData() {
1228  if (data == 41) {
1229  addTask([]() {
1230  EXPECT_EQ(42, local<CrazyData>().data);
1231  // Make sure we don't have infinite loop
1232  local<CrazyData>().data = 0;
1233  });
1234  }
1235  }
1236  };
1237 
1238  FiberManager fm(
1239  LocalType<CrazyData>(), std::make_unique<SimpleLoopController>());
1240 
1241  fm.addTask([]() { local<CrazyData>().data = 41; });
1242 
1243  fm.loopUntilNoReady();
1244  EXPECT_FALSE(fm.hasTasks());
1245 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Single-threaded task execution engine.
void addTask(F &&func)
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
static constexpr uint64_t data[1]
Definition: Fingerprint.cpp:43
TEST ( FiberManager  ,
yieldTest   
)

Definition at line 1247 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), EXPECT_TRUE, folly::fibers::FiberManager::loopController(), and folly::fibers::FiberManager::yield().

1247  {
1248  FiberManager manager(std::make_unique<SimpleLoopController>());
1249  auto& loopController =
1250  dynamic_cast<SimpleLoopController&>(manager.loopController());
1251 
1252  bool checkRan = false;
1253 
1254  manager.addTask([&]() {
1255  manager.yield();
1256  checkRan = true;
1257  });
1258 
1259  loopController.loop([&]() {
1260  if (checkRan) {
1261  loopController.stop();
1262  }
1263  });
1264 
1265  EXPECT_TRUE(checkRan);
1266 }
Single-threaded task execution engine.
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
TEST ( FiberManager  ,
RequestContext   
)

Definition at line 1268 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), folly::fibers::FiberManager::addTaskFinally(), folly::fibers::FiberManager::addTaskRemote(), EXPECT_EQ, EXPECT_TRUE, folly::RequestContext::get(), folly::fibers::FiberManager::loopUntilNoReady(), folly::fibers::Baton::post(), folly::fibers::runInMainContext(), folly::RequestContext::setContext(), and folly::fibers::Baton::wait().

1268  {
1269  FiberManager fm(std::make_unique<SimpleLoopController>());
1270 
1271  bool checkRun1 = false;
1272  bool checkRun2 = false;
1273  bool checkRun3 = false;
1274  bool checkRun4 = false;
1275  folly::fibers::Baton baton1;
1276  folly::fibers::Baton baton2;
1277  folly::fibers::Baton baton3;
1278  folly::fibers::Baton baton4;
1279 
1280  {
1282  auto rcontext1 = folly::RequestContext::get();
1283  fm.addTask([&, rcontext1]() {
1284  EXPECT_EQ(rcontext1, folly::RequestContext::get());
1285  baton1.wait(
1286  [&]() { EXPECT_EQ(rcontext1, folly::RequestContext::get()); });
1287  EXPECT_EQ(rcontext1, folly::RequestContext::get());
1289  [&]() { EXPECT_EQ(rcontext1, folly::RequestContext::get()); });
1290  checkRun1 = true;
1291  });
1292  }
1293  {
1295  auto rcontext2 = folly::RequestContext::get();
1296  fm.addTaskRemote([&, rcontext2]() {
1297  EXPECT_EQ(rcontext2, folly::RequestContext::get());
1298  baton2.wait();
1299  EXPECT_EQ(rcontext2, folly::RequestContext::get());
1300  checkRun2 = true;
1301  });
1302  }
1303  {
1305  auto rcontext3 = folly::RequestContext::get();
1306  fm.addTaskFinally(
1307  [&, rcontext3]() {
1308  EXPECT_EQ(rcontext3, folly::RequestContext::get());
1309  baton3.wait();
1310  EXPECT_EQ(rcontext3, folly::RequestContext::get());
1311 
1312  return folly::Unit();
1313  },
1314  [&, rcontext3](Try<folly::Unit>&& /* t */) {
1315  EXPECT_EQ(rcontext3, folly::RequestContext::get());
1316  checkRun3 = true;
1317  });
1318  }
1319  {
1321  fm.addTask([&]() {
1323  auto rcontext4 = folly::RequestContext::get();
1324  baton4.wait();
1325  EXPECT_EQ(rcontext4, folly::RequestContext::get());
1326  checkRun4 = true;
1327  });
1328  }
1329  {
1331  auto rcontext = folly::RequestContext::get();
1332 
1333  fm.loopUntilNoReady();
1335 
1336  baton1.post();
1338  fm.loopUntilNoReady();
1339  EXPECT_TRUE(checkRun1);
1341 
1342  baton2.post();
1344  fm.loopUntilNoReady();
1345  EXPECT_TRUE(checkRun2);
1347 
1348  baton3.post();
1350  fm.loopUntilNoReady();
1351  EXPECT_TRUE(checkRun3);
1353 
1354  baton4.post();
1356  fm.loopUntilNoReady();
1357  EXPECT_TRUE(checkRun4);
1359  }
1360 }
static std::shared_ptr< RequestContext > setContext(std::shared_ptr< RequestContext > ctx)
Definition: Request.cpp:227
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Single-threaded task execution engine.
Definition: Try.h:51
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
invoke_result_t< F > runInMainContext(F &&func)
static RequestContext * get()
Definition: Request.cpp:290
TEST ( FiberManager  ,
resizePeriodically   
)

Definition at line 1362 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), EXPECT_EQ, folly::fibers::FiberManager::fibersAllocated(), folly::fibers::FiberManager::Options::fibersPoolResizePeriodMs, folly::fibers::FiberManager::fibersPoolSize(), i, folly::fibers::FiberManager::loopController(), folly::EventBase::loopOnce(), and folly::fibers::FiberManager::Options::maxFibersPoolSize.

1362  {
1363  FiberManager::Options opts;
1364  opts.fibersPoolResizePeriodMs = 300;
1365  opts.maxFibersPoolSize = 5;
1366 
1367  FiberManager manager(std::make_unique<EventBaseLoopController>(), opts);
1368 
1369  folly::EventBase evb;
1370  dynamic_cast<EventBaseLoopController&>(manager.loopController())
1371  .attachEventBase(evb);
1372 
1373  std::vector<Baton> batons(10);
1374 
1375  size_t tasksRun = 0;
1376  for (size_t i = 0; i < 30; ++i) {
1377  manager.addTask([i, &batons, &tasksRun]() {
1378  ++tasksRun;
1379  // Keep some fibers active indefinitely
1380  if (i < batons.size()) {
1381  batons[i].wait();
1382  }
1383  });
1384  }
1385 
1386  EXPECT_EQ(0, tasksRun);
1387  EXPECT_EQ(30, manager.fibersAllocated());
1388  EXPECT_EQ(0, manager.fibersPoolSize());
1389 
1390  evb.loopOnce();
1391  EXPECT_EQ(30, tasksRun);
1392  EXPECT_EQ(30, manager.fibersAllocated());
1393  // Can go over maxFibersPoolSize, 10 of 30 fibers still active
1394  EXPECT_EQ(20, manager.fibersPoolSize());
1395 
1396  std::this_thread::sleep_for(std::chrono::milliseconds(400));
1397  evb.loopOnce(); // no fibers active in this period
1398  EXPECT_EQ(30, manager.fibersAllocated());
1399  EXPECT_EQ(20, manager.fibersPoolSize());
1400 
1401  std::this_thread::sleep_for(std::chrono::milliseconds(400));
1402  evb.loopOnce(); // should shrink fibers pool to maxFibersPoolSize
1403  EXPECT_EQ(15, manager.fibersAllocated());
1404  EXPECT_EQ(5, manager.fibersPoolSize());
1405 
1406  for (size_t i = 0; i < batons.size(); ++i) {
1407  batons[i].post();
1408  }
1409  evb.loopOnce();
1410  EXPECT_EQ(15, manager.fibersAllocated());
1411  EXPECT_EQ(15, manager.fibersPoolSize());
1412 
1413  std::this_thread::sleep_for(std::chrono::milliseconds(400));
1414  evb.loopOnce(); // 10 fibers active in last period
1415  EXPECT_EQ(10, manager.fibersAllocated());
1416  EXPECT_EQ(10, manager.fibersPoolSize());
1417 
1418  std::this_thread::sleep_for(std::chrono::milliseconds(400));
1419  evb.loopOnce();
1420  EXPECT_EQ(5, manager.fibersAllocated());
1421  EXPECT_EQ(5, manager.fibersPoolSize());
1422 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Single-threaded task execution engine.
bool loopOnce(int flags=0)
Definition: EventBase.cpp:271
TEST ( FiberManager  ,
batonWaitTimeoutHandler   
)

Definition at line 1424 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), EXPECT_EQ, EXPECT_FALSE, folly::fibers::FiberManager::loopController(), folly::EventBase::loopOnce(), folly::fibers::FiberManager::loopUntilNoReady(), folly::fibers::Baton::TimeoutHandler::scheduleTimeout(), folly::fibers::Baton::try_wait(), and folly::fibers::Baton::wait().

1424  {
1425  FiberManager manager(std::make_unique<EventBaseLoopController>());
1426 
1427  folly::EventBase evb;
1428  dynamic_cast<EventBaseLoopController&>(manager.loopController())
1429  .attachEventBase(evb);
1430 
1431  size_t fibersRun = 0;
1432  Baton baton;
1433  Baton::TimeoutHandler timeoutHandler;
1434 
1435  manager.addTask([&]() {
1436  baton.wait(timeoutHandler);
1437  ++fibersRun;
1438  });
1439  manager.loopUntilNoReady();
1440 
1441  EXPECT_FALSE(baton.try_wait());
1442  EXPECT_EQ(0, fibersRun);
1443 
1444  timeoutHandler.scheduleTimeout(std::chrono::milliseconds(250));
1445  std::this_thread::sleep_for(std::chrono::milliseconds(500));
1446 
1447  EXPECT_FALSE(baton.try_wait());
1448  EXPECT_EQ(0, fibersRun);
1449 
1450  evb.loopOnce();
1451  manager.loopUntilNoReady();
1452 
1453  EXPECT_EQ(1, fibersRun);
1454 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
Single-threaded task execution engine.
void scheduleTimeout(TimeoutController::Duration timeoutMs)
Definition: Baton.cpp:192
bool loopOnce(int flags=0)
Definition: EventBase.cpp:271
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
TEST ( FiberManager  ,
batonWaitTimeoutMany   
)

Definition at line 1456 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), folly::fibers::addTask(), i, folly::fibers::FiberManager::loopController(), folly::EventBase::loopForever(), folly::fibers::Baton::TimeoutHandler::scheduleTimeout(), folly::EventBase::terminateLoopSoon(), and folly::fibers::Baton::wait().

1456  {
1457  FiberManager manager(std::make_unique<EventBaseLoopController>());
1458 
1459  folly::EventBase evb;
1460  dynamic_cast<EventBaseLoopController&>(manager.loopController())
1461  .attachEventBase(evb);
1462 
1463  constexpr size_t kNumTimeoutTasks = 10000;
1464  size_t tasksCount = kNumTimeoutTasks;
1465 
1466  // We add many tasks to hit timeout queue deallocation logic.
1467  for (size_t i = 0; i < kNumTimeoutTasks; ++i) {
1468  manager.addTask([&]() {
1469  Baton baton;
1470  Baton::TimeoutHandler timeoutHandler;
1471 
1473  timeoutHandler.scheduleTimeout(std::chrono::milliseconds(1000));
1474  });
1475 
1476  baton.wait(timeoutHandler);
1477  if (--tasksCount == 0) {
1478  evb.terminateLoopSoon();
1479  }
1480  });
1481  }
1482 
1483  evb.loopForever();
1484 }
Single-threaded task execution engine.
void scheduleTimeout(TimeoutController::Duration timeoutMs)
Definition: Baton.cpp:192
void terminateLoopSoon()
Definition: EventBase.cpp:493
void addTask(F &&func)
TEST ( FiberManager  ,
remoteFutureTest   
)

Definition at line 1486 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTaskFuture(), folly::fibers::FiberManager::addTaskRemoteFuture(), EXPECT_EQ, folly::fibers::FiberManager::loopController(), and folly::gen::move.

1486  {
1487  FiberManager fiberManager(std::make_unique<SimpleLoopController>());
1488  auto& loopController =
1489  dynamic_cast<SimpleLoopController&>(fiberManager.loopController());
1490 
1491  int testValue1 = 5;
1492  int testValue2 = 7;
1493  auto f1 = fiberManager.addTaskFuture([&]() { return testValue1; });
1494  auto f2 = fiberManager.addTaskRemoteFuture([&]() { return testValue2; });
1495  loopController.loop([&]() { loopController.stop(); });
1496  auto v1 = std::move(f1).get();
1497  auto v2 = std::move(f2).get();
1498 
1499  EXPECT_EQ(v1, testValue1);
1500  EXPECT_EQ(v2, testValue2);
1501 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
Single-threaded task execution engine.
TEST ( FiberManager  ,
remoteFutureVoidUnitTest   
)

Definition at line 1504 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTaskFuture(), folly::fibers::FiberManager::addTaskRemoteFuture(), ASSERT_TRUE, folly::fibers::FiberManager::loopController(), and folly::Future< T >::wait().

1504  {
1505  FiberManager fiberManager(std::make_unique<SimpleLoopController>());
1506  auto& loopController =
1507  dynamic_cast<SimpleLoopController&>(fiberManager.loopController());
1508 
1509  bool ranLocal = false;
1510  folly::Future<folly::Unit> futureLocal =
1511  fiberManager.addTaskFuture([&]() { ranLocal = true; });
1512 
1513  bool ranRemote = false;
1514  folly::Future<folly::Unit> futureRemote =
1515  fiberManager.addTaskRemoteFuture([&]() { ranRemote = true; });
1516 
1517  loopController.loop([&]() { loopController.stop(); });
1518 
1519  futureLocal.wait();
1520  ASSERT_TRUE(ranLocal);
1521 
1522  futureRemote.wait();
1523  ASSERT_TRUE(ranRemote);
1524 }
Future< T > & wait()&
Definition: Future-inl.h:2197
Single-threaded task execution engine.
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
TEST ( FiberManager  ,
nestedFiberManagers   
)

Definition at line 1526 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), EXPECT_EQ, folly::fibers::getFiberManager(), folly::fibers::FiberManager::getFiberManagerUnsafe(), folly::EventBase::loopForever(), folly::fibers::runInMainContext(), and folly::EventBase::terminateLoopSoon().

1526  {
1527  folly::EventBase outerEvb;
1528  folly::EventBase innerEvb;
1529 
1530  getFiberManager(outerEvb).addTask([&]() {
1531  EXPECT_EQ(
1532  &getFiberManager(outerEvb), FiberManager::getFiberManagerUnsafe());
1533 
1534  runInMainContext([&]() {
1535  getFiberManager(innerEvb).addTask([&]() {
1536  EXPECT_EQ(
1537  &getFiberManager(innerEvb), FiberManager::getFiberManagerUnsafe());
1538 
1539  innerEvb.terminateLoopSoon();
1540  });
1541 
1542  innerEvb.loopForever();
1543  });
1544 
1545  EXPECT_EQ(
1546  &getFiberManager(outerEvb), FiberManager::getFiberManagerUnsafe());
1547 
1548  outerEvb.terminateLoopSoon();
1549  });
1550 
1551  outerEvb.loopForever();
1552 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
void terminateLoopSoon()
Definition: EventBase.cpp:493
invoke_result_t< F > runInMainContext(F &&func)
FiberManager & getFiberManager(EventBase &evb, const FiberManager::Options &opts)
TEST ( FiberManager  ,
semaphore   
)

Definition at line 1554 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), counter, evb_, EXPECT_GE, EXPECT_LT, i, folly::fibers::FiberManager::loopController(), folly::EventBase::loopForever(), folly::fibers::Baton::post(), folly::fibers::Semaphore::signal(), folly::EventBase::terminateLoopSoon(), and folly::fibers::Semaphore::wait().

1554  {
1555  static constexpr size_t kTasks = 10;
1556  static constexpr size_t kIterations = 10000;
1557  static constexpr size_t kNumTokens = 10;
1558 
1559  Semaphore sem(kNumTokens);
1560  int counterA = 0;
1561  int counterB = 0;
1562 
1563  auto task = [&sem](int& counter, folly::fibers::Baton& baton) {
1564  FiberManager manager(std::make_unique<EventBaseLoopController>());
1565  folly::EventBase evb;
1566  dynamic_cast<EventBaseLoopController&>(manager.loopController())
1567  .attachEventBase(evb);
1568 
1569  {
1570  std::shared_ptr<folly::EventBase> completionCounter(
1571  &evb, [](folly::EventBase* evb_) { evb_->terminateLoopSoon(); });
1572 
1573  for (size_t i = 0; i < kTasks; ++i) {
1574  manager.addTask([&, completionCounter]() {
1575  for (size_t j = 0; j < kIterations; ++j) {
1576  sem.wait();
1577  ++counter;
1578  sem.signal();
1579  --counter;
1580 
1581  EXPECT_LT(counter, kNumTokens);
1582  EXPECT_GE(counter, 0);
1583  }
1584  });
1585  }
1586 
1587  baton.wait();
1588  }
1589  evb.loopForever();
1590  };
1591 
1592  folly::fibers::Baton batonA;
1593  folly::fibers::Baton batonB;
1594  std::thread threadA([&] { task(counterA, batonA); });
1595  std::thread threadB([&] { task(counterB, batonB); });
1596 
1597  batonA.post();
1598  batonB.post();
1599  threadA.join();
1600  threadB.join();
1601 
1602  EXPECT_LT(counterA, kNumTokens);
1603  EXPECT_LT(counterB, kNumTokens);
1604  EXPECT_GE(counterA, 0);
1605  EXPECT_GE(counterB, 0);
1606 }
#define EXPECT_GE(val1, val2)
Definition: gtest.h:1932
Single-threaded task execution engine.
EventBase * evb_
void terminateLoopSoon()
Definition: EventBase.cpp:493
std::atomic< int > counter
#define EXPECT_LT(val1, val2)
Definition: gtest.h:1930
TEST ( FiberManager  ,
batchDispatchTest   
)

Definition at line 1625 of file FibersTest.cpp.

References folly::pushmi::executor, folly::fibers::getFiberManager(), i, folly::EventBase::loop(), and singleBatchDispatch().

1625  {
1626  folly::EventBase evb;
1627  auto& executor = getFiberManager(evb);
1628 
1629  // Launch multiple fibers with a single id.
1630  executor.add([&]() {
1631  int batchSize = 10;
1632  for (int i = 0; i < batchSize; i++) {
1633  executor.add(
1634  [=, &executor]() { singleBatchDispatch(executor, batchSize, i); });
1635  }
1636  });
1637  evb.loop();
1638 
1639  // Reuse the same BatchDispatcher to batch once again.
1640  executor.add([&]() {
1641  int batchSize = 10;
1642  for (int i = 0; i < batchSize; i++) {
1643  executor.add(
1644  [=, &executor]() { singleBatchDispatch(executor, batchSize, i); });
1645  }
1646  });
1647  evb.loop();
1648 }
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
void singleBatchDispatch(ExecutorT &executor, int batchSize, int index)
FiberManager & getFiberManager(EventBase &evb, const FiberManager::Options &opts)
TEST ( FiberManager  ,
doubleBatchDispatchTest   
)

Definition at line 1725 of file FibersTest.cpp.

References doubleBatchOuterDispatch(), folly::pushmi::executor, folly::fibers::getFiberManager(), i, and folly::EventBase::loop().

1725  {
1726  folly::EventBase evb;
1727  auto& executor = getFiberManager(evb);
1728 
1729  // Launch multiple fibers with a single id.
1730  executor.add([&]() {
1731  int totalNumberOfElements = 20;
1732  for (int i = 0; i < totalNumberOfElements; i++) {
1733  executor.add([=, &executor]() {
1734  doubleBatchOuterDispatch(executor, totalNumberOfElements, i);
1735  });
1736  }
1737  });
1738  evb.loop();
1739 }
void doubleBatchOuterDispatch(ExecutorT &executor, int totalNumberOfElements, int index)
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
FiberManager & getFiberManager(EventBase &evb, const FiberManager::Options &opts)
TEST ( FiberManager  ,
batchDispatchExceptionHandlingTest   
)

Definition at line 1751 of file FibersTest.cpp.

References batchDispatchExceptionHandling(), folly::pushmi::executor, folly::fibers::getFiberManager(), i, and folly::EventBase::loop().

1751  {
1752  folly::EventBase evb;
1753  auto& executor = getFiberManager(evb);
1754 
1755  // Launch multiple fibers with a single id.
1756  executor.add([&]() {
1757  int totalNumberOfElements = 5;
1758  for (int i = 0; i < totalNumberOfElements; i++) {
1759  executor.add(
1761  }
1762  });
1763  evb.loop();
1764 }
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
void batchDispatchExceptionHandling(ExecutorT &executor, int i)
FiberManager & getFiberManager(EventBase &evb, const FiberManager::Options &opts)
TEST ( FiberManager  ,
ABD_Test   
)

Definition at line 1941 of file FibersTest.cpp.

References folly::fibers::createAtomicBatchDispatcher(), AtomicBatchDispatcherTesting::createJobs(), AtomicBatchDispatcherTesting::dispatchJobs(), folly::pushmi::executor, folly::gen::move, SET_UP_TEST_FUNC, AtomicBatchDispatcherTesting::userDispatchFunc(), and AtomicBatchDispatcherTesting::validateResults().

1941  {
1943 
1944  //
1945  // Testing AtomicBatchDispatcher with explicit call to commit()
1946  //
1947  dispatchFunc = userDispatchFunc;
1948  auto atomicBatchDispatcher =
1949  createAtomicBatchDispatcher(std::move(dispatchFunc));
1950  createJobs(atomicBatchDispatcher, jobs, COUNT);
1951  dispatchJobs(executor, jobs, results);
1952  atomicBatchDispatcher.commit();
1953  evb.loop();
1954  validateResults(results, COUNT);
1955 }
std::vector< ResultT > userDispatchFunc(std::vector< ValueT > &&inputs)
#define SET_UP_TEST_FUNC
AtomicBatchDispatcher< InputT, ResultT > createAtomicBatchDispatcher(folly::Function< std::vector< ResultT >(std::vector< InputT > &&)> dispatchFunc, size_t initialCapacity)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
void validateResults(std::vector< folly::Optional< folly::Future< ResultT >>> &results, size_t expectedNumResults)
void dispatchJobs(FiberManager &executor, std::vector< Job > &jobs, std::vector< folly::Optional< folly::Future< ResultT >>> &results, DispatchProblem dispatchProblem=DispatchProblem::None, size_t problemIndex=size_t(-1))
void createJobs(AtomicBatchDispatcher< ValueT, ResultT > &atomicBatchDispatcher, std::vector< Job > &jobs, size_t count)
TEST ( FiberManager  ,
ABD_DispatcherDestroyedBeforeCallingCommit   
)

Definition at line 1957 of file FibersTest.cpp.

References folly::fibers::createAtomicBatchDispatcher(), AtomicBatchDispatcherTesting::createJobs(), AtomicBatchDispatcherTesting::dispatchJobs(), folly::pushmi::executor, folly::gen::move, SET_UP_TEST_FUNC, and AtomicBatchDispatcherTesting::userDispatchFunc().

1957  {
1959 
1960  //
1961  // Testing AtomicBatchDispatcher destroyed before calling commit.
1962  // Handles error cases for:
1963  // - User might have forgotten to add the call to commit() in the code
1964  // - An unexpected exception got thrown in user code before commit() is called
1965  //
1966  try {
1967  dispatchFunc = userDispatchFunc;
1968  auto atomicBatchDispatcher =
1969  createAtomicBatchDispatcher(std::move(dispatchFunc));
1970  createJobs(atomicBatchDispatcher, jobs, COUNT);
1971  dispatchJobs(executor, jobs, results);
1972  throw std::runtime_error(
1973  "Unexpected exception in user code before commit called");
1974  // atomicBatchDispatcher.commit();
1975  } catch (...) {
1976  /* User code handles the exception and does not exit process */
1977  }
1978  evb.loop();
1979  validateResults<ABDCommitNotCalledException>(results, COUNT);
1980 }
std::vector< ResultT > userDispatchFunc(std::vector< ValueT > &&inputs)
#define SET_UP_TEST_FUNC
AtomicBatchDispatcher< InputT, ResultT > createAtomicBatchDispatcher(folly::Function< std::vector< ResultT >(std::vector< InputT > &&)> dispatchFunc, size_t initialCapacity)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
void dispatchJobs(FiberManager &executor, std::vector< Job > &jobs, std::vector< folly::Optional< folly::Future< ResultT >>> &results, DispatchProblem dispatchProblem=DispatchProblem::None, size_t problemIndex=size_t(-1))
void createJobs(AtomicBatchDispatcher< ValueT, ResultT > &atomicBatchDispatcher, std::vector< Job > &jobs, size_t count)
TEST ( FiberManager  ,
ABD_PreprocessingFailureTest   
)

Definition at line 1982 of file FibersTest.cpp.

References folly::fibers::createAtomicBatchDispatcher(), AtomicBatchDispatcherTesting::createJobs(), AtomicBatchDispatcherTesting::dispatchJobs(), folly::pushmi::executor, folly::gen::move, SET_UP_TEST_FUNC, and AtomicBatchDispatcherTesting::userDispatchFunc().

1982  {
1984 
1985  //
1986  // Testing preprocessing failure on a job throws
1987  //
1988  dispatchFunc = userDispatchFunc;
1989  auto atomicBatchDispatcher =
1990  createAtomicBatchDispatcher(std::move(dispatchFunc));
1991  createJobs(atomicBatchDispatcher, jobs, COUNT);
1992  dispatchJobs(executor, jobs, results, DispatchProblem::PreprocessThrows, 8);
1993  atomicBatchDispatcher.commit();
1994  evb.loop();
1995  validateResults<ABDTokenNotDispatchedException>(results, COUNT - 1);
1996 }
std::vector< ResultT > userDispatchFunc(std::vector< ValueT > &&inputs)
#define SET_UP_TEST_FUNC
AtomicBatchDispatcher< InputT, ResultT > createAtomicBatchDispatcher(folly::Function< std::vector< ResultT >(std::vector< InputT > &&)> dispatchFunc, size_t initialCapacity)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
void dispatchJobs(FiberManager &executor, std::vector< Job > &jobs, std::vector< folly::Optional< folly::Future< ResultT >>> &results, DispatchProblem dispatchProblem=DispatchProblem::None, size_t problemIndex=size_t(-1))
void createJobs(AtomicBatchDispatcher< ValueT, ResultT > &atomicBatchDispatcher, std::vector< Job > &jobs, size_t count)
TEST ( FiberManager  ,
ABD_MultipleDispatchOnSameTokenErrorTest   
)

Definition at line 1998 of file FibersTest.cpp.

References folly::fibers::createAtomicBatchDispatcher(), AtomicBatchDispatcherTesting::createJobs(), AtomicBatchDispatcherTesting::dispatchJobs(), folly::pushmi::executor, folly::gen::move, SET_UP_TEST_FUNC, and AtomicBatchDispatcherTesting::userDispatchFunc().

1998  {
2000 
2001  //
2002  // Testing that calling dispatch more than once on the same token throws
2003  //
2004  dispatchFunc = userDispatchFunc;
2005  auto atomicBatchDispatcher =
2006  createAtomicBatchDispatcher(std::move(dispatchFunc));
2007  createJobs(atomicBatchDispatcher, jobs, COUNT);
2008  dispatchJobs(executor, jobs, results, DispatchProblem::DuplicateDispatch, 4);
2009  atomicBatchDispatcher.commit();
2010  evb.loop();
2011 }
std::vector< ResultT > userDispatchFunc(std::vector< ValueT > &&inputs)
#define SET_UP_TEST_FUNC
AtomicBatchDispatcher< InputT, ResultT > createAtomicBatchDispatcher(folly::Function< std::vector< ResultT >(std::vector< InputT > &&)> dispatchFunc, size_t initialCapacity)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
void dispatchJobs(FiberManager &executor, std::vector< Job > &jobs, std::vector< folly::Optional< folly::Future< ResultT >>> &results, DispatchProblem dispatchProblem=DispatchProblem::None, size_t problemIndex=size_t(-1))
void createJobs(AtomicBatchDispatcher< ValueT, ResultT > &atomicBatchDispatcher, std::vector< Job > &jobs, size_t count)
TEST ( FiberManager  ,
ABD_GetTokenCalledAfterCommitTest   
)

Definition at line 2013 of file FibersTest.cpp.

References folly::fibers::createAtomicBatchDispatcher(), AtomicBatchDispatcherTesting::createJobs(), AtomicBatchDispatcherTesting::dispatchJobs(), folly::pushmi::executor, EXPECT_THROW, folly::gen::move, SET_UP_TEST_FUNC, AtomicBatchDispatcherTesting::userDispatchFunc(), and AtomicBatchDispatcherTesting::validateResults().

2013  {
2015 
2016  //
2017  // Testing that exception set on attempt to call getToken after commit called
2018  //
2019  dispatchFunc = userDispatchFunc;
2020  auto atomicBatchDispatcher =
2021  createAtomicBatchDispatcher(std::move(dispatchFunc));
2022  createJobs(atomicBatchDispatcher, jobs, COUNT);
2023  atomicBatchDispatcher.commit();
2024  EXPECT_THROW(atomicBatchDispatcher.getToken(), ABDUsageException);
2025  dispatchJobs(executor, jobs, results);
2026  EXPECT_THROW(atomicBatchDispatcher.getToken(), ABDUsageException);
2027  evb.loop();
2028  validateResults(results, COUNT);
2029  EXPECT_THROW(atomicBatchDispatcher.getToken(), ABDUsageException);
2030 }
#define EXPECT_THROW(statement, expected_exception)
Definition: gtest.h:1843
std::vector< ResultT > userDispatchFunc(std::vector< ValueT > &&inputs)
#define SET_UP_TEST_FUNC
AtomicBatchDispatcher< InputT, ResultT > createAtomicBatchDispatcher(folly::Function< std::vector< ResultT >(std::vector< InputT > &&)> dispatchFunc, size_t initialCapacity)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
void validateResults(std::vector< folly::Optional< folly::Future< ResultT >>> &results, size_t expectedNumResults)
void dispatchJobs(FiberManager &executor, std::vector< Job > &jobs, std::vector< folly::Optional< folly::Future< ResultT >>> &results, DispatchProblem dispatchProblem=DispatchProblem::None, size_t problemIndex=size_t(-1))
void createJobs(AtomicBatchDispatcher< ValueT, ResultT > &atomicBatchDispatcher, std::vector< Job > &jobs, size_t count)
TEST ( FiberManager  ,
ABD_UserProvidedBatchDispatchThrowsTest   
)

Definition at line 2032 of file FibersTest.cpp.

References folly::fibers::createAtomicBatchDispatcher(), AtomicBatchDispatcherTesting::createJobs(), AtomicBatchDispatcherTesting::dispatchJobs(), folly::pushmi::executor, folly::gen::move, SET_UP_TEST_FUNC, and AtomicBatchDispatcherTesting::userDispatchFunc().

2032  {
2034 
2035  //
2036  // Testing that exception is set if user provided batch dispatch throws
2037  //
2038  dispatchFunc = [](std::vector<ValueT>&& inputs) -> std::vector<ResultT> {
2039  (void)userDispatchFunc(std::move(inputs));
2040  throw std::runtime_error("Unexpected exception in user dispatch function");
2041  };
2042  auto atomicBatchDispatcher =
2043  createAtomicBatchDispatcher(std::move(dispatchFunc));
2044  createJobs(atomicBatchDispatcher, jobs, COUNT);
2045  dispatchJobs(executor, jobs, results);
2046  atomicBatchDispatcher.commit();
2047  evb.loop();
2048  validateResults<std::runtime_error>(results, COUNT);
2049 }
std::vector< ResultT > userDispatchFunc(std::vector< ValueT > &&inputs)
#define SET_UP_TEST_FUNC
AtomicBatchDispatcher< InputT, ResultT > createAtomicBatchDispatcher(folly::Function< std::vector< ResultT >(std::vector< InputT > &&)> dispatchFunc, size_t initialCapacity)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
void dispatchJobs(FiberManager &executor, std::vector< Job > &jobs, std::vector< folly::Optional< folly::Future< ResultT >>> &results, DispatchProblem dispatchProblem=DispatchProblem::None, size_t problemIndex=size_t(-1))
void createJobs(AtomicBatchDispatcher< ValueT, ResultT > &atomicBatchDispatcher, std::vector< Job > &jobs, size_t count)
TEST ( FiberManager  ,
VirtualEventBase   
)

Definition at line 2051 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTaskRemote(), EXPECT_FALSE, EXPECT_TRUE, folly::ScopedEventBaseThread::getEventBase(), folly::fibers::getFiberManager(), folly::EventBase::getVirtualEventBase(), and folly::fibers::Baton::try_wait_for().

2051  {
2052  bool done1{false};
2053  bool done2{false};
2054  {
2056 
2057  auto evb1 =
2058  std::make_unique<folly::VirtualEventBase>(*thread.getEventBase());
2059  auto& evb2 = thread.getEventBase()->getVirtualEventBase();
2060 
2061  getFiberManager(*evb1).addTaskRemote([&] {
2062  Baton baton;
2063  baton.try_wait_for(std::chrono::milliseconds{100});
2064 
2065  done1 = true;
2066  });
2067 
2068  getFiberManager(evb2).addTaskRemote([&] {
2069  Baton baton;
2070  baton.try_wait_for(std::chrono::milliseconds{200});
2071 
2072  done2 = true;
2073  });
2074 
2075  EXPECT_FALSE(done1);
2076  EXPECT_FALSE(done2);
2077 
2078  evb1.reset();
2079  EXPECT_TRUE(done1);
2080  EXPECT_FALSE(done2);
2081  }
2082  EXPECT_TRUE(done2);
2083 }
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
bool try_wait_for(const std::chrono::duration< Rep, Period > &timeout)
Definition: Baton.h:105
folly::VirtualEventBase & getVirtualEventBase()
Definition: EventBase.cpp:768
FiberManager & getFiberManager(EventBase &evb, const FiberManager::Options &opts)
TEST ( TimedMutex  ,
ThreadsAndFibersDontDeadlock   
)

Definition at line 2085 of file FibersTest.cpp.

References b, EXPECT_EQ, folly::fibers::getFiberManager(), i, folly::fibers::TimedMutex::lock(), folly::EventBase::loop(), mutex, folly::fibers::Baton::try_wait_for(), and folly::fibers::TimedMutex::unlock().

2085  {
2086  folly::EventBase evb;
2087  auto& fm = getFiberManager(evb);
2088  TimedMutex mutex;
2089  std::thread testThread([&] {
2090  for (int i = 0; i < 100; i++) {
2091  mutex.lock();
2092  mutex.unlock();
2093  {
2094  Baton b;
2095  b.try_wait_for(std::chrono::milliseconds(1));
2096  }
2097  }
2098  });
2099 
2100  for (int numFibers = 0; numFibers < 100; numFibers++) {
2101  fm.addTask([&] {
2102  for (int i = 0; i < 20; i++) {
2103  mutex.lock();
2104  {
2105  Baton b;
2106  b.try_wait_for(std::chrono::milliseconds(1));
2107  }
2108  mutex.unlock();
2109  {
2110  Baton b;
2111  b.try_wait_for(std::chrono::milliseconds(1));
2112  }
2113  }
2114  });
2115  }
2116 
2117  evb.loop();
2118  EXPECT_EQ(0, fm.hasTasks());
2119  testThread.join();
2120 }
char b
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
std::mutex mutex
bool try_wait_for(const std::chrono::duration< Rep, Period > &timeout)
Definition: Baton.h:105
FiberManager & getFiberManager(EventBase &evb, const FiberManager::Options &opts)
TEST ( TimedMutex  ,
ThreadFiberDeadlockOrder   
)

Definition at line 2122 of file FibersTest.cpp.

References EXPECT_EQ, EXPECT_TRUE, folly::fibers::getFiberManager(), folly::fibers::TimedMutex::lock(), folly::EventBase::loopOnce(), mutex, folly::fibers::runInMainContext(), folly::fibers::TimedMutex::timed_lock(), and folly::fibers::TimedMutex::unlock().

2122  {
2123  folly::EventBase evb;
2124  auto& fm = getFiberManager(evb);
2125  TimedMutex mutex;
2126 
2127  mutex.lock();
2128  std::thread unlockThread([&] {
2129  /* sleep override */ std::this_thread::sleep_for(
2130  std::chrono::milliseconds{100});
2131  mutex.unlock();
2132  });
2133 
2134  fm.addTask([&] { std::lock_guard<TimedMutex> lg(mutex); });
2135  fm.addTask([&] {
2136  runInMainContext([&] {
2137  auto locked = mutex.timed_lock(std::chrono::seconds{1});
2138  EXPECT_TRUE(locked);
2139  if (locked) {
2140  mutex.unlock();
2141  }
2142  });
2143  });
2144 
2145  evb.loopOnce();
2146  EXPECT_EQ(0, fm.hasTasks());
2147 
2148  unlockThread.join();
2149 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
bool loopOnce(int flags=0)
Definition: EventBase.cpp:271
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
invoke_result_t< F > runInMainContext(F &&func)
std::mutex mutex
bool timed_lock(const std::chrono::duration< Rep, Period > &duration)
FiberManager & getFiberManager(EventBase &evb, const FiberManager::Options &opts)
TEST ( TimedMutex  ,
ThreadFiberDeadlockRace   
)

Definition at line 2151 of file FibersTest.cpp.

References EXPECT_EQ, EXPECT_LT, EXPECT_NE, EXPECT_TRUE, folly::fibers::getFiberManager(), folly::fibers::TimedMutex::lock(), folly::EventBase::loopOnce(), mutex, folly::fibers::runInMainContext(), folly::fibers::TimedMutex::timed_lock(), and folly::fibers::TimedMutex::unlock().

2151  {
2152  folly::EventBase evb;
2153  auto& fm = getFiberManager(evb);
2154  TimedMutex mutex;
2155 
2156  mutex.lock();
2157 
2158  fm.addTask([&] {
2159  auto locked = mutex.timed_lock(std::chrono::seconds{1});
2160  EXPECT_TRUE(locked);
2161  if (locked) {
2162  mutex.unlock();
2163  }
2164  });
2165  fm.addTask([&] {
2166  mutex.unlock();
2167  runInMainContext([&] {
2168  auto locked = mutex.timed_lock(std::chrono::seconds{1});
2169  EXPECT_TRUE(locked);
2170  if (locked) {
2171  mutex.unlock();
2172  }
2173  });
2174  });
2175 
2176  evb.loopOnce();
2177  EXPECT_EQ(0, fm.hasTasks());
2178 }
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
bool loopOnce(int flags=0)
Definition: EventBase.cpp:271
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
invoke_result_t< F > runInMainContext(F &&func)
std::mutex mutex
bool timed_lock(const std::chrono::duration< Rep, Period > &duration)
FiberManager & getFiberManager(EventBase &evb, const FiberManager::Options &opts)
TEST ( FiberManager  ,
highWaterMarkViaRecordStackEvery   
)

Test that we can properly track fiber stack usage, via recordStackEvery For ASAN builds, it is not recorded.

Definition at line 2202 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), b, f, i, folly::fibers::FiberManager::loopController(), folly::fibers::FiberManager::Options::recordStackEvery, s, and folly::fibers::FiberManager::stackHighWatermark().

2202  {
2203  auto f = [] {
2205  opts.recordStackEvery = 1;
2206 
2207  FiberManager fm(std::make_unique<SimpleLoopController>(), opts);
2208  auto& loopController =
2209  dynamic_cast<SimpleLoopController&>(fm.loopController());
2210 
2211  static constexpr size_t n = 1000;
2212  int s = 0;
2213  fm.addTask([&]() {
2214  int b[n] = {0};
2215  for (size_t i = 0; i < n; ++i) {
2216  b[i] = i;
2217  }
2218  for (size_t i = 0; i + 1 < n; ++i) {
2219  s += b[i] * b[i + 1];
2220  }
2221  });
2222 
2223  (void)s;
2224 
2225  loopController.loop([&]() { loopController.stop(); });
2226  expectStackHighWatermark(n * sizeof(int), fm.stackHighWatermark());
2227  };
2228  std::thread(f).join();
2229 }
auto f
char b
Single-threaded task execution engine.
static set< string > s
TEST ( FiberManager  ,
highWaterMarkViaRecordCurrentPosition   
)

Test that we can properly track fiber stack usage, via current position estimate. For ASAN builds, it is not recorded.

Definition at line 2235 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), b, f, i, folly::fibers::FiberManager::loopController(), folly::fibers::FiberManager::runInMainContext(), s, and folly::fibers::FiberManager::stackHighWatermark().

2235  {
2236  auto f = [] {
2237  FiberManager fm(std::make_unique<SimpleLoopController>());
2238  auto& loopController =
2239  dynamic_cast<SimpleLoopController&>(fm.loopController());
2240 
2241  static constexpr size_t n = 1000;
2242  int s = 0;
2243  fm.addTask([&]() {
2244  int b[n] = {0};
2245  for (size_t i = 0; i < n; ++i) {
2246  b[i] = i;
2247  }
2248  for (size_t i = 0; i + 1 < n; ++i) {
2249  s += b[i] * b[i + 1];
2250  }
2251  // Calls preempt, which calls recordStackPosition.
2252  fm.runInMainContext([]() {});
2253  });
2254 
2255  (void)s;
2256 
2257  loopController.loop([&]() { loopController.stop(); });
2258  expectStackHighWatermark(n * sizeof(int), fm.stackHighWatermark());
2259  };
2260  std::thread(f).join();
2261 }
auto f
char b
Single-threaded task execution engine.
static set< string > s
template<typename Data >
void testFiberLocal ( )

Definition at line 1163 of file FibersTest.cpp.

References folly::fibers::FiberManager::addTask(), folly::fibers::addTask(), folly::fibers::FiberManager::addTaskRemote(), folly::fibers::collectAny(), EXPECT_EQ, EXPECT_FALSE, folly::fibers::FiberManager::hasTasks(), folly::fibers::FiberManager::loopUntilNoReady(), tasks, and folly::value().

1163  {
1164  FiberManager fm(LocalType<Data>(), std::make_unique<SimpleLoopController>());
1165 
1166  fm.addTask([]() {
1167  EXPECT_EQ(42, local<Data>().value);
1168 
1169  local<Data>().value = 43;
1170 
1171  addTask([]() {
1172  EXPECT_EQ(43, local<Data>().value);
1173 
1174  local<Data>().value = 44;
1175 
1176  addTask([]() { EXPECT_EQ(44, local<Data>().value); });
1177  });
1178  });
1179 
1180  fm.addTask([&]() {
1181  EXPECT_EQ(42, local<Data>().value);
1182 
1183  local<Data>().value = 43;
1184 
1185  fm.addTaskRemote([]() { EXPECT_EQ(43, local<Data>().value); });
1186  });
1187 
1188  fm.addTask([]() {
1189  EXPECT_EQ(42, local<Data>().value);
1190  local<Data>().value = 43;
1191 
1192  auto task = []() {
1193  EXPECT_EQ(43, local<Data>().value);
1194  local<Data>().value = 44;
1195  };
1196  std::vector<std::function<void()>> tasks{task};
1197  collectAny(tasks.begin(), tasks.end());
1198 
1199  EXPECT_EQ(43, local<Data>().value);
1200  });
1201 
1202  fm.loopUntilNoReady();
1203  EXPECT_FALSE(fm.hasTasks());
1204 }
std::enable_if< !std::is_same< invoke_result_t< typename std::iterator_traits< InputIterator >::value_type >, void >::value, typename std::pair< size_t, invoke_result_t< typename std::iterator_traits< InputIterator >::value_type > > >::type collectAny(InputIterator first, InputIterator last)
Definition: WhenN-inl.h:192
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
std::list< AtForkTask > tasks
Definition: AtFork.cpp:81
Single-threaded task execution engine.
static const char *const value
Definition: Conv.cpp:50
void addTask(F &&func)
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862