]> git.sesse.net Git - casparcg/blob - server/utils/CommandQueue.h
Fixed a problem related to character encoding that prevented the PK project from...
[casparcg] / server / utils / CommandQueue.h
1 /*\r
2 * copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
3 *\r
4 *  This file is part of CasparCG.\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 */\r
20  \r
21 #ifndef _COMMANDQUEUE_H__\r
22 #define _COMMANDQUEUE_H__\r
23 \r
24 #pragma once\r
25 \r
26 #include <list>\r
27 #include "thread.h"\r
28 #include "Lockable.h"\r
29 \r
30 namespace caspar {\r
31 namespace utils {\r
32 \r
33 //TODO: Add idle-processing. preferably as a functor suplied at construction-time\r
34 \r
35 //CommandQueue is a \r
36 template<typename T>\r
37 class CommandQueue\r
38 {\r
39         template<typename U>\r
40         class WorkerThread : public utils::IRunnable, private utils::LockableObject\r
41         {\r
42         public:\r
43                 WorkerThread() : commandAvailibleEvent_(TRUE, FALSE)\r
44                 {}\r
45 \r
46                 void AddCommand(U pCommand);\r
47                 virtual void Run(HANDLE stopEvent);\r
48                 virtual bool OnUnhandledException(const std::exception& ex) throw();\r
49 \r
50         private:\r
51                 utils::Event    commandAvailibleEvent_;\r
52 \r
53                 //Needs synro-protection\r
54                 std::list<U> commands_;\r
55         };\r
56 \r
57         CommandQueue(const CommandQueue&);\r
58         CommandQueue& operator=(const CommandQueue&);\r
59 public:\r
60         CommandQueue() : pWorker_(new WorkerThread<T>())\r
61         {}\r
62         ~CommandQueue() \r
63         {}\r
64 \r
65         bool Start();\r
66         void Stop();\r
67         void AddCommand(T pCommand);\r
68 \r
69 private:\r
70         utils::Thread   commandPump_;\r
71         std::tr1::shared_ptr<WorkerThread<T> > pWorker_;\r
72 \r
73 };\r
74 \r
75 template<typename T>\r
76 bool CommandQueue<T>::Start() {\r
77         return commandPump_.Start(pWorker_.get());\r
78 }\r
79 \r
80 template<typename T>\r
81 void CommandQueue<T>::Stop() {\r
82         commandPump_.Stop();\r
83 }\r
84 \r
85 template<typename T>\r
86 void CommandQueue<T>::AddCommand(T pCommand) {\r
87         pWorker_->AddCommand(pCommand);\r
88 }\r
89 \r
90 template<typename T>\r
91 template<typename U>\r
92 void CommandQueue<T>::WorkerThread<U>::AddCommand(U pCommand) {\r
93         Lock lock(*this);\r
94 \r
95         commands_.push_back(pCommand);\r
96         commandAvailibleEvent_.Set();\r
97 }\r
98 \r
99 template<typename T>\r
100 template<typename U>\r
101 void CommandQueue<T>::WorkerThread<U>::Run(HANDLE stopEvent)\r
102 {\r
103         HANDLE events[2] = {commandAvailibleEvent_, stopEvent};\r
104         U pCommand;\r
105 \r
106         while(true) {\r
107                 DWORD waitResult = WaitForMultipleObjects(2, events, FALSE, 1000);\r
108                 int result = waitResult - WAIT_OBJECT_0;\r
109 \r
110                 if(result == 1) {\r
111                         break;\r
112                 }\r
113                 else if(result == 0) {\r
114                         Lock lock(*this);\r
115 \r
116                         if(commands_.size() > 0) {\r
117                                 pCommand = commands_.front();\r
118                                 commands_.pop_front();\r
119 \r
120                                 if(commands_.size() == 0)\r
121                                         commandAvailibleEvent_.Reset();\r
122                         }\r
123                 }\r
124 \r
125                 if(pCommand != 0) {\r
126                         pCommand->Execute();\r
127                         pCommand.reset();\r
128                 }\r
129         }\r
130 }\r
131 \r
132 template<typename T>\r
133 template<typename U>\r
134 bool CommandQueue<T>::WorkerThread<U>::OnUnhandledException(const std::exception& ex) throw() {\r
135         bool bDoRestart = true;\r
136 \r
137         try \r
138         {\r
139                 LOG << LogLevel::Critical << TEXT("UNHANDLED EXCEPTION in commandqueue. Message: ") << ex.what() << LogStream::Flush;\r
140         }\r
141         catch(...)\r
142         {\r
143                 bDoRestart = false;\r
144         }\r
145 \r
146         return bDoRestart;\r
147 }\r
148 \r
149 }       //namespace utils\r
150 }       //namespace caspar\r
151 \r
152 #endif  //_COMMANDQUEUE_H__