3 #include "../exception/exceptions.h"
\r
4 #include "../exception/win32_exception.h"
\r
6 #include <boost/thread.hpp>
\r
8 #include <tbb/atomic.h>
\r
9 #include <tbb/concurrent_queue.h>
\r
11 #include <functional>
\r
13 namespace caspar { namespace common {
\r
18 explicit executor(const std::function<void()>& run_func = nullptr)
\r
20 is_running_ = false;
\r
21 run_func_ = run_func != nullptr ? run_func : [=]{run();};
\r
31 if(is_running_.fetch_and_store(true))
\r
33 thread_ = boost::thread(run_func_);
\r
36 bool is_running() const
\r
43 if(is_running_.fetch_and_store(false))
\r
45 execution_queue_.clear();
\r
46 execution_queue_.push([](){});
\r
53 std::function<void()> func;
\r
54 execution_queue_.pop(func);
\r
60 std::function<void()> func;
\r
61 if(execution_queue_.try_pop(func))
\r
64 return func != nullptr;
\r
69 execution_queue_.clear();
\r
72 template<typename Func>
\r
73 void enqueue(Func&& func)
\r
75 execution_queue_.push([=]{try{func();}catch(...){CASPAR_LOG_CURRENT_EXCEPTION();}});
\r
78 template<typename Func>
\r
79 auto begin_invoke(Func&& func) -> boost::unique_future<decltype(func())>
\r
81 typedef decltype(func()) result_type;
\r
83 auto task = std::make_shared<boost::packaged_task<result_type>>(std::forward<Func>(func)); // boost::packaged_task cannot be moved, need to used shared_ptr.
\r
84 auto future = task->get_future();
\r
86 task->set_wait_callback(std::function<void(decltype(*task)& task)>([=](decltype(*task)& task) // The std::function wrapper is required in order to add ::result_type to functor class.
\r
90 if(boost::this_thread::get_id() == thread_.get_id()) // Avoids potential deadlock.
\r
93 catch(boost::task_already_started&){}
\r
95 execution_queue_.push([=]
\r
101 catch(boost::task_already_started&){}
\r
104 return std::move(future);
\r
107 template<typename Func>
\r
108 auto invoke(Func&& func) -> decltype(func())
\r
110 if(boost::this_thread::get_id() == thread_.get_id()) // Avoids potential deadlock.
\r
113 return begin_invoke(std::forward<Func>(func)).get();
\r
120 win32_exception::install_handler();
\r
125 std::function<void()> run_func_;
\r
126 boost::thread thread_;
\r
127 tbb::atomic<bool> is_running_;
\r
128 tbb::concurrent_bounded_queue<std::function<void()>> execution_queue_;
\r