1- // #include "pot/coroutines/task.h"
2- // #include "pot/coroutines/when_all.h"
3- // #include "pot/executors/thread_pool_executor_lfgq.h"
4- // #include "pot/algorithms/parfor.h"
5- // #include "pot/coroutines/async_condition_variable.h"
6-
71#include " pot/pot.h"
82
93#include < catch2/catch_test_macros.hpp>
2216pot::coroutines::task<int > add_one_task (int x) { co_return x + 1 ; }
2317pot::coroutines::lazy_task<int > add_one_lazy (int x) { co_return x + 1 ; }
2418
25- using pot::coroutines::task;
2619using pot::coroutines::lazy_task;
20+ using pot::coroutines::task;
2721
28- TEST_CASE (" task<int> returns value via get() and await " , " [task] " )
22+ TEST_CASE (" CORO " )
2923{
30- auto t = []() -> task<int > { co_return 42 ; }();
31- REQUIRE (t.get () == 42 );
32-
33- auto outer = [&]() -> task<int >
24+ SECTION (" task<int> returns value via get() and await" )
3425 {
35- int v = co_await []() -> task<int > { co_return 100 ; }();
36- co_return v + 1 ;
37- }();
38- REQUIRE (outer.get () == 101 );
39- }
26+ auto t = []() -> task<int >
27+ { co_return 42 ; }();
28+ REQUIRE (t.get () == 42 );
4029
41- TEST_CASE (" task propagates exceptions through get()/await" , " [task]" )
42- {
43- auto failing = []() -> task<int >
30+ auto outer = [&]() -> task<int >
31+ {
32+ int v = co_await []() -> task<int >
33+ { co_return 100 ; }();
34+ co_return v + 1 ;
35+ }();
36+ REQUIRE (outer.get () == 101 );
37+ }
38+
39+ SECTION (" task propagates exceptions through get()/await" )
4440 {
45- throw std::runtime_error (" boom" );
46- co_return 0 ;
47- }();
41+ auto failing = []() -> task<int >
42+ {
43+ throw std::runtime_error (" boom" );
44+ co_return 0 ;
45+ }();
4846
49- REQUIRE_THROWS_AS (failing.get (), std::runtime_error);
47+ REQUIRE_THROWS_AS (failing.get (), std::runtime_error);
5048
51- auto proxy = [&]() -> task<void >
52- {
53- try
49+ auto proxy = [&]() -> task<void >
5450 {
55- ( void ) co_await []() -> task< int >
51+ try
5652 {
57- throw std::logic_error (" bad" );
58- co_return 0 ;
59- }();
60- FAIL (" exception not thrown" );
61- }
62- catch (const std::logic_error &)
63- {
64- co_return ;
65- }
66- }();
67- REQUIRE_NOTHROW (proxy.get ());
68- }
53+ (void )co_await []() -> task<int >
54+ {
55+ throw std::logic_error (" bad" );
56+ co_return 0 ;
57+ }();
58+ FAIL (" exception not thrown" );
59+ }
60+ catch (const std::logic_error &)
61+ {
62+ co_return ;
63+ }
64+ }();
65+ REQUIRE_NOTHROW (proxy.get ());
66+ }
6967
70- TEST_CASE (" lazy_task is lazy until get()/await" , " [lazy_task]" )
71- {
72- std::atomic<bool > started{false };
73- auto make = [&]() -> lazy_task<int >
68+ SECTION (" lazy_task is lazy until get()/await" )
7469 {
75- started.store (true , std::memory_order_relaxed);
76- co_return 7 ;
77- };
78- auto lt = make ();
79-
80- REQUIRE (started.load (std::memory_order_relaxed) == false );
81- REQUIRE (lt.get () == 7 );
82- REQUIRE (started.load (std::memory_order_relaxed) == true );
83- }
84-
85- TEST_CASE (" lazy_task<void> await + continuation resumes caller" , " [lazy_task]" )
86- {
87- std::atomic<int > seq{0 };
70+ std::atomic<bool > started{false };
71+ auto make = [&]() -> lazy_task<int >
72+ {
73+ started.store (true , std::memory_order_relaxed);
74+ co_return 7 ;
75+ };
76+ auto lt = make ();
77+
78+ REQUIRE (started.load (std::memory_order_relaxed) == false );
79+ REQUIRE (lt.get () == 7 );
80+ REQUIRE (started.load (std::memory_order_relaxed) == true );
81+ }
8882
89- auto child = [&]() -> lazy_task<void >
83+ SECTION ( " lazy_task<void> await + continuation resumes caller " )
9084 {
91- seq.fetch_add (1 , std::memory_order_relaxed);
92- co_return ;
93- };
85+ std::atomic<int > seq{0 };
9486
95- auto parent = [&]() -> task<int >
96- {
97- seq.fetch_add (1 , std::memory_order_relaxed);
98- co_await child ();
99- seq.fetch_add (1 , std::memory_order_relaxed);
100- co_return seq.load (std::memory_order_relaxed);
101- }();
87+ auto child = [&]() -> lazy_task<void >
88+ {
89+ seq.fetch_add (1 , std::memory_order_relaxed);
90+ co_return ;
91+ };
10292
103- REQUIRE (parent.get () == 3 );
104- }
93+ auto parent = [&]() -> task<int >
94+ {
95+ seq.fetch_add (1 , std::memory_order_relaxed);
96+ co_await child ();
97+ seq.fetch_add (1 , std::memory_order_relaxed);
98+ co_return seq.load (std::memory_order_relaxed);
99+ }();
105100
106- TEST_CASE (" parfor processes all indices (void functor)" , " [parfor]" )
107- {
108- pot::executors::thread_pool_executor_lfgq ex (" Main" );
109- const int N = 1000 ;
110- std::vector<int > data (N, 0 );
101+ REQUIRE (parent.get () == 3 );
102+ }
111103
112- auto set_i = [&]( int i )
104+ SECTION ( " parfor processes all indices (void functor) " )
113105 {
114- data[static_cast <std::size_t >(i)] = i;
115- };
106+ pot::executors::thread_pool_executor_lflqt ex (" Main" );
107+ const int N = 1000 ;
108+ std::vector<int > data (N, 0 );
116109
117- auto task_par = pot::algorithms::parfor (ex, 0 , N, set_i);
118- REQUIRE_NOTHROW (task_par.get ());
110+ auto set_i = [&](int i)
111+ {
112+ data[static_cast <std::size_t >(i)] = i;
113+ };
119114
120- for (int i = 0 ; i < N; ++i)
121- {
122- REQUIRE (data[static_cast <std::size_t >(i)] == i);
123- }
124- }
115+ auto task_par = pot::algorithms::parfor (ex, 0 , N, set_i);
116+ REQUIRE_NOTHROW (task_par.get ());
125117
126- TEST_CASE ( " parfor supports functor returning task<void> " , " [parfor] " )
127- {
128- pot::executors::thread_pool_executor_lfgq ex ( " Main " );
129- const int N = 512 ;
130- std::atomic< int > sum{ 0 };
118+ for ( int i = 0 ; i < N; ++i )
119+ {
120+ REQUIRE (data[ static_cast <std:: size_t >(i)] == i );
121+ }
122+ }
131123
132- auto body_task = [&]( int i) -> task<void >
124+ SECTION ( " parfor supports functor returning task<void>" )
133125 {
134- sum.fetch_add (i, std::memory_order_relaxed);
135- co_return ;
136- };
137-
138- auto lt = pot::algorithms::parfor (ex, 0 , N, body_task);
139- lt.get ();
126+ pot::executors::thread_pool_executor_lflqt ex (" Main" );
127+ const int N = 512 ;
128+ std::atomic<int > sum{0 };
140129
141- const long long expected = 1LL * N * (N - 1 ) / 2 ;
142- REQUIRE (sum.load (std::memory_order_relaxed) == expected);
143- }
130+ auto body_task = [&](int i) -> task<void >
131+ {
132+ sum.fetch_add (i, std::memory_order_relaxed);
133+ co_return ;
134+ };
144135
145- TEST_CASE (" parfor respects chunking math (small ranges)" , " [parfor]" )
146- {
147- pot::executors::thread_pool_executor_lfgq ex (" Main" );
136+ auto lt = pot::algorithms::parfor (ex, 0 , N, body_task);
137+ lt.get ();
148138
149- const int from = 5 , to = 13 ;
150- std::vector<int > out (to - from, -1 );
139+ const long long expected = 1LL * N * (N - 1 ) / 2 ;
140+ REQUIRE (sum.load (std::memory_order_relaxed) == expected);
141+ }
151142
152- auto body = [&]( int i )
143+ SECTION ( " parfor respects chunking math (small ranges) " )
153144 {
154- out[static_cast <std::size_t >(i - from)] = i * 2 ;
155- };
145+ pot::executors::thread_pool_executor_lflqt ex (" Main" );
156146
157- auto lt = pot::algorithms::parfor (ex, from, to, body) ;
158- lt. get ( );
147+ const int from = 5 , to = 13 ;
148+ std::vector< int > out (to - from, - 1 );
159149
160- for (int i = 0 ; i < (to - from); ++i)
161- {
162- REQUIRE (out[static_cast <std::size_t >(i)] == (from + i) * 2 );
163- }
164- }
150+ auto body = [&](int i)
151+ {
152+ out[static_cast <std::size_t >(i - from)] = i * 2 ;
153+ };
165154
166- TEST_CASE (" parfor works with lazy functor returning lazy_task<void>" , " [parfor][lazy]" )
167- {
168- pot::executors::thread_pool_executor_lfgq ex (" Main" );
155+ auto lt = pot::algorithms::parfor (ex, from, to, body);
156+ lt.get ();
169157
170- const int N = 64 ;
171- std::atomic<int > cnt{0 };
158+ for (int i = 0 ; i < (to - from); ++i)
159+ {
160+ REQUIRE (out[static_cast <std::size_t >(i)] == (from + i) * 2 );
161+ }
162+ }
172163
173- auto lazy_body = [&]( int /* i */ ) -> lazy_task<void >
164+ SECTION ( " parfor works with lazy functor returning lazy_task<void>" )
174165 {
175- cnt.fetch_add (1 , std::memory_order_relaxed);
176- co_return ;
177- };
166+ pot::executors::thread_pool_executor_lflqt ex (" Main" );
167+
168+ const int N = 64 ;
169+ std::atomic<int > cnt{0 };
178170
179- auto lt = pot::algorithms::parfor (ex, 0 , N, lazy_body);
180- lt.get ();
171+ auto lazy_body = [&](int /* i*/ ) -> lazy_task<void >
172+ {
173+ cnt.fetch_add (1 , std::memory_order_relaxed);
174+ co_return ;
175+ };
181176
182- REQUIRE (cnt.load (std::memory_order_relaxed) == N);
183- }
177+ auto lt = pot::algorithms::parfor (ex, 0 , N, lazy_body);
178+ lt.get ();
179+
180+ REQUIRE (cnt.load (std::memory_order_relaxed) == N);
181+ }
182+ }
0 commit comments