if(layers.empty())\r
{ // Bypass GPU with empty frame.\r
auto buffer = spl::make_shared<const std::vector<uint8_t, tbb::cache_aligned_allocator<uint8_t>>>(format_desc.size, 0);\r
- return async(launch_policy::deferred, [=]\r
+ return async(launch::deferred, [=]\r
{\r
return core::const_array(buffer->data(), static_cast<std::size_t>(format_desc.size), buffer);\r
});\r
} \r
\r
- return fold(ogl_->begin_invoke([=]() mutable -> boost::shared_future<core::const_array>\r
+ return flatten(ogl_->begin_invoke([=]() mutable -> boost::shared_future<core::const_array>\r
{\r
auto draw_buffer = create_mixer_buffer(format_desc.width, format_desc.height, 4);\r
\r
\r
boost::unique_future<core::const_array> copy_async(const spl::shared_ptr<texture>& source)\r
{\r
- return fold(render_executor_.begin_invoke([=]() -> boost::shared_future<core::const_array>\r
+ return flatten(render_executor_.begin_invoke([=]() -> boost::shared_future<core::const_array>\r
{\r
auto buffer = create_buffer(source->size(), buffer::usage::read_only); \r
source->copy_to(*buffer); \r
\r
- return make_shared(async(launch_policy::deferred, [=]() mutable -> core::const_array\r
+ return make_shared(async(launch::deferred, [=]() mutable -> core::const_array\r
{\r
const auto& buf = buffer.get();\r
if(!buf->data())\r
deferred\r
};\r
};\r
-typedef enum_class<launch_policy_def> launch_policy;\r
+typedef enum_class<launch_policy_def> launch;\r
\r
namespace detail {\r
\r
}\r
\r
template<typename F>\r
-auto async(launch_policy lp, F&& f) -> boost::unique_future<decltype(f())>\r
+auto async(launch lp, F&& f) -> boost::unique_future<decltype(f())>\r
{ \r
typedef decltype(f()) result_type;\r
+ \r
+ typedef boost::promise<result_type> promise_t;\r
\r
- if(lp == launch_policy::deferred)\r
- {\r
- typedef boost::promise<result_type> promise_t;\r
+ // WORKAROUND: Use heap storage since lambdas don't support move semantics and do a lot of unnecessary copies.\r
+ auto promise = new promise_t();\r
+ auto func = new F(std::forward<F>(f));\r
+ auto future = promise->get_future();\r
\r
- auto promise = new promise_t();\r
- auto future = promise->get_future();\r
- \r
+ if(lp == launch::deferred)\r
+ { \r
promise->set_wait_callback(std::function<void(promise_t&)>([=](promise_t&) mutable\r
{\r
std::unique_ptr<promise_t> pointer_guard(promise);\r
- detail::invoke_function<result_type>()(*promise, f);\r
+ std::unique_ptr<F> func_guard(func);\r
+ detail::invoke_function<result_type>()(*promise, *func);\r
}));\r
\r
return std::move(future);\r
}\r
else\r
{\r
- typedef boost::packaged_task<result_type> packaged_task_t;\r
-\r
- auto task = packaged_task_t(f); \r
- auto future = task.get_future();\r
-\r
- boost::thread(std::move(task)).detach();\r
+ boost::thread([=]\r
+ {\r
+ std::unique_ptr<promise_t> pointer_guard(promise);\r
+ std::unique_ptr<F> func_guard(func);\r
+\r
+ try\r
+ { \r
+ detail::invoke_function<result_type>()(*promise, *func);\r
+ }\r
+ catch(...)\r
+ {\r
+ promise->set_exception(boost::current_exception());\r
+ }\r
+ }).detach();\r
\r
return std::move(future);\r
}\r
template<typename F>\r
auto async(F&& f) -> boost::unique_future<decltype(f())>\r
{ \r
- return async(launch_policy::async, std::forward<F>(f));\r
+ return async(launch::async, std::forward<F>(f));\r
}\r
\r
template<typename T>\r
}\r
\r
template<typename T>\r
-auto fold(boost::unique_future<T>&& f) -> boost::unique_future<decltype(f.get().get())>\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_policy::deferred, [=]() mutable\r
+ return async(launch::deferred, [=]() mutable\r
{\r
return shared_f.get().get();\r
});\r
s->execute = thread_execute;\r
s->execute2 = thread_execute2;\r
s->thread_count = MAX_THREADS; // We are using a task-scheduler, so use as many "threads/tasks" as possible. \r
-\r
- CASPAR_LOG(info) << "Initialized ffmpeg tbb context.";\r
}\r
\r
void thread_free(AVCodecContext* s)\r
return;\r
\r
s->thread_opaque = nullptr;\r
- \r
- CASPAR_LOG(info) << "Released ffmpeg tbb context.";\r
}\r
\r
int tbb_avcodec_open(AVCodecContext* avctx, AVCodec* codec)\r