#pragma once\r
\r
#include "../exception/win32_exception.h"\r
-#include "../utility/assert.h"\r
+#include "../utility/string.h"\r
+#include "../utility/move_on_copy.h"\r
#include "../log/log.h"\r
\r
#include <tbb/atomic.h>\r
#include <tbb/concurrent_queue.h>\r
\r
#include <boost/thread.hpp>\r
+#include <boost/optional.hpp>\r
#include <boost/noncopyable.hpp>\r
\r
#include <functional>\r
\r
}\r
\r
-enum priority\r
+enum task_priority\r
{\r
high_priority,\r
normal_priority,\r
priority_count\r
};\r
\r
-enum priority_class\r
+enum thread_priority\r
{\r
high_priority_class,\r
above_normal_priority_class,\r
below_normal_priority_class\r
};\r
\r
-namespace internal\r
-{\r
- template<typename T>\r
- struct move_on_copy\r
- {\r
- move_on_copy(const move_on_copy<T>& other) : value(std::move(other.value)){}\r
- move_on_copy(T&& value) : value(std::move(value)){}\r
- mutable T value;\r
- };\r
-\r
- template<typename T>\r
- move_on_copy<T> make_move_on_copy(T&& value)\r
- {\r
- return move_on_copy<T>(std::move(value));\r
- }\r
-}\r
-\r
class executor : boost::noncopyable\r
{\r
const std::string name_;\r
execution_queue_[normal_priority].set_capacity(capacity);\r
}\r
\r
- void set_priority_class(priority_class p)\r
+ void set_priority_class(thread_priority p)\r
{\r
begin_invoke([=]\r
{\r
}\r
\r
template<typename Func>\r
- auto begin_invoke(Func&& func, priority priority = normal_priority) -> boost::unique_future<decltype(func())> // noexcept\r
+ auto begin_invoke(Func&& func, task_priority priority = normal_priority) -> boost::unique_future<decltype(func())> // noexcept\r
{ \r
// Create a move on copy adaptor to avoid copying the functor into the queue, tbb::concurrent_queue does not support move semantics.\r
- auto task_adaptor = internal::make_move_on_copy(create_task(func));\r
+ auto task_adaptor = make_move_on_copy(create_task(func));\r
\r
auto future = task_adaptor.value.get_future();\r
\r
\r
return std::move(future); \r
}\r
-\r
- template<typename Func>\r
- auto try_begin_invoke(Func&& func, priority priority = normal_priority) -> boost::unique_future<decltype(func())> // noexcept\r
- {\r
- // Create a move on copy adaptor to avoid copying the functor into the queue, tbb::concurrent_queue does not support move semantics.\r
- auto task_adaptor = internal::make_move_on_copy(create_task(func));\r
- \r
- auto future = task_adaptor.value.get_future();\r
-\r
- if(priority == normal_priority || execution_queue_[normal_priority].try_push(nullptr))\r
- { \r
- execution_queue_[priority].try_push([=]\r
- {\r
- try{task_adaptor.value();}\r
- catch(boost::task_already_started&){}\r
- catch(...)\r
- {\r
- CASPAR_LOG_CURRENT_EXCEPTION();\r
- throw;\r
- }\r
- });\r
- }\r
- \r
- return std::move(future); \r
- }\r
-\r
+ \r
template<typename Func>\r
- auto invoke(Func&& func, priority prioriy = normal_priority) -> decltype(func()) // noexcept\r
+ auto invoke(Func&& func, task_priority prioriy = normal_priority) -> decltype(func()) // noexcept\r
{\r
if(boost::this_thread::get_id() == thread_.get_id()) // Avoids potential deadlock.\r
return func();\r
\r
return begin_invoke(std::forward<Func>(func), prioriy).get();\r
}\r
-\r
- template<typename Func>\r
- auto try_invoke(Func&& func, priority prioriy = normal_priority) -> decltype(func()) // noexcept\r
- {\r
- if(boost::this_thread::get_id() == thread_.get_id()) // Avoids potential deadlock.\r
- return func();\r
- \r
- return try_begin_invoke(std::forward<Func>(func), prioriy).get();\r
- }\r
-\r
+ \r
void yield() // noexcept\r
{\r
if(boost::this_thread::get_id() != thread_.get_id()) // Only yield when calling from execution thread.\r
win32_exception::install_handler(); \r
detail::SetThreadName(GetCurrentThreadId(), name_.c_str());\r
while(is_running_)\r
- execute();\r
+ {\r
+ try\r
+ {\r
+ execute();\r
+ }\r
+ catch(...)\r
+ {\r
+ CASPAR_LOG_CURRENT_EXCEPTION();\r
+ }\r
+ }\r
} \r
};\r
\r