X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=common%2Ffuture.h;h=65bea20b56b42e347a2fe89a841fa2b7d4adb5f1;hb=49949fedc13aff4be9a7c40c72a0a96e7670836c;hp=85a848cac96b1b4888b6bd8156c69904a808b8af;hpb=a9bb7ddbd5ce4774a1d29fdd5f4e7a22e4bfed40;p=casparcg diff --git a/common/future.h b/common/future.h index 85a848cac..65bea20b5 100644 --- a/common/future.h +++ b/common/future.h @@ -1,159 +1,57 @@ -#pragma once - -#include "enum_class.h" - -#include -#include -#include - -#include - -namespace caspar { - -struct launch_policy_def -{ - enum type - { - async = 1, - deferred = 2 - }; -}; -typedef caspar::enum_class launch; - -namespace detail { - -template -struct callback_object: public boost::detail::future_object -{ - F f; - bool done; - - template - callback_object(F2&& f) - : f(std::forward(f)) - , done(false) - { - } - - void operator()() - { - boost::lock_guard lock2(mutex); - - if(done) - return; - - try - { - this->mark_finished_with_result_internal(f()); - } - catch(...) - { - this->mark_exceptional_finish_internal(boost::current_exception()); - } - - done = true; - } -}; - -template -struct callback_object : public boost::detail::future_object -{ - F f; - bool done; - - template - callback_object(F2&& f) - : f(std::forward(f)) - , done(false) - { - } - - void operator()() - { - boost::lock_guard lock2(mutex); - - if(done) - return; - - try - { - f(); - this->mark_finished_with_result_internal(); - } - catch(...) - { - this->mark_exceptional_finish_internal(boost::current_exception()); - } - - done = true; - } -}; - -} - -template -auto async(launch policy, F&& f) -> boost::unique_future -{ - typedef decltype(f()) result_type; - - if((policy & launch::async) != 0) - { - typedef boost::packaged_task task_t; - - auto task = task_t(std::forward(f)); - auto future = task.get_future(); - - boost::thread(std::move(task)).detach(); - - return std::move(future); - } - else if((policy & launch::deferred) != 0) - { - // HACK: THIS IS A MAYOR HACK! - - typedef boost::detail::future_object future_object_t; - - auto callback_object = boost::make_shared>(std::forward(f)); - auto callback_object_raw = callback_object.get(); - auto future_object = boost::static_pointer_cast(std::move(callback_object)); - - int dummy = 0; - future_object->set_wait_callback(std::function([callback_object_raw](int) mutable - { - (*callback_object_raw)(); - }), &dummy); - - boost::unique_future future; - - static_assert(sizeof(future) == sizeof(future_object), ""); - - reinterpret_cast&>(future) = std::move(future_object); // Get around the "private" encapsulation. - return std::move(future); - } - else - throw std::invalid_argument("policy"); -} - -template -auto async(F&& f) -> boost::unique_future -{ - return async(launch::async, std::forward(f)); -} - -template -auto make_shared(boost::unique_future&& f) -> boost::shared_future -{ - return boost::shared_future(std::move(f)); -} - -template -auto flatten(boost::unique_future&& f) -> boost::unique_future -{ - auto shared_f = make_shared(std::move(f)); - return async(launch::deferred, [=]() mutable - { - return shared_f.get().get(); - }); -} - +#pragma once + +#include +#include +#include + +#include +#include + +namespace caspar { + +template +auto flatten(std::future&& f) -> std::future::type> +{ + auto shared_f = f.share(); + return std::async(std::launch::deferred, [=]() mutable -> typename std::decay::type + { + return shared_f.get().get(); + }); +} + +template +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. + *

+ * 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 +std::future make_ready_future(R&& value) +{ + std::promise p; + + p.set_value(value); + + return p.get_future(); +} + +static std::future make_ready_future() +{ + std::promise p; + + p.set_value(); + + return p.get_future(); +} + } \ No newline at end of file