3 #include "enum_class.h"
\r
5 #include <boost/thread/future.hpp>
\r
6 #include <boost/thread/thread.hpp>
\r
7 #include <boost/shared_ptr.hpp>
\r
9 #include <functional>
\r
13 struct launch_policy_def
\r
21 typedef caspar::enum_class<launch_policy_def> launch;
\r
25 template<typename R>
\r
26 struct future_object_helper
\r
28 template<typename T, typename F>
\r
29 static void invoke(T& future_object, F& f)
\r
33 future_object.mark_finished_with_result_internal(f());
\r
37 future_object.mark_exceptional_finish_internal(boost::current_exception());
\r
43 struct future_object_helper<void>
\r
45 template<typename T, typename F>
\r
46 static void invoke(T& future_object, F& f)
\r
51 future_object.mark_finished_with_result_internal();
\r
55 future_object.mark_exceptional_finish_internal(boost::current_exception());
\r
60 template<typename R, typename F>
\r
61 struct deferred_future_object : public boost::detail::future_object<R>
\r
66 template<typename F2>
\r
67 deferred_future_object(F2&& f)
\r
68 : f(std::forward<F2>(f))
\r
71 set_wait_callback(std::mem_fn(&detail::deferred_future_object<R, F>::operator()), this);
\r
76 boost::lock_guard<boost::mutex> lock2(mutex);
\r
81 future_object_helper<R>::invoke(*this, f);
\r
87 template<typename R, typename F>
\r
88 struct async_future_object : public boost::detail::future_object<R>
\r
91 boost::thread thread;
\r
93 template<typename F2>
\r
94 async_future_object(F2&& f)
\r
95 : f(std::forward<F2>(f))
\r
96 , thread([this]{run();})
\r
100 ~async_future_object()
\r
107 boost::lock_guard<boost::mutex> lock2(mutex);
\r
109 future_object_helper<R>::invoke(*this, f);
\r
115 template<typename F>
\r
116 auto async(launch policy, F&& f) -> boost::unique_future<decltype(f())>
\r
118 typedef decltype(f()) result_type;
\r
119 typedef boost::detail::future_object<result_type> future_object_type;
\r
121 boost::shared_ptr<future_object_type> future_object;
\r
123 if((policy & launch::async) != 0)
\r
124 future_object = boost::static_pointer_cast<future_object_type>(boost::make_shared<detail::async_future_object<result_type, F>>(std::forward<F>(f)));
\r
125 else if((policy & launch::deferred) != 0)
\r
126 future_object = boost::static_pointer_cast<future_object_type>(boost::make_shared<detail::deferred_future_object<result_type, F>>(std::forward<F>(f)));
\r
128 throw std::invalid_argument("policy");
\r
130 boost::unique_future<result_type> future;
\r
132 static_assert(sizeof(future) == sizeof(future_object), "");
\r
134 reinterpret_cast<boost::shared_ptr<future_object_type>&>(future) = std::move(future_object); // Get around the "private" encapsulation.
\r
135 return std::move(future);
\r
138 template<typename F>
\r
139 auto async(F&& f) -> boost::unique_future<decltype(f())>
\r
141 return async(launch::async | launch::deferred, std::forward<F>(f));
\r
144 template<typename T>
\r
145 auto make_shared(boost::unique_future<T>&& f) -> boost::shared_future<T>
\r
147 return boost::shared_future<T>(std::move(f));
\r
150 template<typename T>
\r
151 auto flatten(boost::unique_future<T>&& f) -> boost::unique_future<decltype(f.get().get())>
\r
153 auto shared_f = make_shared(std::move(f));
\r
154 return async(launch::deferred, [=]() mutable
\r
156 return shared_f.get().get();
\r