state.values.swap(values);
state.promises.swap(promises);
- auto results = state.dispatchFunc(std::move(values));
- if (results.size() != promises.size()) {
- throw std::logic_error(
- "Unexpected number of results returned from dispatch function");
- }
- for (size_t i = 0; i < promises.size(); i++) {
- promises[i].setValue(std::move(results[i]));
+ try {
+ auto results = state.dispatchFunc(std::move(values));
+ if (results.size() != promises.size()) {
+ throw std::logic_error(
+ "Unexpected number of results returned from dispatch function");
+ }
+
+ for (size_t i = 0; i < promises.size(); i++) {
+ promises[i].setValue(std::move(results[i]));
+ }
+ } catch (const std::exception& ex) {
+ for (size_t i = 0; i < promises.size(); i++) {
+ promises[i].setException(
+ exception_wrapper(std::current_exception(), ex));
+ }
+ } catch (...) {
+ for (size_t i = 0; i < promises.size(); i++) {
+ promises[i].setException(exception_wrapper(std::current_exception()));
+ }
}
}
evb.loop();
}
+template <typename ExecutorT>
+void batchDispatchExceptionHandling(ExecutorT& executor, int i) {
+ thread_local BatchDispatcher<int, int, ExecutorT> batchDispatcher(
+ executor, [=, &executor](std::vector<int> &&) -> std::vector<int> {
+ throw std::runtime_error("Surprise!!");
+ });
+
+ EXPECT_THROW(batchDispatcher.add(i).get(), std::runtime_error);
+}
+
+TEST(FiberManager, batchDispatchExceptionHandlingTest) {
+ folly::EventBase evb;
+ auto& executor = getFiberManager(evb);
+
+ // Launch multiple fibers with a single id.
+ executor.add([&]() {
+ int totalNumberOfElements = 5;
+ for (int i = 0; i < totalNumberOfElements; i++) {
+ executor.add(
+ [=, &executor]() { batchDispatchExceptionHandling(executor, i); });
+ }
+ });
+ evb.loop();
+}
+
/**
* Test that we can properly track fiber stack usage.
*