xref: /aosp_15_r20/external/libcxx/test/std/thread/futures/futures.async/async_race.38682.pass.cpp (revision 58b9f456b02922dfdb1fad8a988d5fd8765ecb80)
1 //===----------------------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // UNSUPPORTED: libcpp-has-no-threads
11 // UNSUPPORTED: c++98, c++03
12 
13 // There's currently no release of OS X whose dylib contains the patch for
14 // PR38682. Since the fix for future<void> is in the dylib, this test may fail.
15 // UNSUPPORTED: with_system_cxx_lib=macosx10.14
16 // UNSUPPORTED: with_system_cxx_lib=macosx10.13
17 // UNSUPPORTED: with_system_cxx_lib=macosx10.12
18 // UNSUPPORTED: with_system_cxx_lib=macosx10.11
19 // UNSUPPORTED: with_system_cxx_lib=macosx10.10
20 // UNSUPPORTED: with_system_cxx_lib=macosx10.9
21 // UNSUPPORTED: with_system_cxx_lib=macosx10.8
22 // UNSUPPORTED: with_system_cxx_lib=macosx10.7
23 
24 // This test is designed to cause and allow TSAN to detect a race condition
25 // in std::async, as reported in https://bugs.llvm.org/show_bug.cgi?id=38682.
26 
27 #include <cassert>
28 #include <functional>
29 #include <future>
30 #include <numeric>
31 #include <vector>
32 
33 
worker(std::vector<int> const & data)34 static int worker(std::vector<int> const& data) {
35   return std::accumulate(data.begin(), data.end(), 0);
36 }
37 
worker_ref(int & i)38 static int& worker_ref(int& i) { return i; }
39 
worker_void()40 static void worker_void() { }
41 
main()42 int main() {
43   // future<T>
44   {
45     std::vector<int> const v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
46     for (int i = 0; i != 20; ++i) {
47       std::future<int> fut = std::async(std::launch::async, worker, v);
48       int answer = fut.get();
49       assert(answer == 55);
50     }
51   }
52 
53   // future<T&>
54   {
55     for (int i = 0; i != 20; ++i) {
56       std::future<int&> fut = std::async(std::launch::async, worker_ref, std::ref(i));
57       int& answer = fut.get();
58       assert(answer == i);
59     }
60   }
61 
62   // future<void>
63   {
64     for (int i = 0; i != 20; ++i) {
65       std::future<void> fut = std::async(std::launch::async, worker_void);
66       fut.get();
67     }
68   }
69 }
70