16 #ifndef ALEXA_CLIENT_SDK_AVSCOMMON_UTILS_INCLUDE_AVSCOMMON_UTILS_THREADING_EXECUTOR_H_
17 #define ALEXA_CLIENT_SDK_AVSCOMMON_UTILS_INCLUDE_AVSCOMMON_UTILS_THREADING_EXECUTOR_H_
20 #include <condition_variable>
48 Executor(
const std::chrono::milliseconds& delayExit = std::chrono::milliseconds(1000));
63 template <
typename Task,
typename... Args>
64 auto submit(Task task, Args&&...
args) -> std::future<decltype(task(
args...))>;
75 template <
typename Task,
typename... Args>
91 using Queue = std::deque<std::function<void()>>;
113 std::function<void()> pop();
125 template <
typename Task,
typename... Args>
126 auto pushTo(
bool front, Task task, Args&&...
args) -> std::future<decltype(task(
args...))>;
132 bool m_threadRunning;
135 std::chrono::milliseconds m_timeout;
138 std::mutex m_queueMutex;
141 std::atomic_bool m_shutdown;
144 std::shared_ptr<power::PowerResource> m_powerResource;
147 std::condition_variable m_delayedCondition;
156 template <
typename Task,
typename... Args>
159 return pushTo(front, std::forward<Task>(task), std::forward<Args>(
args)...);
162 template <
typename Task,
typename... Args>
165 return pushTo(front, std::forward<Task>(task), std::forward<Args>(
args)...);
174 template <
typename T>
175 inline static void forwardPromise(std::shared_ptr<std::promise<T>> promise, std::future<T>* future) {
176 #if __cpp_exceptions || defined(__EXCEPTIONS)
179 promise->set_value(future->get());
180 #if __cpp_exceptions || defined(__EXCEPTIONS)
182 promise->set_exception(std::current_exception());
195 #if __cpp_exceptions || defined(__EXCEPTIONS)
199 promise->set_value();
200 #if __cpp_exceptions || defined(__EXCEPTIONS)
202 promise->set_exception(std::current_exception());
207 template <
typename Task,
typename... Args>
208 auto Executor::pushTo(
bool front, Task task, Args&&...
args) -> std::future<decltype(task(
args...))> {
210 auto boundTask = std::bind(std::forward<Task>(task), std::forward<Args>(
args)...);
226 using PackagedTaskType = std::packaged_task<decltype(boundTask())()>;
227 auto packaged_task = std::make_shared<PackagedTaskType>(boundTask);
230 auto cleanupPromise = std::make_shared<std::promise<decltype(task(
args...))>>();
231 auto cleanupFuture = cleanupPromise->get_future();
234 auto translated_task = [packaged_task, cleanupPromise]()
mutable {
236 packaged_task->operator()();
238 auto taskFuture = packaged_task->get_future();
240 packaged_task.reset();
246 packaged_task.reset();
249 bool restart =
false;
250 std::lock_guard<std::mutex> queueLock{m_queueMutex};
252 restart = !m_threadRunning;
253 if (m_powerResource) {
254 m_powerResource->acquire();
256 m_queue.emplace(front ? m_queue.begin() : m_queue.end(), std::move(translated_task));
258 using FutureType = decltype(task(
args...));
259 return std::future<FutureType>();
264 m_taskThread.start(std::bind(&Executor::runNext,
this));
265 m_threadRunning =
true;
269 m_delayedCondition.notify_one();
270 return cleanupFuture;
278 #endif // ALEXA_CLIENT_SDK_AVSCOMMON_UTILS_INCLUDE_AVSCOMMON_UTILS_THREADING_EXECUTOR_H_