Skip to content

Commit cbce313

Browse files
committed
Execution/Planner
1 parent 351a616 commit cbce313

4 files changed

Lines changed: 93 additions & 0 deletions

File tree

modules/Execution/Execution.mpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export module CppUtils.Execution;
22

33
export import CppUtils.Execution.EventSystem;
4+
export import CppUtils.Execution.Planner;

modules/Execution/Planner.mpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
export module CppUtils.Execution.Planner;
2+
3+
import std;
4+
import CppUtils.Chrono;
5+
6+
export namespace CppUtils::Execution
7+
{
8+
class Planner final
9+
{
10+
public:
11+
inline ~Planner()
12+
{
13+
m_active = false;
14+
m_conditionVariable.notify_all();
15+
}
16+
17+
inline auto schedule(auto&& function, CppUtils::Chrono::Duration auto delay) -> void
18+
{
19+
if (not m_active)
20+
return;
21+
22+
m_threads.emplace_back(std::jthread{[this, function = std::forward<decltype(function)>(function), delay]() mutable -> void {
23+
auto lockGuard = std::unique_lock{m_mutex};
24+
if (m_conditionVariable.wait_for(lockGuard, delay, [this] { return not m_active.load(); }))
25+
return;
26+
if (m_active)
27+
function();
28+
}});
29+
}
30+
31+
private:
32+
std::atomic<bool> m_active = true;
33+
std::vector<std::jthread> m_threads;
34+
std::mutex m_mutex;
35+
std::condition_variable m_conditionVariable;
36+
};
37+
}

tests/Execution/Planner.mpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
export module CppUtils.UnitTests.Execution.Planner;
2+
3+
import std;
4+
import CppUtils;
5+
6+
export namespace CppUtils::UnitTest::Execution::Planner
7+
{
8+
inline auto _ = TestSuite{
9+
"Execution/Planner", {"UnitTest"}, [](auto& suite) {
10+
using namespace std::chrono_literals;
11+
12+
suite.addTest("Schedule and execute", [&] {
13+
auto planner = CppUtils::Execution::Planner{};
14+
auto executed = std::atomic<bool>{false};
15+
16+
planner.schedule([&executed] {
17+
executed = true;
18+
}, 50ms);
19+
20+
std::this_thread::sleep_for(100ms);
21+
22+
suite.expect(executed.load());
23+
});
24+
25+
suite.addTest("Cancel tasks on destruction", [&] {
26+
auto executed = std::atomic<bool>{false};
27+
28+
{
29+
auto planner = CppUtils::Execution::Planner{};
30+
31+
planner.schedule([&executed] {
32+
executed = true;
33+
}, 200ms);
34+
}
35+
36+
std::this_thread::sleep_for(300ms);
37+
38+
suite.expect(not executed.load());
39+
});
40+
41+
suite.addTest("Multiple tasks", [&] {
42+
auto planner = CppUtils::Execution::Planner{};
43+
auto counter = std::atomic<std::size_t>{0};
44+
45+
planner.schedule([&counter] { ++counter; }, 10ms);
46+
planner.schedule([&counter] { ++counter; }, 20ms);
47+
planner.schedule([&counter] { ++counter; }, 30ms);
48+
49+
std::this_thread::sleep_for(50ms);
50+
51+
suite.expectEqual(counter.load(), 3uz);
52+
});
53+
}};
54+
}

tests/UnitTests.mpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export import CppUtils.UnitTests.Container.Tree;
1313
export import CppUtils.UnitTests.Container.TypedStack;
1414
export import CppUtils.UnitTests.Container.Vector;
1515
export import CppUtils.UnitTests.Execution.EventSystem;
16+
export import CppUtils.UnitTests.Execution.Planner;
1617
export import CppUtils.UnitTests.FileSystem.Directory;
1718
export import CppUtils.UnitTests.FileSystem.File;
1819
export import CppUtils.UnitTests.FileSystem.Watcher;

0 commit comments

Comments
 (0)