diff options
author | Mathias Stearn <mathias@10gen.com> | 2018-11-14 17:28:15 -0500 |
---|---|---|
committer | Mathias Stearn <mathias@10gen.com> | 2018-11-30 19:21:46 -0500 |
commit | 3cc2238a6e132b1fc67f70a3a137ebf2f4db3849 (patch) | |
tree | b0a839eb988fec6e1e2dcce9cba4a91576c02f30 /src/mongo/util/future_test_edge_cases.cpp | |
parent | 69e3a7e1b92b72b5332339a9834a239c635f1350 (diff) | |
download | mongo-3cc2238a6e132b1fc67f70a3a137ebf2f4db3849.tar.gz |
SERVER-35682 Add SharedPromise and SharedSemiFuture types
Diffstat (limited to 'src/mongo/util/future_test_edge_cases.cpp')
-rw-r--r-- | src/mongo/util/future_test_edge_cases.cpp | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/src/mongo/util/future_test_edge_cases.cpp b/src/mongo/util/future_test_edge_cases.cpp index c3ce5db03e2..f2b05484ce1 100644 --- a/src/mongo/util/future_test_edge_cases.cpp +++ b/src/mongo/util/future_test_edge_cases.cpp @@ -163,6 +163,76 @@ TEST(Future_EdgeCases, interrupted_wait_then_then_with_bgthread) { std::move(future).then([] {}).get(); } +TEST(Future_EdgeCases, Racing_SharePromise_getFuture_and_emplaceValue) { + SharedPromise<void> sp; + std::vector<Future<void>> futs; + futs.reserve(30); + + // Note, this is intentionally somewhat racy. async() is defined to sleep 100ms before running + // the function so the first batch of futures will generally block before getting the value is + // emplaced, and the second batch will happen around the same time. In all cases the final batch + // happen after the emplaceValue(), but roughly at the same time. Under TSAN the sleep is + // removed to allow it to find more interesting interleavings, and give it a better chance at + // detecting data races. + + for (int i = 0; i < 10; i++) { + futs.push_back(async([&] { sp.getFuture().get(); })); + } + + sleepUnlessInTsan(); + + for (int i = 0; i < 10; i++) { + futs.push_back(async([&] { sp.getFuture().get(); })); + } + + sleepUnlessInTsan(); + + sp.emplaceValue(); + + for (int i = 0; i < 10; i++) { + futs.push_back(async([&] { sp.getFuture().get(); })); + } + + for (auto& fut : futs) { + fut.get(); + } +} + +TEST(Future_EdgeCases, Racing_SharePromise_getFuture_and_setError) { + SharedPromise<void> sp; + std::vector<Future<void>> futs; + futs.reserve(30); + + // Note, this is intentionally somewhat racy. async() is defined to sleep 100ms before running + // the function so the first batch of futures will generally block before getting the value is + // emplaced, and the second batch will happen around the same time. In all cases the final batch + // happen after the emplaceValue(), but roughly at the same time. Under TSAN the sleep is + // removed to allow it to find more interesting interleavings, and give it a better chance at + // detecting data races. + + for (int i = 0; i < 10; i++) { + futs.push_back(async([&] { sp.getFuture().get(); })); + } + + sleepUnlessInTsan(); + + for (int i = 0; i < 10; i++) { + futs.push_back(async([&] { sp.getFuture().get(); })); + } + + sleepUnlessInTsan(); + + sp.setError(failStatus()); + + for (int i = 0; i < 10; i++) { + futs.push_back(async([&] { sp.getFuture().get(); })); + } + + for (auto& fut : futs) { + ASSERT_EQ(fut.getNoThrow(), failStatus()); + } +} + // Make sure we actually die if someone throws from the getAsync callback. // // With gcc 5.8 we terminate, but print "terminate() called. No exception is active". This works in |