]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/30_threads/future/members/poll.cc
libstdc++: Optimise std::future::wait_for and fix futex polling
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 30_threads / future / members / poll.cc
1 // Copyright (C) 2020 Free Software Foundation, Inc.
2 //
3 // This file is part of the GNU ISO C++ Library. This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 3, or (at your option)
7 // any later version.
8
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3. If not see
16 // <http://www.gnu.org/licenses/>.
17
18 // { dg-options "-O3" }
19 // { dg-do run { target c++11 } }
20
21 #include <future>
22 #include <chrono>
23 #include <iostream>
24 #include <testsuite_hooks.h>
25
26 const int iterations = 200;
27
28 using namespace std;
29
30 template<typename Duration>
31 double
32 print(const char* desc, Duration dur)
33 {
34 auto ns = chrono::duration_cast<chrono::nanoseconds>(dur).count();
35 double d = double(ns) / iterations;
36 cout << desc << ": " << ns << "ns for " << iterations
37 << " calls, avg " << d << "ns per call\n";
38 return d;
39 }
40
41 int main()
42 {
43 promise<int> p;
44 future<int> f = p.get_future();
45
46 auto start = chrono::high_resolution_clock::now();
47 for(int i = 0; i < iterations; i++)
48 f.wait_for(chrono::seconds(0));
49 auto stop = chrono::high_resolution_clock::now();
50 double wait_for_0 = print("wait_for(0s)", stop - start);
51
52 start = chrono::high_resolution_clock::now();
53 for(int i = 0; i < iterations; i++)
54 f.wait_until(chrono::system_clock::time_point());
55 stop = chrono::high_resolution_clock::now();
56 double wait_until_sys_epoch __attribute__((unused))
57 = print("wait_until(system_clock epoch)", stop - start);
58
59 start = chrono::high_resolution_clock::now();
60 for(int i = 0; i < iterations; i++)
61 f.wait_until(chrono::steady_clock::time_point());
62 stop = chrono::high_resolution_clock::now();
63 double wait_until_steady_epoch __attribute__((unused))
64 = print("wait_until(steady_clock epoch", stop - start);
65
66 start = chrono::high_resolution_clock::now();
67 for(int i = 0; i < iterations; i++)
68 f.wait_until(chrono::system_clock::time_point::min());
69 stop = chrono::high_resolution_clock::now();
70 double wait_until_sys_min __attribute__((unused))
71 = print("wait_until(system_clock minimum)", stop - start);
72
73 start = chrono::high_resolution_clock::now();
74 for(int i = 0; i < iterations; i++)
75 f.wait_until(chrono::steady_clock::time_point::min());
76 stop = chrono::high_resolution_clock::now();
77 double wait_until_steady_min __attribute__((unused))
78 = print("wait_until(steady_clock minimum)", stop - start);
79
80 p.set_value(1);
81
82 start = chrono::high_resolution_clock::now();
83 for(int i = 0; i < iterations; i++)
84 f.wait_for(chrono::seconds(0));
85 stop = chrono::high_resolution_clock::now();
86 double ready = print("wait_for when ready", stop - start);
87
88 // polling before ready with wait_for(0s) should be almost as fast as
89 // after the result is ready.
90 VERIFY( wait_for_0 < (ready * 10) );
91
92 // The following two tests fail with GCC 11, see
93 // https://gcc.gnu.org/pipermail/libstdc++/2020-November/051422.html
94 #if 0
95 // polling before ready using wait_until(epoch) should not be terribly slow.
96 VERIFY( wait_until_sys_epoch < (ready * 100) );
97 VERIFY( wait_until_steady_epoch < (ready * 100) );
98 #endif
99
100 // polling before ready using wait_until(min) should not be terribly slow.
101 VERIFY( wait_until_sys_min < (ready * 100) );
102 VERIFY( wait_until_steady_min < (ready * 100) );
103 }