]> git.sesse.net Git - casparcg/commitdiff
Reverted changes from previous commit.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Tue, 27 Dec 2011 10:25:40 +0000 (10:25 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Tue, 27 Dec 2011 10:25:40 +0000 (10:25 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/trunk@1953 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

common/common.vcxproj
common/common.vcxproj.filters
common/concurrency/com_context.h [new file with mode: 0644]
modules/decklink/consumer/decklink_consumer.cpp

index a99f1b15f05c68647497bbb979a2bcf1783b8755..f889ce3340f767e0a16fbc61327b034524073fec 100644 (file)
   </ItemDefinitionGroup>\r
   <ItemGroup>\r
     <ClInclude Include="compiler\vs\disable_silly_warnings.h" />\r
+    <ClInclude Include="concurrency\com_context.h" />\r
     <ClInclude Include="concurrency\executor.h" />\r
     <ClInclude Include="concurrency\lock.h" />\r
     <ClInclude Include="concurrency\target.h" />\r
index d11a18be9bb13b6165095fcf83056e8f9967fdca..1a5155289638e6d63b996aef99d026c4124e8e02 100644 (file)
     <ClInclude Include="os\windows\system_info.h">\r
       <Filter>source\os\windows</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="concurrency\com_context.h">\r
+      <Filter>source\concurrency</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="memory\memshfl.h">\r
       <Filter>source\memory</Filter>\r
     </ClInclude>\r
diff --git a/common/concurrency/com_context.h b/common/concurrency/com_context.h
new file mode 100644 (file)
index 0000000..509c0af
--- /dev/null
@@ -0,0 +1,99 @@
+/*\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
index bddcf909850bdbe5678e184ae0b00be654cefedb..04b9f194cf557fcec2b29888ea5261b86f80aca5 100644 (file)
@@ -29,8 +29,7 @@
 \r
 #include <core/mixer/read_frame.h>\r
 \r
-#include <common/concurrency/executor.h>\r
-#include <common/concurrency/lock.h>\r
+#include <common/concurrency/com_context.h>\r
 #include <common/diagnostics/graph.h>\r
 #include <common/exception/exceptions.h>\r
 #include <common/memory/memcpy.h>\r
@@ -355,10 +354,8 @@ public:
                }\r
                catch(...)\r
                {\r
-                       lock(exception_mutex_, [this]\r
-                       {\r
-                               exception_ = std::current_exception();\r
-                       });\r
+                       tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
+                       exception_ = std::current_exception();\r
                        return E_FAIL;\r
                }\r
 \r
@@ -395,10 +392,8 @@ public:
                }\r
                catch(...)\r
                {\r
-                       lock(exception_mutex_, [this]\r
-                       {\r
-                               exception_ = std::current_exception();\r
-                       });\r
+                       tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
+                       exception_ = std::current_exception();\r
                        return E_FAIL;\r
                }\r
 \r
@@ -432,14 +427,12 @@ public:
 \r
        void send(const safe_ptr<core::read_frame>& frame)\r
        {\r
-               auto exception = lock(exception_mutex_, [this]\r
                {\r
-                       return exception_;\r
-               });\r
+                       tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
+                       if(exception_ != nullptr)\r
+                               std::rethrow_exception(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
@@ -457,51 +450,35 @@ public:
 \r
 struct decklink_consumer_proxy : public core::frame_consumer\r
 {\r
-       const configuration                                     config_;\r
-       std::unique_ptr<decklink_consumer>      consumer_;\r
-       std::vector<size_t>                                     audio_cadence_;\r
-       executor                                                        executor_;\r
+       const configuration                             config_;\r
+       com_context<decklink_consumer>  context_;\r
+       std::vector<size_t>                             audio_cadence_;\r
 public:\r
 \r
        decklink_consumer_proxy(const configuration& config)\r
                : config_(config)\r
-               , executor_(L"decklink_consumer[" + boost::lexical_cast<std::wstring>(config.device_index) + L"]")\r
+               , context_(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
-               executor_.invoke([=]\r
+               if(context_)\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
+                       auto str = print();\r
+                       context_.reset();\r
+                       CASPAR_LOG(info) << str << L" Successfully Uninitialized.";     \r
+               }\r
        }\r
 \r
        // frame_consumer\r
        \r
        virtual void initialize(const core::video_format_desc& format_desc, int channel_index) override\r
        {\r
-               executor_.invoke([=]\r
-               {\r
-                       consumer_.reset(new decklink_consumer(config_, format_desc, channel_index));            \r
-                       audio_cadence_ = format_desc.audio_cadence;             \r
+               context_.reset([&]{return 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
-               });\r
+               CASPAR_LOG(info) << print() << L" Successfully Initialized.";   \r
        }\r
        \r
        virtual bool send(const safe_ptr<core::read_frame>& frame) override\r
@@ -509,13 +486,13 @@ public:
                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
-               consumer_->send(frame);\r
+               context_->send(frame);\r
                return true;\r
        }\r
        \r
        virtual std::wstring print() const override\r
        {\r
-               return consumer_ ? consumer_->print() : L"[decklink_consumer]";\r
+               return context_ ? context_->print() : L"[decklink_consumer]";\r
        }               \r
 \r
        virtual boost::property_tree::wptree info() const override\r