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: apple-darwin
16 
17 // This test is designed to cause and allow TSAN to detect a race condition
18 // in std::async, as reported in https://bugs.llvm.org/show_bug.cgi?id=38682.
19 
20 #include <cassert>
21 #include <functional>
22 #include <future>
23 #include <numeric>
24 #include <vector>
25 
26 
27 static int worker(std::vector<int> const& data) {
28   return std::accumulate(data.begin(), data.end(), 0);
29 }
30 
31 static int& worker_ref(int& i) { return i; }
32 
33 static void worker_void() { }
34 
35 int main() {
36   // future<T>
37   {
38     std::vector<int> const v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
39     for (int i = 0; i != 20; ++i) {
40       std::future<int> fut = std::async(std::launch::async, worker, v);
41       int answer = fut.get();
42       assert(answer == 55);
43     }
44   }
45 
46   // future<T&>
47   {
48     for (int i = 0; i != 20; ++i) {
49       std::future<int&> fut = std::async(std::launch::async, worker_ref, std::ref(i));
50       int& answer = fut.get();
51       assert(answer == i);
52     }
53   }
54 
55   // future<void>
56   {
57     for (int i = 0; i != 20; ++i) {
58       std::future<void> fut = std::async(std::launch::async, worker_void);
59       fut.get();
60     }
61   }
62 }
63