]> git.sesse.net Git - casparcg/blob - common/concurrency/com_context.h
2.0. stage: Changed error handling.
[casparcg] / common / concurrency / com_context.h
1 #pragma once\r
2 \r
3 #include "executor.h"\r
4 \r
5 #include "../log/log.h"\r
6 #include "../exception/exceptions.h"\r
7 \r
8 #define NOMINMAX\r
9 #define WIN32_LEAN_AND_MEAN\r
10 \r
11 #include <Windows.h>\r
12 \r
13 #include <boost/noncopyable.hpp>\r
14 #include <boost/thread/future.hpp>\r
15 \r
16 #include <functional>\r
17 \r
18 namespace caspar {\r
19 \r
20 template<typename T>\r
21 class com_context : public executor\r
22 {\r
23         std::unique_ptr<T> instance_;\r
24 public:\r
25         com_context(const std::wstring& name) : executor(name)\r
26         {\r
27                 executor::begin_invoke([]\r
28                 {\r
29                         ::CoInitialize(nullptr);\r
30                 });\r
31         }\r
32 \r
33         ~com_context()\r
34         {\r
35                 if(!executor::begin_invoke([&]\r
36                 {\r
37                         instance_.reset(nullptr);\r
38                         ::CoUninitialize();\r
39                 }).timed_wait(boost::posix_time::milliseconds(500)))\r
40                 {\r
41                         CASPAR_LOG(error) << L"[com_contex] Timer expired, deadlock detected and released, leaking resources.";\r
42                 }\r
43         }\r
44         \r
45         void reset(const std::function<T*()>& factory = nullptr)\r
46         {\r
47                 executor::invoke([&]\r
48                 {\r
49                         instance_.reset();\r
50                         if(factory)\r
51                                 instance_.reset(factory());\r
52                 });\r
53         }\r
54 \r
55         T& operator*() const \r
56         {\r
57                 if(instance_ == nullptr)\r
58                         BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Tried to access null context."));\r
59 \r
60                 return *instance_.get();\r
61         }  // noexcept\r
62 \r
63         T* operator->() const \r
64         {\r
65                 if(instance_ == nullptr)\r
66                         BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Tried to access null context."));\r
67                 return instance_.get();\r
68         }  // noexcept\r
69 \r
70         T* get() const\r
71         {\r
72                 return instance_.get();\r
73         }  // noexcept\r
74 \r
75         operator bool() const {return get() != nullptr;}\r
76 };\r
77 \r
78 }