]> git.sesse.net Git - casparcg/blob - common/concurrency/com_context.h
31ab5a1623b8845dc37a937aca256d6384b7865e
[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 \r
7 #define NOMINMAX\r
8 #define WIN32_LEAN_AND_MEAN\r
9 \r
10 #include <Windows.h>\r
11 \r
12 #include <boost/noncopyable.hpp>\r
13 #include <boost/thread/future.hpp>\r
14 \r
15 #include <functional>\r
16 \r
17 namespace caspar {\r
18 \r
19 template<typename T>\r
20 class com_context : public executor\r
21 {\r
22         std::unique_ptr<T> instance_;\r
23 public:\r
24         com_context(const std::wstring& name) : executor(name)\r
25         {\r
26                 executor::begin_invoke([]\r
27                 {\r
28                         ::CoInitialize(nullptr);\r
29                 });\r
30         }\r
31 \r
32         ~com_context()\r
33         {\r
34                 if(!executor::begin_invoke([&]\r
35                 {\r
36                         instance_.reset(nullptr);\r
37                         ::CoUninitialize();\r
38                 }).timed_wait(boost::posix_time::milliseconds(500)))\r
39                 {\r
40                         CASPAR_LOG(error) << L"[com_contex] Timer expired, deadlock detected and released, leaking resources";\r
41                 }\r
42         }\r
43         \r
44         void reset(const std::function<T*()>& factory = nullptr)\r
45         {\r
46                 executor::invoke([&]\r
47                 {\r
48                         instance_.reset();\r
49                         if(factory)\r
50                                 instance_.reset(factory());\r
51                 });\r
52         }\r
53 \r
54         T& operator*() const { return *instance_.get();}  // noexcept\r
55 \r
56         T* operator->() const { return instance_.get();}  // noexcept\r
57 \r
58         T* get() const { return instance_.get();}  // noexcept\r
59 \r
60         operator bool() const {return get() != nullptr;}\r
61 };\r
62 \r
63 }