Skip to content

Commit ffb8d89

Browse files
committed
Refactor coro::default_executor
1 parent 82cb974 commit ffb8d89

File tree

6 files changed

+64
-202
lines changed

6 files changed

+64
-202
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,7 @@ struct Params
801801

802802
int main()
803803
{
804-
auto default_scheduler = coro::default_executor::instance();
804+
auto default_scheduler = coro::default_executor::executor();
805805
std::vector<coro::task<void>> tasks{};
806806
auto params = std::make_shared<Params>();
807807
params->max_value = 20;

examples/coro_condition_variable.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ struct Params
8989

9090
int main()
9191
{
92-
auto default_scheduler = coro::default_executor::instance();
92+
auto default_scheduler = coro::default_executor::executor();
9393
std::vector<coro::task<void>> tasks{};
9494
auto params = std::make_shared<Params>();
9595
params->max_value = 20;

include/coro/condition_variable.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ class strategy_based_on_io_scheduler
198198

199199
public:
200200
explicit strategy_based_on_io_scheduler(
201-
std::shared_ptr<io_scheduler> io_scheduler = coro::default_executor::instance()->get_io_scheduler());
201+
std::shared_ptr<io_scheduler> io_scheduler = coro::default_executor::io_executor());
202202

203203
~strategy_based_on_io_scheduler();
204204

include/coro/default_executor.hpp

+18-86
Original file line numberDiff line numberDiff line change
@@ -6,99 +6,31 @@
66
#include "coro/thread_pool.hpp"
77
#endif
88

9-
namespace coro
9+
namespace coro::default_executor
1010
{
1111

1212
/**
13-
* Default executor for universal access to default scheduler or default thread pool.
14-
* This coro::default_executor supports the concept of coro::concepts::executor.
13+
* Set up default coro::thread_pool::options before constructing a single instance of the default_executor
14+
* @param thread_pool_options thread_pool options
1515
*/
16-
class default_executor
17-
{
18-
public:
19-
default_executor();
20-
21-
/**
22-
* Getting a single instance of default_executor per process
23-
* @return single instance of default_executor
24-
*/
25-
static default_executor* instance();
26-
27-
#ifdef LIBCORO_FEATURE_NETWORKING
28-
[[nodiscard]] auto schedule() -> coro::io_scheduler::schedule_operation;
29-
#else
30-
[[nodiscard]] auto schedule() -> coro::thread_pool::operation;
31-
#endif
32-
33-
bool spawn(coro::task<void>&& task) noexcept;
34-
[[nodiscard]] auto yield() { return schedule(); };
35-
bool resume(std::coroutine_handle<> handle);
36-
std::size_t size();
37-
bool empty();
38-
void shutdown();
39-
40-
/**
41-
* Schedules a task on the thread pool or io_scheduler and returns another task that must be awaited on for
42-
* completion. This can be done via co_await in a coroutine context or coro::sync_wait() outside of coroutine
43-
* context.
44-
* @tparam return_type The return value of the task.
45-
* @param task The task to schedule on the thread pool.
46-
* @return The task to await for the input task to complete.
47-
*/
48-
template<typename return_type>
49-
[[nodiscard]] auto schedule(coro::task<return_type> task) -> coro::task<return_type>
50-
{
51-
co_await schedule();
52-
co_return co_await task;
53-
}
54-
55-
#ifdef LIBCORO_FEATURE_NETWORKING
56-
/**
57-
* Set up default coro::io_scheduler::options before constructing a single instance of the default_executor
58-
* @param io_scheduler_options io_scheduler options
59-
*/
60-
static void set_io_scheduler_options(io_scheduler::options io_scheduler_options);
61-
62-
/**
63-
* Get default coro::io_scheduler
64-
*/
65-
std::shared_ptr<io_scheduler> get_io_scheduler();
66-
#else
67-
/**
68-
* Set up default coro::thread_pool::options before constructing a single instance of the default_executor
69-
* @param thread_pool_options thread_pool options
70-
*/
71-
static void set_thread_pool_options(thread_pool::options thread_pool_options);
16+
void set_executor_options(thread_pool::options thread_pool_options);
7217

73-
/**
74-
* Get default coro::thread_pool
75-
*/
76-
std::shared_ptr<thread_pool> get_thread_pool();
77-
#endif
18+
/**
19+
* Get default coro::thread_pool
20+
*/
21+
std::shared_ptr<thread_pool> executor();
7822

79-
private:
8023
#ifdef LIBCORO_FEATURE_NETWORKING
81-
/**
82-
* Options for default coro::io_scheduler
83-
*/
84-
static io_scheduler::options s_io_scheduler_options;
85-
86-
/**
87-
* Default coro::io_scheduler
88-
*/
89-
std::shared_ptr<io_scheduler> m_io_scheduler;
90-
#else
91-
92-
/**
93-
* Options for default coro::thread_pool
94-
*/
95-
static thread_pool::options s_thread_pool_options;
24+
/**
25+
* Set up default coro::io_scheduler::options before constructing a single instance of the default_io_executor
26+
* @param io_scheduler_options io_scheduler options
27+
*/
28+
void set_io_executor_options(io_scheduler::options io_scheduler_options);
9629

97-
/**
98-
* Default coro::thread_pool
99-
*/
100-
std::shared_ptr<thread_pool> m_thread_pool;
30+
/**
31+
* Get default coro::io_scheduler
32+
*/
33+
std::shared_ptr<io_scheduler> io_executor();
10134
#endif
102-
};
10335

104-
} // namespace coro
36+
} // namespace coro::default_executor

src/default_executor.cpp

+26-95
Original file line numberDiff line numberDiff line change
@@ -2,115 +2,46 @@
22
#include <atomic>
33
#include <memory>
44

5-
static std::atomic<coro::default_executor*> s_default_executor = {nullptr};
5+
static coro::thread_pool::options s_default_executor_options;
6+
static std::atomic<std::shared_ptr<coro::thread_pool>> s_default_executor = {nullptr};
67

78
#ifdef LIBCORO_FEATURE_NETWORKING
8-
coro::io_scheduler::options coro::default_executor::s_io_scheduler_options;
9-
#else
10-
coro::thread_pool::options coro::default_executor::s_thread_pool_options;
9+
static coro::io_scheduler::options s_default_io_executor_options;
10+
static std::atomic<std::shared_ptr<coro::io_scheduler>> s_default_io_executor = {nullptr};
1111
#endif
1212

13-
coro::default_executor* coro::default_executor::instance()
13+
void coro::default_executor::set_executor_options(thread_pool::options thread_pool_options)
1414
{
15-
auto* result = s_default_executor.load(std::memory_order::acquire);
15+
s_default_executor_options = thread_pool_options;
16+
}
17+
18+
std::shared_ptr<coro::thread_pool> coro::default_executor::executor()
19+
{
20+
auto result = s_default_executor.load(std::memory_order::acquire);
1621
if (!result)
1722
{
18-
auto ptr = std::make_unique<default_executor>();
23+
auto ptr = std::make_shared<coro::thread_pool>(s_default_executor_options);
1924
if (s_default_executor.compare_exchange_strong(
20-
result, ptr.get(), std::memory_order::release, std::memory_order::acquire))
21-
result = ptr.release();
25+
result, ptr, std::memory_order::release, std::memory_order::acquire))
26+
result = ptr;
2227
}
2328
return result;
2429
}
2530

26-
coro::default_executor::default_executor()
27-
{
28-
#ifdef LIBCORO_FEATURE_NETWORKING
29-
m_io_scheduler = io_scheduler::make_shared(s_io_scheduler_options);
30-
#else
31-
m_thread_pool = std::make_shared<thread_pool>(s_thread_pool_options);
32-
#endif
33-
}
34-
35-
bool coro::default_executor::spawn(coro::task<void>&& task) noexcept
36-
{
37-
#ifdef LIBCORO_FEATURE_NETWORKING
38-
return m_io_scheduler->spawn(std::move(task));
39-
#else
40-
return m_thread_pool->spawn(std::move(task));
41-
#endif
42-
}
43-
44-
bool coro::default_executor::resume(std::coroutine_handle<> handle)
45-
{
46-
#ifdef LIBCORO_FEATURE_NETWORKING
47-
return m_io_scheduler->resume(handle);
48-
#else
49-
return m_thread_pool->resume(handle);
50-
#endif
51-
}
52-
53-
std::size_t coro::default_executor::size()
54-
{
55-
#ifdef LIBCORO_FEATURE_NETWORKING
56-
return m_io_scheduler->size();
57-
#else
58-
return m_thread_pool->size();
59-
#endif
60-
}
61-
62-
bool coro::default_executor::empty()
31+
void coro::default_executor::set_io_executor_options(io_scheduler::options io_scheduler_options)
6332
{
64-
#ifdef LIBCORO_FEATURE_NETWORKING
65-
return m_io_scheduler->empty();
66-
#else
67-
return m_thread_pool->empty();
68-
#endif
33+
s_default_io_executor_options = io_scheduler_options;
6934
}
7035

71-
void coro::default_executor::shutdown()
36+
std::shared_ptr<coro::io_scheduler> coro::default_executor::io_executor()
7237
{
73-
#ifdef LIBCORO_FEATURE_NETWORKING
74-
m_io_scheduler->shutdown();
75-
#else
76-
m_thread_pool->shutdown();
77-
#endif
78-
}
79-
80-
#ifdef LIBCORO_FEATURE_NETWORKING
81-
auto coro::default_executor::schedule() -> coro::io_scheduler::schedule_operation
82-
{
83-
return m_io_scheduler->schedule();
84-
}
85-
#else
86-
auto coro::default_executor::schedule() -> coro::thread_pool::operation
87-
{
88-
return m_thread_pool->schedule();
89-
}
90-
#endif
91-
92-
#ifdef LIBCORO_FEATURE_NETWORKING
93-
94-
void coro::default_executor::set_io_scheduler_options(io_scheduler::options io_scheduler_options)
95-
{
96-
s_io_scheduler_options = io_scheduler_options;
97-
}
98-
99-
std::shared_ptr<coro::io_scheduler> coro::default_executor::get_io_scheduler()
100-
{
101-
return m_io_scheduler;
102-
}
103-
104-
#else
105-
106-
void coro::default_executor::set_thread_pool_options(thread_pool::options thread_pool_options)
107-
{
108-
s_thread_pool_options = thread_pool_options;
109-
}
110-
111-
std::shared_ptr<coro::thread_pool> coro::default_executor::get_thread_pool()
112-
{
113-
return m_thread_pool;
38+
auto result = s_default_io_executor.load(std::memory_order::acquire);
39+
if (!result)
40+
{
41+
auto ptr = coro::io_scheduler::make_shared(s_default_io_executor_options);
42+
if (s_default_io_executor.compare_exchange_strong(
43+
result, ptr, std::memory_order::release, std::memory_order::acquire))
44+
result = ptr;
45+
}
46+
return result;
11447
}
115-
116-
#endif

test/test_condition_variable.cpp

+17-18
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ TEST_CASE("condition_variable single waiter", "[condition_variable]")
1515

1616
std::cout << "condition_variable single waiter" << std::endl;
1717

18-
auto sched = coro::default_executor::instance()->get_io_scheduler();
18+
auto sched = coro::default_executor::io_executor();
1919
coro::mutex m;
2020
coro::condition_variable cv;
2121

@@ -115,7 +115,7 @@ TEST_CASE("condition_variable one notifier and one waiter", "[condition_variable
115115

116116
struct BaseParams
117117
{
118-
std::shared_ptr<coro::io_scheduler> sched = coro::default_executor::instance()->get_io_scheduler();
118+
std::shared_ptr<coro::io_scheduler> sched = coro::default_executor::io_executor();
119119
coro::mutex m;
120120
coro::condition_variable cv{sched};
121121
};
@@ -170,11 +170,10 @@ TEST_CASE("condition_variable notify_all", "[condition_variable]")
170170

171171
struct BaseParams
172172
{
173-
std::shared_ptr<coro::io_scheduler> sched = coro::default_executor::instance()->get_io_scheduler();
174-
;
175-
coro::mutex m;
176-
coro::condition_variable cv{sched};
177-
int number_of_timeouts{};
173+
std::shared_ptr<coro::io_scheduler> sched = coro::default_executor::io_executor();
174+
coro::mutex m;
175+
coro::condition_variable cv{sched};
176+
int number_of_timeouts{};
178177
};
179178

180179
BaseParams bp;
@@ -223,17 +222,17 @@ TEST_CASE("condition_variable for thread-safe-queue between producers and consum
223222

224223
struct BaseParams
225224
{
226-
coro::default_executor* sched = coro::default_executor::instance();
227-
coro::mutex m;
228-
coro::condition_variable cv;
229-
std::atomic_bool cancel{false};
230-
std::atomic_int32_t next{0};
231-
int32_t max_value{10000};
232-
std::queue<int32_t> q;
233-
std::set<int32_t> values_not_delivered;
234-
std::set<int32_t> values_not_produced;
235-
std::atomic_int32_t producers{0};
236-
std::atomic_int32_t consumers{0};
225+
std::shared_ptr<coro::thread_pool> sched = coro::default_executor::executor();
226+
coro::mutex m;
227+
coro::condition_variable cv;
228+
std::atomic_bool cancel{false};
229+
std::atomic_int32_t next{0};
230+
int32_t max_value{10000};
231+
std::queue<int32_t> q;
232+
std::set<int32_t> values_not_delivered;
233+
std::set<int32_t> values_not_produced;
234+
std::atomic_int32_t producers{0};
235+
std::atomic_int32_t consumers{0};
237236
};
238237

239238
BaseParams bp;

0 commit comments

Comments
 (0)