Home | History | Annotate | Download | only in source
      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