]> git.sesse.net Git - casparcg/blob - protocol/util/Thread.cpp
* Created custom decklink allocator for reducing memory footprint.
[casparcg] / protocol / util / Thread.cpp
1 /*\r
2 * Copyright 2013 Sveriges Television AB http://casparcg.com/\r
3 *\r
4 * This file is part of CasparCG (www.casparcg.com).\r
5 *\r
6 * CasparCG is free software: you can redistribute it and/or modify\r
7 * it under the terms of the GNU General Public License as published by\r
8 * the Free Software Foundation, either version 3 of the License, or\r
9 * (at your option) any later version.\r
10 *\r
11 * CasparCG is distributed in the hope that it will be useful,\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14 * GNU General Public License for more details.\r
15 *\r
16 * You should have received a copy of the GNU General Public License\r
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
18 *\r
19 * Author: Nicklas P Andersson\r
20 */\r
21 \r
22 #include "../StdAfx.h"\r
23 \r
24 #include "thread.h"\r
25 #include <common/exception/win32_exception.h>\r
26 \r
27 namespace caspar {\r
28         \r
29 Event::Event(bool bManualReset, bool bInitialState) : handle_(0)\r
30 {\r
31         handle_ = CreateEvent(0, bManualReset, bInitialState, 0);\r
32         if(handle_ == 0) {\r
33                 throw std::exception("Failed to create event");\r
34         }\r
35 }\r
36 \r
37 void Event::Set() {\r
38         SetEvent(handle_);\r
39         // TODO: huh?\r
40         //BOOL res = SetEvent(handle_);\r
41         //if(res == FALSE) {\r
42         //      DWORD error = GetLastError();\r
43         //}\r
44 }\r
45 void Event::Reset() {\r
46         ResetEvent(handle_);\r
47 }\r
48 \r
49 Event::~Event()\r
50 {\r
51         CloseHandle(handle_);\r
52 }\r
53 \r
54 Thread::Thread() : pRunnable_(0), hThread_(0), stopEvent_(TRUE, FALSE), timeout_(10000)  {\r
55 }\r
56 \r
57 Thread::~Thread() {\r
58         Stop();\r
59 }\r
60 \r
61 bool Thread::IsRunning() {\r
62         if(hThread_ != 0) {\r
63                 if(WaitForSingleObject(hThread_, 0) == WAIT_OBJECT_0) {\r
64                         CloseHandle(hThread_);\r
65                         hThread_ = 0;\r
66                         pRunnable_ = 0;\r
67                 }\r
68         }\r
69 \r
70         return (hThread_ != 0);\r
71 }\r
72 \r
73 bool Thread::Start(IRunnable* pRunnable) {\r
74         if(hThread_ == 0) {\r
75                 if(pRunnable != 0) {\r
76                         pRunnable_ = pRunnable;\r
77                         stopEvent_.Reset();\r
78                         hThread_ = CreateThread(0, 0, ThreadEntrypoint, this, 0, 0);\r
79 \r
80                         if(hThread_ == 0)\r
81                                 pRunnable_ = 0;\r
82 \r
83                         return (hThread_ != 0);\r
84                 }\r
85         }\r
86         return false;\r
87 }\r
88 \r
89 bool Thread::Stop(bool bWait) {\r
90         bool returnValue = true;\r
91 \r
92         if(hThread_ != 0) {\r
93                 stopEvent_.Set();\r
94 \r
95                 if(bWait) {\r
96                         DWORD successCode = WaitForSingleObject(hThread_, timeout_);\r
97                         if(successCode != WAIT_OBJECT_0)\r
98                                 returnValue = false;\r
99                 }\r
100                 CloseHandle(hThread_);\r
101 \r
102                 hThread_ = 0;\r
103                 pRunnable_ = 0;\r
104         }\r
105 \r
106         return returnValue;\r
107 }\r
108 \r
109 DWORD WINAPI Thread::ThreadEntrypoint(LPVOID pParam) {\r
110         Thread* pThis = reinterpret_cast<Thread*>(pParam);\r
111         \r
112         win32_exception::install_handler();\r
113 \r
114         _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);\r
115 \r
116         pThis->Run();\r
117 \r
118         return 0;\r
119 }\r
120 \r
121 void Thread::Run() {\r
122         bool bDoRestart = false;\r
123 \r
124         do {\r
125                 try {\r
126                         bDoRestart = false;\r
127                         stopEvent_.Reset();\r
128                         pRunnable_->Run(stopEvent_);\r
129                 }\r
130                 catch(const std::exception& e) {\r
131                         bDoRestart = pRunnable_->OnUnhandledException(e);\r
132                 }\r
133         }while(bDoRestart);\r
134 }\r
135 \r
136 }       //namespace caspar