]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/30_threads/future/members/poll.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 30_threads / future / members / poll.cc
1 // Copyright (C) 2020-2023 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 // { dg-additional-options "-pthread" { target pthread } }
21 // { dg-require-gthreads "" }
22
23 #include <future>
24 #include <chrono>
25 #include <iostream>
26 #include <testsuite_hooks.h>
27
28 int iterations = 200;
29
30 using namespace std;
31
32 template<typename Duration>
33 double
34 print(const char* desc, Duration dur)
35 {
36 auto ns = chrono::duration_cast<chrono::nanoseconds>(dur).count();
37 double d = double(ns) / iterations;
38 cout << desc << ": " << ns << "ns for " << iterations
39 << " calls, avg " << d << "ns per call\n";
40 return d;
41 }
42
43 int main()
44 {
45 promise<int> p;
46 future<int> f = p.get_future();
47
48 start_over:
49 auto start = chrono::high_resolution_clock::now();
50 for(int i = 0; i < iterations; i++)
51 f.wait_for(chrono::seconds(0));
52 auto stop = chrono::high_resolution_clock::now();
53
54 /* We've run too few iterations for the clock resolution.
55 Attempt to calibrate it. */
56 if (start == stop)
57 {
58 /* After set_value, wait_for is faster, so use that for the
59 calibration to avoid zero at low clock resultions. */
60 promise<int> pc;
61 future<int> fc = pc.get_future();
62 pc.set_value(1);
63
64 /* Loop until the clock advances, so that start is right after a
65 time increment. */
66 do
67 start = chrono::high_resolution_clock::now();
68 while (start == stop);
69 int i = 0;
70 /* Now until the clock advances again, so that stop is right
71 after another time increment. */
72 do
73 {
74 fc.wait_for(chrono::seconds(0));
75 stop = chrono::high_resolution_clock::now();
76 i++;
77 }
78 while (start == stop);
79 /* Go for some 10 cycles, but if we're already past that and
80 still get into the calibration loop, double the iteration
81 count and try again. */
82 if (iterations < i * 10)
83 iterations = i * 10;
84 else
85 iterations *= 2;
86 goto start_over;
87 }
88
89 double wait_for_0 = print("wait_for(0s)", stop - start);
90
91 start = chrono::high_resolution_clock::now();
92 for(int i = 0; i < iterations; i++)
93 f.wait_until(chrono::system_clock::time_point::min());
94 stop = chrono::high_resolution_clock::now();
95 double wait_until_sys_min __attribute__((unused))
96 = print("wait_until(system_clock minimum)", stop - start);
97
98 start = chrono::high_resolution_clock::now();
99 for(int i = 0; i < iterations; i++)
100 f.wait_until(chrono::steady_clock::time_point::min());
101 stop = chrono::high_resolution_clock::now();
102 double wait_until_steady_min __attribute__((unused))
103 = print("wait_until(steady_clock minimum)", stop - start);
104
105 start = chrono::high_resolution_clock::now();
106 for(int i = 0; i < iterations; i++)
107 f.wait_until(chrono::system_clock::time_point());
108 stop = chrono::high_resolution_clock::now();
109 double wait_until_sys_epoch __attribute__((unused))
110 = print("wait_until(system_clock epoch)", stop - start);
111
112 start = chrono::high_resolution_clock::now();
113 for(int i = 0; i < iterations; i++)
114 f.wait_until(chrono::steady_clock::time_point());
115 stop = chrono::high_resolution_clock::now();
116 double wait_until_steady_epoch __attribute__((unused))
117 = print("wait_until(steady_clock epoch", stop - start);
118
119 p.set_value(1);
120
121 start = chrono::high_resolution_clock::now();
122 for(int i = 0; i < iterations; i++)
123 f.wait_for(chrono::seconds(0));
124 stop = chrono::high_resolution_clock::now();
125 double ready = print("wait_for when ready", stop - start);
126
127 // Polling before ready with wait_for(0s) should be almost as fast as
128 // after the result is ready.
129 VERIFY( wait_for_0 < (ready * 30) );
130
131 // Polling before ready using wait_until(min) should not be terribly slow.
132 VERIFY( wait_until_sys_min < (ready * 100) );
133 VERIFY( wait_until_steady_min < (ready * 100) );
134
135 // The following two tests fail with GCC 11, see
136 // https://gcc.gnu.org/pipermail/libstdc++/2020-November/051422.html
137 #if 0
138 // Polling before ready using wait_until(epoch) should not be terribly slow.
139 VERIFY( wait_until_sys_epoch < (ready * 100) );
140 VERIFY( wait_until_steady_epoch < (ready * 100) );
141 #endif
142 }