50 , m_thread{ execute_thread, this }
56 m_pool_state.store(
false);
57 lock_type _task_lock{ m_task_lock, std::defer_lock };
58 if(!_task_lock.owns_lock())
60 m_task_cond.notify_one();
71 template <
typename FuncT,
typename... Args>
75 enqueue(std::forward<FuncT>(func), 0, std::move(args)...);
77 m_task_cond.notify_one();
82 std::deque<std::future<void>> _wait{};
84 lock_type _task_lock{ m_task_lock, std::defer_lock };
85 std::swap(m_task_wait, _wait);
86 if(!_task_lock.owns_lock())
88 m_task_cond.notify_all();
90 for(
auto& itr : _wait)
95 static void execute_thread(
this_type* _this)
97 while(_this->m_pool_state.load() || (_this->m_task_size.load() == 0))
100 lock_type _task_lock(_this->m_task_lock, std::defer_lock);
102 auto leave_pool = [&]() {
103 return !_this->m_pool_state.load() && (_this->m_task_size.load() == 0);
106 while(_this->m_task_size.load() == 0 && _this->m_pool_state.load())
109 if(!_task_lock.owns_lock())
113 if(_this->m_task_size.load() > 0)
117 if(!_this->m_pool_state.load())
123 _this->m_task_cond.wait(_task_lock, [&]() {
124 return (_this->m_task_size.load() > 0 || !_this->m_pool_state.load());
133 if(!_task_lock.owns_lock())
136 std::packaged_task<void()> _task{};
137 if(!_this->m_task_pool.empty() && _this->m_task_size.load() > 0)
139 --(_this->m_task_size);
140 _task = std::move(_this->m_task_pool.front());
141 _this->m_task_pool.pop_front();
145 if(_task_lock.owns_lock())
156 template <
typename FuncT,
typename... Args>
157 auto enqueue(FuncT&& func,
int, Args... args)
158 ->
decltype(func(std::declval<type&>(), args...), void())
162 .emplace(m_task_pool.end(),
163 [=]() { std::move(func)(*m_data, std::move(args)...); })
166 m_task_wait.emplace_back(std::move(_fut));
169 template <
typename FuncT,
typename... Args>
170 auto enqueue(FuncT&& func,
long, Args... args)
171 ->
decltype(func(std::declval<type*>(), args...), void())
173 auto&& _fut = m_task_pool
174 .emplace(m_task_pool.end(),
175 [=]() { std::move(func)(m_data, std::move(args)...); })
178 m_task_wait.emplace_back(std::move(_fut));
181 template <
typename FuncT,
typename... Args>
182 auto enqueue(FuncT&& func,
long long, Args... args) ->
decltype(func(args...), void())
184 auto&& _fut = m_task_pool
185 .emplace(m_task_pool.end(),
186 [=]() { std::move(func)(std::move(args)...); })
188 m_task_wait.emplace_back(std::move(_fut));
192 type* m_data =
nullptr;
193 std::atomic<bool> m_pool_state{
true };
194 std::atomic<size_t> m_task_size{ 0 };
195 std::mutex m_task_lock{};
196 std::condition_variable m_task_cond{};
197 std::deque<std::packaged_task<void()>> m_task_pool = {};
198 std::deque<std::future<void>> m_task_wait = {};
199 std::thread m_thread;
The declaration for the types for operations without definitions.
Include the macros for operations.
Declare the operations types.
auto operator()(FuncT &&func, Args... args)
async & operator=(async &&)=default
std::unique_lock< std::mutex > lock_type
async(const async &)=delete
async & operator=(const async &)=delete
std::packaged_task< void()> task_type