1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 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 "webrtc/modules/interface/module.h" 12 #include "webrtc/modules/utility/source/process_thread_impl.h" 13 14 15 namespace webrtc { 16 ProcessThread::~ProcessThread() 17 { 18 } 19 20 ProcessThread* ProcessThread::CreateProcessThread() 21 { 22 return new ProcessThreadImpl(); 23 } 24 25 void ProcessThread::DestroyProcessThread(ProcessThread* module) 26 { 27 delete module; 28 } 29 30 ProcessThreadImpl::ProcessThreadImpl() 31 : _timeEvent(*EventWrapper::Create()), 32 _critSectModules(CriticalSectionWrapper::CreateCriticalSection()), 33 _thread(NULL) 34 { 35 } 36 37 ProcessThreadImpl::~ProcessThreadImpl() 38 { 39 delete _critSectModules; 40 delete &_timeEvent; 41 } 42 43 int32_t ProcessThreadImpl::Start() 44 { 45 CriticalSectionScoped lock(_critSectModules); 46 if(_thread) 47 { 48 return -1; 49 } 50 _thread = ThreadWrapper::CreateThread(Run, this, kNormalPriority, 51 "ProcessThread"); 52 unsigned int id; 53 int32_t retVal = _thread->Start(id); 54 if(retVal >= 0) 55 { 56 return 0; 57 } 58 delete _thread; 59 _thread = NULL; 60 return -1; 61 } 62 63 int32_t ProcessThreadImpl::Stop() 64 { 65 _critSectModules->Enter(); 66 if(_thread) 67 { 68 _thread->SetNotAlive(); 69 70 ThreadWrapper* thread = _thread; 71 _thread = NULL; 72 73 _timeEvent.Set(); 74 _critSectModules->Leave(); 75 76 if(thread->Stop()) 77 { 78 delete thread; 79 } else { 80 return -1; 81 } 82 } else { 83 _critSectModules->Leave(); 84 } 85 return 0; 86 } 87 88 int32_t ProcessThreadImpl::RegisterModule(Module* module) 89 { 90 CriticalSectionScoped lock(_critSectModules); 91 92 // Only allow module to be registered once. 93 for (ModuleList::iterator iter = _modules.begin(); 94 iter != _modules.end(); ++iter) { 95 if(module == *iter) 96 { 97 return -1; 98 } 99 } 100 101 _modules.push_front(module); 102 103 // Wake the thread calling ProcessThreadImpl::Process() to update the 104 // waiting time. The waiting time for the just registered module may be 105 // shorter than all other registered modules. 106 _timeEvent.Set(); 107 return 0; 108 } 109 110 int32_t ProcessThreadImpl::DeRegisterModule(const Module* module) 111 { 112 CriticalSectionScoped lock(_critSectModules); 113 for (ModuleList::iterator iter = _modules.begin(); 114 iter != _modules.end(); ++iter) { 115 if(module == *iter) 116 { 117 _modules.erase(iter); 118 return 0; 119 } 120 } 121 return -1; 122 } 123 124 bool ProcessThreadImpl::Run(void* obj) 125 { 126 return static_cast<ProcessThreadImpl*>(obj)->Process(); 127 } 128 129 bool ProcessThreadImpl::Process() 130 { 131 // Wait for the module that should be called next, but don't block thread 132 // longer than 100 ms. 133 int32_t minTimeToNext = 100; 134 { 135 CriticalSectionScoped lock(_critSectModules); 136 for (ModuleList::iterator iter = _modules.begin(); 137 iter != _modules.end(); ++iter) { 138 int32_t timeToNext = (*iter)->TimeUntilNextProcess(); 139 if(minTimeToNext > timeToNext) 140 { 141 minTimeToNext = timeToNext; 142 } 143 } 144 } 145 146 if(minTimeToNext > 0) 147 { 148 if(kEventError == _timeEvent.Wait(minTimeToNext)) 149 { 150 return true; 151 } 152 CriticalSectionScoped lock(_critSectModules); 153 if(!_thread) 154 { 155 return false; 156 } 157 } 158 { 159 CriticalSectionScoped lock(_critSectModules); 160 for (ModuleList::iterator iter = _modules.begin(); 161 iter != _modules.end(); ++iter) { 162 int32_t timeToNext = (*iter)->TimeUntilNextProcess(); 163 if(timeToNext < 1) 164 { 165 (*iter)->Process(); 166 } 167 } 168 } 169 return true; 170 } 171 } // namespace webrtc 172