38 static constexpr size_t default_queue_capacity = 1024;
40 using task_type = std::function<void()>;
43 std::atomic<bool> ready{
false};
44 std::atomic<bool> running{
true};
51 : tasks_(queue_capacity) {}
56 ready.store(
false, std::memory_order_release);
57 running.store(
false, std::memory_order_release);
64 bool is_ready() {
return ready.load(std::memory_order_acquire); }
72#if __cplusplus > 201402L
73 template <
class F,
class... Args>
typename std::invoke_result<F, Args...>::type
enqueue_and_wait(F&& f, Args&&... args) {
75 template <
class F,
class... Args>
typename std::result_of<F(Args...)>::type
enqueue_and_wait(F&& f, Args&&... args) {
88#if __cplusplus > 201402L
89 template <
class F,
class... Args>
auto enqueue(F&& f, Args&&... args) -> std::future<
typename std::invoke_result<F, Args...>::type> {
90 using return_type =
typename std::invoke_result<F, Args...>::type;
92 template <
class F,
class... Args>
auto enqueue(F&& f, Args&&... args) -> std::future<
typename std::result_of<F(Args...)>::type> {
93 using return_type =
typename std::result_of<F(Args...)>::type;
95 auto task = std::make_shared<std::packaged_task<return_type()>>(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
97 std::future<return_type> res = task->get_future();
98 while(running.load(std::memory_order_acquire)) {
99 if(tasks_.try_emplace([task]() { (*task)(); })) {
102 std::this_thread::yield();
104 throw std::runtime_error(
"thread_syncronizer is shutting down");
110 if(
auto* pending = tasks_.front()) {
113 task_type functor = std::move(*pending);
125 ready.store(
true, std::memory_order_release);
126 while(running.load(std::memory_order_acquire) && ready.load(std::memory_order_acquire)) {
131 std::this_thread::yield();
133 ready.store(
false, std::memory_order_release);