]> git.sesse.net Git - casparcg/blobdiff - common/future.h
No more use for retry_task in decklink_consumer now since audio and video are complet...
[casparcg] / common / future.h
index 5909e2be970eb8e4c351c1ee63885f0e0e516329..65bea20b56b42e347a2fe89a841fa2b7d4adb5f1 100644 (file)
-#pragma once\r
-\r
-#include "enum_class.h"\r
-\r
-#include <boost/thread/future.hpp>\r
-#include <boost/thread/thread.hpp>\r
-#include <boost/shared_ptr.hpp>\r
-\r
-#include <functional>\r
-\r
-namespace caspar {\r
-       \r
-struct launch_policy_def\r
-{\r
-       enum type\r
-       {\r
-               async = 1,\r
-               deferred = 2\r
-       };\r
-};\r
-typedef caspar::enum_class<launch_policy_def> launch;\r
-\r
-namespace detail {\r
-\r
-template<typename R, typename F>\r
-struct callback_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
-               : f(std::forward<F2>(f))\r
-               , done(false)\r
-       {\r
-       }\r
-               \r
-       void operator()()\r
-       {               \r
-               boost::lock_guard<boost::mutex> lock2(mutex);\r
-\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
-\r
-               done = true;\r
-       }\r
-};\r
-\r
-template<typename F>\r
-struct callback_object<void, F> : public boost::detail::future_object<void>\r
-{      \r
-       F f;\r
-       bool done;\r
-\r
-       template<typename F2>\r
-       callback_object(F2&& f)\r
-               : f(std::forward<F2>(f))\r
-               , done(false)\r
-       {\r
-       }\r
-\r
-       void operator()()\r
-       {\r
-               boost::lock_guard<boost::mutex> lock2(mutex);\r
-               \r
-               if(done)\r
-                       return;\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
-\r
-               done = true;\r
-       }\r
-};\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
-\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
-\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
-       else\r
-               throw std::invalid_argument("policy");\r
-}\r
-       \r
-template<typename F>\r
-auto async(F&& f) -> boost::unique_future<decltype(f())>\r
-{      \r
-       return async(launch::async | launch::deferred, std::forward<F>(f));\r
-}\r
-\r
-template<typename T>\r
-auto make_shared(boost::unique_future<T>&& f) -> boost::shared_future<T>\r
-{      \r
-       return boost::shared_future<T>(std::move(f));\r
-}\r
-\r
-template<typename T>\r
-auto flatten(boost::unique_future<T>&& f) -> boost::unique_future<decltype(f.get().get())>\r
-{\r
-       auto shared_f = make_shared(std::move(f));\r
-       return async(launch::deferred, [=]() mutable\r
-       {\r
-               return shared_f.get().get();\r
-       });\r
-}\r
-\r
+#pragma once
+
+#include <boost/thread/mutex.hpp>
+#include <boost/function.hpp>
+#include <boost/optional.hpp>
+
+#include <functional>
+#include <future>
+
+namespace caspar {
+
+template<typename T>
+auto flatten(std::future<T>&& f) -> std::future<typename std::decay<decltype(f.get().get())>::type>
+{
+       auto shared_f = f.share();
+       return std::async(std::launch::deferred, [=]() mutable -> typename std::decay<decltype(f.get().get())>::type
+       {
+               return shared_f.get().get();
+       });
+}
+
+template<typename F>
+bool is_ready(const F& future)
+{
+       return future.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
+}
+
+/**
+ * Wrap a value in a future with an already known result.
+ * <p>
+ * Useful when the result of an operation is already known at the time of
+ * calling.
+ *
+ * @param value The r-value to wrap.
+ *
+ * @return The future with the result set.
+ */
+template<class R>
+std::future<R> make_ready_future(R&& value)
+{
+       std::promise<R> p;
+
+       p.set_value(value);
+
+       return p.get_future();
+}
+
+static std::future<void> make_ready_future()
+{
+       std::promise<void> p;
+
+       p.set_value();
+
+       return p.get_future();
+}
+
 }
\ No newline at end of file