blob: 61b3e332f403193b1a3ee2b9ad4511a8e2c5e48e [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
xians@webrtc.org6bde7a82012-02-20 08:39:25 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "process_thread_impl.h"
12#include "module.h"
13#include "trace.h"
14
15namespace webrtc {
16ProcessThread::~ProcessThread()
17{
18}
19
20ProcessThread* ProcessThread::CreateProcessThread()
21{
niklase@google.com470e71d2011-07-07 08:21:25 +000022 return new ProcessThreadImpl();
23}
24
25void ProcessThread::DestroyProcessThread(ProcessThread* module)
26{
niklase@google.com470e71d2011-07-07 08:21:25 +000027 delete module;
28}
29
30ProcessThreadImpl::ProcessThreadImpl()
31 : _timeEvent(*EventWrapper::Create()),
henrike@webrtc.org105e0712011-12-16 19:53:46 +000032 _critSectModules(CriticalSectionWrapper::CreateCriticalSection()),
niklase@google.com470e71d2011-07-07 08:21:25 +000033 _thread(NULL)
34{
35 WEBRTC_TRACE(kTraceMemory, kTraceUtility, -1, "%s created", __FUNCTION__);
36}
37
38ProcessThreadImpl::~ProcessThreadImpl()
39{
henrike@webrtc.org105e0712011-12-16 19:53:46 +000040 delete _critSectModules;
niklase@google.com470e71d2011-07-07 08:21:25 +000041 delete &_timeEvent;
42 WEBRTC_TRACE(kTraceMemory, kTraceUtility, -1, "%s deleted", __FUNCTION__);
43}
44
pbos@webrtc.orgc75102e2013-04-09 13:32:55 +000045int32_t ProcessThreadImpl::Start()
niklase@google.com470e71d2011-07-07 08:21:25 +000046{
47 CriticalSectionScoped lock(_critSectModules);
48 if(_thread)
49 {
50 return -1;
51 }
52 _thread = ThreadWrapper::CreateThread(Run, this, kNormalPriority,
53 "ProcessThread");
54 unsigned int id;
pbos@webrtc.orgc75102e2013-04-09 13:32:55 +000055 int32_t retVal = _thread->Start(id);
niklase@google.com470e71d2011-07-07 08:21:25 +000056 if(retVal >= 0)
57 {
58 return 0;
59 }
60 delete _thread;
61 _thread = NULL;
62 return -1;
63}
64
pbos@webrtc.orgc75102e2013-04-09 13:32:55 +000065int32_t ProcessThreadImpl::Stop()
niklase@google.com470e71d2011-07-07 08:21:25 +000066{
henrike@webrtc.org105e0712011-12-16 19:53:46 +000067 _critSectModules->Enter();
niklase@google.com470e71d2011-07-07 08:21:25 +000068 if(_thread)
69 {
70 _thread->SetNotAlive();
71
72 ThreadWrapper* thread = _thread;
73 _thread = NULL;
74
75 _timeEvent.Set();
henrike@webrtc.org105e0712011-12-16 19:53:46 +000076 _critSectModules->Leave();
niklase@google.com470e71d2011-07-07 08:21:25 +000077
78 if(thread->Stop())
79 {
80 delete thread;
81 } else {
82 return -1;
83 }
84 } else {
henrike@webrtc.org105e0712011-12-16 19:53:46 +000085 _critSectModules->Leave();
niklase@google.com470e71d2011-07-07 08:21:25 +000086 }
87 return 0;
88}
89
pbos@webrtc.orgc75102e2013-04-09 13:32:55 +000090int32_t ProcessThreadImpl::RegisterModule(const Module* module)
niklase@google.com470e71d2011-07-07 08:21:25 +000091{
niklase@google.com470e71d2011-07-07 08:21:25 +000092 CriticalSectionScoped lock(_critSectModules);
93
94 // Only allow module to be registered once.
95 ListItem* item = _modules.First();
pbos@webrtc.orgc75102e2013-04-09 13:32:55 +000096 for(uint32_t i = 0; i < _modules.GetSize() && item; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +000097 {
98 if(module == item->GetItem())
99 {
100 return -1;
101 }
102 item = _modules.Next(item);
103 }
104
105 _modules.PushFront(module);
106 WEBRTC_TRACE(kTraceInfo, kTraceUtility, -1,
107 "number of registered modules has increased to %d",
108 _modules.GetSize());
109 // Wake the thread calling ProcessThreadImpl::Process() to update the
110 // waiting time. The waiting time for the just registered module may be
111 // shorter than all other registered modules.
112 _timeEvent.Set();
113 return 0;
114}
115
pbos@webrtc.orgc75102e2013-04-09 13:32:55 +0000116int32_t ProcessThreadImpl::DeRegisterModule(const Module* module)
niklase@google.com470e71d2011-07-07 08:21:25 +0000117{
niklase@google.com470e71d2011-07-07 08:21:25 +0000118 CriticalSectionScoped lock(_critSectModules);
119
120 ListItem* item = _modules.First();
pbos@webrtc.orgc75102e2013-04-09 13:32:55 +0000121 for(uint32_t i = 0; i < _modules.GetSize() && item; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000122 {
123 if(module == item->GetItem())
124 {
125 int res = _modules.Erase(item);
126 WEBRTC_TRACE(kTraceInfo, kTraceUtility, -1,
127 "number of registered modules has decreased to %d",
128 _modules.GetSize());
129 return res;
130 }
131 item = _modules.Next(item);
132 }
133 return -1;
134}
135
136bool ProcessThreadImpl::Run(void* obj)
137{
138 return static_cast<ProcessThreadImpl*>(obj)->Process();
139}
140
141bool ProcessThreadImpl::Process()
142{
143 // Wait for the module that should be called next, but don't block thread
144 // longer than 100 ms.
pbos@webrtc.orgc75102e2013-04-09 13:32:55 +0000145 int32_t minTimeToNext = 100;
niklase@google.com470e71d2011-07-07 08:21:25 +0000146 {
147 CriticalSectionScoped lock(_critSectModules);
148 ListItem* item = _modules.First();
pbos@webrtc.orgc75102e2013-04-09 13:32:55 +0000149 for(uint32_t i = 0; i < _modules.GetSize() && item; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000150 {
pbos@webrtc.orgc75102e2013-04-09 13:32:55 +0000151 int32_t timeToNext =
niklase@google.com470e71d2011-07-07 08:21:25 +0000152 static_cast<Module*>(item->GetItem())->TimeUntilNextProcess();
153 if(minTimeToNext > timeToNext)
154 {
155 minTimeToNext = timeToNext;
156 }
157 item = _modules.Next(item);
158 }
159 }
160
161 if(minTimeToNext > 0)
162 {
163 if(kEventError == _timeEvent.Wait(minTimeToNext))
164 {
165 return true;
166 }
henrika@webrtc.org4ff956f2013-04-02 11:59:11 +0000167 CriticalSectionScoped lock(_critSectModules);
niklase@google.com470e71d2011-07-07 08:21:25 +0000168 if(!_thread)
169 {
170 return false;
171 }
172 }
173 {
174 CriticalSectionScoped lock(_critSectModules);
175 ListItem* item = _modules.First();
pbos@webrtc.orgc75102e2013-04-09 13:32:55 +0000176 for(uint32_t i = 0; i < _modules.GetSize() && item; i++)
niklase@google.com470e71d2011-07-07 08:21:25 +0000177 {
pbos@webrtc.orgc75102e2013-04-09 13:32:55 +0000178 int32_t timeToNext =
niklase@google.com470e71d2011-07-07 08:21:25 +0000179 static_cast<Module*>(item->GetItem())->TimeUntilNextProcess();
180 if(timeToNext < 1)
181 {
182 static_cast<Module*>(item->GetItem())->Process();
183 }
184 item = _modules.Next(item);
185 }
186 }
187 return true;
188}
189} // namespace webrtc