Skip to content

Commit 93c0f01

Browse files
committed
Added small tests for resume_on
1 parent 5879726 commit 93c0f01

8 files changed

Lines changed: 227 additions & 142 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ set(POT_HEADERS
2828
include/${PROJECT_NAME}/simd/simd_forced.h
2929

3030
include/${PROJECT_NAME}/sync/sync_object.h
31-
include/${PROJECT_NAME}/sync/async_lock.h
31+
# include/${PROJECT_NAME}/sync/async_lock.h
3232

3333
include/${PROJECT_NAME}/traits/pot_traits.h
3434
include/${PROJECT_NAME}/traits/compare.h
@@ -39,7 +39,6 @@ set(POT_HEADERS
3939
include/${PROJECT_NAME}/utils/this_thread.h
4040
include/${PROJECT_NAME}/utils/cache_line.h
4141
include/${PROJECT_NAME}/utils/unique_function.h
42-
4342
include/${PROJECT_NAME}/executors/executor.h
4443
include/${PROJECT_NAME}/executors/inline_executor.h
4544
include/${PROJECT_NAME}/executors/thread_executor.h

include/pot/algorithms/parsections.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ namespace pot::algorithms
5050
})
5151
), ...);
5252

53-
for (auto it = tasks.begin(); it != tasks.end(); ++it)
54-
std::move(*it).sync_wait();
53+
co_await pot::coroutines::when_all(tasks);
5554

5655
co_return;
5756
}

include/pot/coroutines/resume_on.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ namespace pot::coroutines
3030
* @return An awaitable that, when awaited, schedules resumption on @p executor.
3131
*
3232
*/
33-
auto resume_on(pot::executor &executor) noexcept
33+
inline auto resume_on(pot::executor &executor) noexcept
3434
{
3535
return details::resume_on_awaitable(executor);
3636
}

include/pot/coroutines/task.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,8 +303,6 @@ namespace pot::coroutines
303303
}
304304
}
305305

306-
void sync_wait() {}
307-
308306
~task()
309307
{
310308
if (m_handle)

include/pot/executors/thread_pool_executor.h

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,8 @@
1212
#include "pot/algorithms/lfqueue.h"
1313
#include "pot/utils/unique_function.h"
1414

15-
#include <iostream>
1615
namespace pot::executors
1716
{
18-
1917
class thread_pool_executor_lflqt final : public executor
2018
{
2119
public:
@@ -52,8 +50,10 @@ namespace pot::executors
5250
void join()
5351
{
5452
for (auto &t : m_workers)
53+
{
5554
if (t.joinable())
5655
t.join();
56+
}
5757
}
5858

5959
void shutdown() override
@@ -69,13 +69,11 @@ namespace pot::executors
6969
throw std::runtime_error("shutting down");
7070

7171
std::size_t idx = m_round_robin.fetch_add(1, std::memory_order_relaxed) % m_thread_count;
72-
m_pending.fetch_add(1, std::memory_order_release);
73-
72+
7473
if (!m_queues[idx]->push_back(std::move(f)))
75-
{
76-
m_pending.fetch_sub(1, std::memory_order_release);
7774
throw std::runtime_error("cant push_back lfqueue");
78-
}
75+
76+
m_pending.fetch_add(1, std::memory_order_release);
7977
m_cv.notify_one();
8078
}
8179

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ include(${CMAKE_SOURCE_DIR}/cmake/Catch2.cmake)
44
# Create test executable
55
set(TEST_SOURCES
66
test_coro.cpp
7+
test_resume_on.cpp
78
)
89

910
add_executable(tests ${TEST_SOURCES})

test/test_coro.cpp

Lines changed: 127 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
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>
@@ -22,162 +16,167 @@
2216
pot::coroutines::task<int> add_one_task(int x) { co_return x + 1; }
2317
pot::coroutines::lazy_task<int> add_one_lazy(int x) { co_return x + 1; }
2418

25-
using pot::coroutines::task;
2619
using 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

Comments
 (0)