typedef caspar::enum_class<launch_policy_def> launch;\r
\r
namespace detail {\r
+ \r
+template<typename R>\r
+struct future_object_helper\r
+{ \r
+ template<typename T, typename F>\r
+ static void invoke(T& future_object, F& f)\r
+ { \r
+ try\r
+ {\r
+ future_object.mark_finished_with_result_internal(f());\r
+ }\r
+ catch(...)\r
+ {\r
+ future_object.mark_exceptional_finish_internal(boost::current_exception());\r
+ }\r
+ }\r
+};\r
+\r
+template<>\r
+struct future_object_helper<void>\r
+{ \r
+ template<typename T, typename F>\r
+ static void invoke(T& future_object, F& f)\r
+ { \r
+ try\r
+ {\r
+ f();\r
+ future_object.mark_finished_with_result_internal();\r
+ }\r
+ catch(...)\r
+ {\r
+ future_object.mark_exceptional_finish_internal(boost::current_exception());\r
+ }\r
+ }\r
+};\r
\r
template<typename R, typename F>\r
-struct callback_object: public boost::detail::future_object<R>\r
+struct deferred_future_object : public boost::detail::future_object<R>\r
{ \r
F f;\r
bool done;\r
\r
template<typename F2>\r
- callback_object(F2&& f)\r
+ deferred_future_object(F2&& f)\r
: f(std::forward<F2>(f))\r
, done(false)\r
{\r
+ set_wait_callback(std::mem_fn(&detail::deferred_future_object<R, F>::operator()), this);\r
}\r
\r
void operator()()\r
if(done)\r
return;\r
\r
- try\r
- {\r
- this->mark_finished_with_result_internal(f());\r
- }\r
- catch(...)\r
- {\r
- this->mark_exceptional_finish_internal(boost::current_exception());\r
- }\r
+ future_object_helper<R>::invoke(*this, f);\r
\r
done = true;\r
}\r
};\r
\r
-template<typename F>\r
-struct callback_object<void, F> : public boost::detail::future_object<void>\r
+template<typename R, typename F>\r
+struct async_future_object : public boost::detail::future_object<R>\r
{ \r
F f;\r
- bool done;\r
+ boost::thread thread;\r
\r
template<typename F2>\r
- callback_object(F2&& f)\r
+ async_future_object(F2&& f)\r
: f(std::forward<F2>(f))\r
- , done(false)\r
+ , thread([this]{run();})\r
{\r
}\r
\r
- void operator()()\r
+ ~async_future_object()\r
{\r
- boost::lock_guard<boost::mutex> lock2(mutex);\r
- \r
- if(done)\r
- return;\r
+ thread.join();\r
+ }\r
\r
- try\r
- {\r
- f();\r
- this->mark_finished_with_result_internal();\r
- }\r
- catch(...)\r
- {\r
- this->mark_exceptional_finish_internal(boost::current_exception());\r
- }\r
+ void run()\r
+ {\r
+ boost::lock_guard<boost::mutex> lock2(mutex); \r
\r
- done = true;\r
+ future_object_helper<R>::invoke(*this, f);\r
}\r
};\r
\r
template<typename F>\r
auto async(launch policy, F&& f) -> boost::unique_future<decltype(f())>\r
{ \r
- typedef decltype(f()) result_type;\r
- \r
- if((policy & launch::async) != 0)\r
- {\r
- typedef boost::packaged_task<result_type> task_t;\r
+ typedef decltype(f()) result_type; \r
+ typedef boost::detail::future_object<result_type> future_object_type;\r
\r
- auto task = task_t(std::forward<F>(f)); \r
- auto future = task.get_future();\r
- \r
- boost::thread(std::move(task)).detach();\r
- \r
- return std::move(future);\r
- }\r
- else if((policy & launch::deferred) != 0)\r
- { \r
- // HACK: THIS IS A MAYOR HACK!\r
-\r
- typedef boost::detail::future_object<result_type> future_object_t;\r
- \r
- auto callback_object = boost::make_shared<detail::callback_object<result_type, F>>(std::forward<F>(f));\r
- auto callback_object_raw = callback_object.get();\r
- auto future_object = boost::static_pointer_cast<future_object_t>(std::move(callback_object));\r
-\r
- future_object->set_wait_callback(std::mem_fn(&detail::callback_object<result_type, F>::operator()), callback_object_raw);\r
- \r
- boost::unique_future<result_type> future;\r
+ boost::shared_ptr<future_object_type> future_object;\r
\r
- static_assert(sizeof(future) == sizeof(future_object), "");\r
-\r
- reinterpret_cast<boost::shared_ptr<future_object_t>&>(future) = std::move(future_object); // Get around the "private" encapsulation.\r
- return std::move(future);\r
- }\r
+ if((policy & launch::async) != 0)\r
+ future_object = boost::static_pointer_cast<future_object_type>(boost::make_shared<detail::async_future_object<result_type, F>>(std::forward<F>(f)));\r
+ else if((policy & launch::deferred) != 0)\r
+ future_object = boost::static_pointer_cast<future_object_type>(boost::make_shared<detail::deferred_future_object<result_type, F>>(std::forward<F>(f))); \r
else\r
throw std::invalid_argument("policy");\r
+ \r
+ boost::unique_future<result_type> future;\r
+\r
+ static_assert(sizeof(future) == sizeof(future_object), "");\r
+\r
+ reinterpret_cast<boost::shared_ptr<future_object_type>&>(future) = std::move(future_object); // Get around the "private" encapsulation.\r
+ return std::move(future);\r
}\r
\r
template<typename F>\r