+++ /dev/null
-/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG (www.casparcg.com).\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-* Author: Robert Nagy, ronag89@gmail.com\r
-*/\r
-\r
-#pragma once\r
-\r
-#include "executor.h"\r
-\r
-#include "../log/log.h"\r
-#include "../exception/exceptions.h"\r
-\r
-#define NOMINMAX\r
-#define WIN32_LEAN_AND_MEAN\r
-\r
-#include <Windows.h>\r
-\r
-#include <boost/noncopyable.hpp>\r
-#include <boost/thread/future.hpp>\r
-\r
-#include <functional>\r
-\r
-namespace caspar {\r
-\r
-template<typename T>\r
-class com_context : public executor\r
-{\r
- std::unique_ptr<T> instance_;\r
-public:\r
- com_context(const std::wstring& name) : executor(name)\r
- {\r
- executor::begin_invoke([]\r
- {\r
- ::CoInitialize(nullptr);\r
- });\r
- }\r
-\r
- ~com_context()\r
- {\r
- if(!executor::begin_invoke([&]\r
- {\r
- instance_.reset(nullptr);\r
- ::CoUninitialize();\r
- }).timed_wait(boost::posix_time::milliseconds(500)))\r
- {\r
- CASPAR_LOG(error) << L"[com_contex] Timer expired, deadlock detected and released, leaking resources.";\r
- }\r
- }\r
- \r
- void reset(const std::function<T*()>& factory = nullptr)\r
- {\r
- executor::invoke([&]\r
- {\r
- instance_.reset();\r
- if(factory)\r
- instance_.reset(factory());\r
- });\r
- }\r
-\r
- T& operator*() const \r
- {\r
- if(instance_ == nullptr)\r
- BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Tried to access null context."));\r
-\r
- return *instance_.get();\r
- } // noexcept\r
-\r
- T* operator->() const \r
- {\r
- if(instance_ == nullptr)\r
- BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Tried to access null context."));\r
- return instance_.get();\r
- } // noexcept\r
-\r
- T* get() const\r
- {\r
- return instance_.get();\r
- } // noexcept\r
-\r
- operator bool() const {return get() != nullptr;}\r
-};\r
-\r
-}
\ No newline at end of file
\r
#include <core/mixer/read_frame.h>\r
\r
-#include <common/concurrency/com_context.h>\r
+#include <common/concurrency/executor.h>\r
+#include <common/concurrency/lock.h>\r
#include <common/diagnostics/graph.h>\r
#include <common/exception/exceptions.h>\r
#include <common/memory/memcpy.h>\r
}\r
catch(...)\r
{\r
- tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
- exception_ = std::current_exception();\r
+ lock(exception_mutex_, [this]\r
+ {\r
+ exception_ = std::current_exception();\r
+ });\r
return E_FAIL;\r
}\r
\r
}\r
catch(...)\r
{\r
- tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
- exception_ = std::current_exception();\r
+ lock(exception_mutex_, [this]\r
+ {\r
+ exception_ = std::current_exception();\r
+ });\r
return E_FAIL;\r
}\r
\r
\r
void send(const safe_ptr<core::read_frame>& frame)\r
{\r
+ auto exception = lock(exception_mutex_, [this]\r
{\r
- tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
- if(exception_ != nullptr)\r
- std::rethrow_exception(exception_);\r
- }\r
+ return exception_;\r
+ });\r
\r
+ if(exception != nullptr)\r
+ std::rethrow_exception(exception);\r
+ \r
if(!is_running_)\r
BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Is not running."));\r
\r
\r
struct decklink_consumer_proxy : public core::frame_consumer\r
{\r
- const configuration config_;\r
- com_context<decklink_consumer> context_;\r
- std::vector<size_t> audio_cadence_;\r
+ const configuration config_;\r
+ std::unique_ptr<decklink_consumer> consumer_;\r
+ std::vector<size_t> audio_cadence_;\r
+ executor executor_;\r
public:\r
\r
decklink_consumer_proxy(const configuration& config)\r
: config_(config)\r
- , context_(L"decklink_consumer[" + boost::lexical_cast<std::wstring>(config.device_index) + L"]")\r
+ , executor_(L"decklink_consumer[" + boost::lexical_cast<std::wstring>(config.device_index) + L"]")\r
{\r
+ executor_.begin_invoke([=]\r
+ {\r
+ ::CoInitialize(nullptr);\r
+ });\r
}\r
\r
~decklink_consumer_proxy()\r
{\r
- if(context_)\r
+ executor_.invoke([=]\r
{\r
- auto str = print();\r
- context_.reset();\r
- CASPAR_LOG(info) << str << L" Successfully Uninitialized."; \r
- }\r
+ if(consumer_)\r
+ {\r
+ auto str = print();\r
+ consumer_.reset();\r
+ CASPAR_LOG(info) << str << L" Successfully Uninitialized."; \r
+ }\r
+ });\r
+ \r
+ executor_.invoke([=]\r
+ {\r
+ ::CoUninitialize();\r
+ });\r
}\r
\r
// frame_consumer\r
\r
virtual void initialize(const core::video_format_desc& format_desc, int channel_index) override\r
{\r
- context_.reset([&]{return new decklink_consumer(config_, format_desc, channel_index);}); \r
- audio_cadence_ = format_desc.audio_cadence; \r
+ executor_.invoke([=]\r
+ {\r
+ consumer_.reset(new decklink_consumer(config_, format_desc, channel_index)); \r
+ audio_cadence_ = format_desc.audio_cadence; \r
\r
- CASPAR_LOG(info) << print() << L" Successfully Initialized."; \r
+ CASPAR_LOG(info) << print() << L" Successfully Initialized.";\r
+ });\r
}\r
\r
virtual bool send(const safe_ptr<core::read_frame>& frame) override\r
CASPAR_VERIFY(audio_cadence_.front() == static_cast<size_t>(frame->audio_data().size()));\r
boost::range::rotate(audio_cadence_, std::begin(audio_cadence_)+1);\r
\r
- context_->send(frame);\r
+ consumer_->send(frame);\r
return true;\r
}\r
\r
virtual std::wstring print() const override\r
{\r
- return context_ ? context_->print() : L"[decklink_consumer]";\r
+ return consumer_ ? consumer_->print() : L"[decklink_consumer]";\r
} \r
\r
virtual boost::property_tree::wptree info() const override\r