1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // UNSUPPORTED: libcpp-has-no-threads
10 // UNSUPPORTED: c++03
11 
12 // There's currently no release of OS X whose dylib contains the patch for
13 // PR38682. Since the fix for future<void> is in the dylib, this test may fail.
14 // UNSUPPORTED: use_system_cxx_lib && x86_64-apple-macosx10.14
15 // UNSUPPORTED: use_system_cxx_lib && x86_64-apple-macosx10.13
16 // UNSUPPORTED: use_system_cxx_lib && x86_64-apple-macosx10.12
17 // UNSUPPORTED: use_system_cxx_lib && x86_64-apple-macosx10.11
18 // UNSUPPORTED: use_system_cxx_lib && x86_64-apple-macosx10.10
19 // UNSUPPORTED: use_system_cxx_lib && x86_64-apple-macosx10.9
20 
21 // This test is designed to cause and allow TSAN to detect a race condition
22 // in std::async, as reported in https://llvm.org/PR38682.
23 
24 #include <cassert>
25 #include <functional>
26 #include <future>
27 #include <numeric>
28 #include <vector>
29 
30 #include "test_macros.h"
31 
32 
33 static int worker(std::vector<int> const& data) {
34   return std::accumulate(data.begin(), data.end(), 0);
35 }
36 
37 static int& worker_ref(int& i) { return i; }
38 
39 static void worker_void() { }
40 
41 int main(int, char**) {
42   // future<T>
43   {
44     std::vector<int> const v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
45     for (int i = 0; i != 20; ++i) {
46       std::future<int> fut = std::async(std::launch::async, worker, v);
47       int answer = fut.get();
48       assert(answer == 55);
49     }
50   }
51 
52   // future<T&>
53   {
54     for (int i = 0; i != 20; ++i) {
55       std::future<int&> fut = std::async(std::launch::async, worker_ref, std::ref(i));
56       int& answer = fut.get();
57       assert(answer == i);
58     }
59   }
60 
61   // future<void>
62   {
63     for (int i = 0; i != 20; ++i) {
64       std::future<void> fut = std::async(std::launch::async, worker_void);
65       fut.get();
66     }
67   }
68 
69   return 0;
70 }
71