| /* | 
 |  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 
 |  * | 
 |  *  Use of this source code is governed by a BSD-style license | 
 |  *  that can be found in the LICENSE file in the root of the source | 
 |  *  tree. An additional intellectual property rights grant can be found | 
 |  *  in the file PATENTS.  All contributing project authors may | 
 |  *  be found in the AUTHORS file in the root of the source tree. | 
 |  */ | 
 |  | 
 | #include "webrtc/modules/interface/module.h" | 
 | #include "webrtc/modules/utility/source/process_thread_impl.h" | 
 |  | 
 |  | 
 | namespace webrtc { | 
 | ProcessThread::~ProcessThread() | 
 | { | 
 | } | 
 |  | 
 | ProcessThread* ProcessThread::CreateProcessThread() | 
 | { | 
 |     return new ProcessThreadImpl(); | 
 | } | 
 |  | 
 | void ProcessThread::DestroyProcessThread(ProcessThread* module) | 
 | { | 
 |     delete module; | 
 | } | 
 |  | 
 | ProcessThreadImpl::ProcessThreadImpl() | 
 |     : _timeEvent(*EventWrapper::Create()), | 
 |       _critSectModules(CriticalSectionWrapper::CreateCriticalSection()), | 
 |       _thread(NULL) | 
 | { | 
 | } | 
 |  | 
 | ProcessThreadImpl::~ProcessThreadImpl() | 
 | { | 
 |     delete _critSectModules; | 
 |     delete &_timeEvent; | 
 | } | 
 |  | 
 | int32_t ProcessThreadImpl::Start() | 
 | { | 
 |     CriticalSectionScoped lock(_critSectModules); | 
 |     if(_thread) | 
 |     { | 
 |         return -1; | 
 |     } | 
 |     _thread = ThreadWrapper::CreateThread(Run, this, kNormalPriority, | 
 |                                           "ProcessThread"); | 
 |     unsigned int id; | 
 |     int32_t retVal = _thread->Start(id); | 
 |     if(retVal >= 0) | 
 |     { | 
 |         return 0; | 
 |     } | 
 |     delete _thread; | 
 |     _thread = NULL; | 
 |     return -1; | 
 | } | 
 |  | 
 | int32_t ProcessThreadImpl::Stop() | 
 | { | 
 |     _critSectModules->Enter(); | 
 |     if(_thread) | 
 |     { | 
 |         _thread->SetNotAlive(); | 
 |  | 
 |         ThreadWrapper* thread = _thread; | 
 |         _thread = NULL; | 
 |  | 
 |         _timeEvent.Set(); | 
 |         _critSectModules->Leave(); | 
 |  | 
 |         if(thread->Stop()) | 
 |         { | 
 |             delete thread; | 
 |         } else { | 
 |             return -1; | 
 |         } | 
 |     } else { | 
 |         _critSectModules->Leave(); | 
 |     } | 
 |     return 0; | 
 | } | 
 |  | 
 | int32_t ProcessThreadImpl::RegisterModule(Module* module) | 
 | { | 
 |     CriticalSectionScoped lock(_critSectModules); | 
 |  | 
 |     // Only allow module to be registered once. | 
 |     for (ModuleList::iterator iter = _modules.begin(); | 
 |          iter != _modules.end(); ++iter) { | 
 |         if(module == *iter) | 
 |         { | 
 |             return -1; | 
 |         } | 
 |     } | 
 |  | 
 |     _modules.push_front(module); | 
 |  | 
 |     // Wake the thread calling ProcessThreadImpl::Process() to update the | 
 |     // waiting time. The waiting time for the just registered module may be | 
 |     // shorter than all other registered modules. | 
 |     _timeEvent.Set(); | 
 |     return 0; | 
 | } | 
 |  | 
 | int32_t ProcessThreadImpl::DeRegisterModule(const Module* module) | 
 | { | 
 |     CriticalSectionScoped lock(_critSectModules); | 
 |     for (ModuleList::iterator iter = _modules.begin(); | 
 |          iter != _modules.end(); ++iter) { | 
 |         if(module == *iter) | 
 |         { | 
 |             _modules.erase(iter); | 
 |             return 0; | 
 |         } | 
 |     } | 
 |     return -1; | 
 | } | 
 |  | 
 | bool ProcessThreadImpl::Run(void* obj) | 
 | { | 
 |     return static_cast<ProcessThreadImpl*>(obj)->Process(); | 
 | } | 
 |  | 
 | bool ProcessThreadImpl::Process() | 
 | { | 
 |     // Wait for the module that should be called next, but don't block thread | 
 |     // longer than 100 ms. | 
 |     int32_t minTimeToNext = 100; | 
 |     { | 
 |         CriticalSectionScoped lock(_critSectModules); | 
 |         for (ModuleList::iterator iter = _modules.begin(); | 
 |              iter != _modules.end(); ++iter) { | 
 |           int32_t timeToNext = (*iter)->TimeUntilNextProcess(); | 
 |             if(minTimeToNext > timeToNext) | 
 |             { | 
 |                 minTimeToNext = timeToNext; | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     if(minTimeToNext > 0) | 
 |     { | 
 |         if(kEventError == _timeEvent.Wait(minTimeToNext)) | 
 |         { | 
 |             return true; | 
 |         } | 
 |         CriticalSectionScoped lock(_critSectModules); | 
 |         if(!_thread) | 
 |         { | 
 |             return false; | 
 |         } | 
 |     } | 
 |     { | 
 |         CriticalSectionScoped lock(_critSectModules); | 
 |         for (ModuleList::iterator iter = _modules.begin(); | 
 |              iter != _modules.end(); ++iter) { | 
 |           int32_t timeToNext = (*iter)->TimeUntilNextProcess(); | 
 |             if(timeToNext < 1) | 
 |             { | 
 |                 (*iter)->Process(); | 
 |             } | 
 |         } | 
 |     } | 
 |     return true; | 
 | } | 
 | }  // namespace webrtc |