• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
~ProcessThread()16 ProcessThread::~ProcessThread()
17 {
18 }
19 
CreateProcessThread()20 ProcessThread* ProcessThread::CreateProcessThread()
21 {
22     return new ProcessThreadImpl();
23 }
24 
DestroyProcessThread(ProcessThread * module)25 void ProcessThread::DestroyProcessThread(ProcessThread* module)
26 {
27     delete module;
28 }
29 
ProcessThreadImpl()30 ProcessThreadImpl::ProcessThreadImpl()
31     : _timeEvent(*EventWrapper::Create()),
32       _critSectModules(CriticalSectionWrapper::CreateCriticalSection()),
33       _thread(NULL)
34 {
35 }
36 
~ProcessThreadImpl()37 ProcessThreadImpl::~ProcessThreadImpl()
38 {
39     delete _critSectModules;
40     delete &_timeEvent;
41 }
42 
Start()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 
Stop()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 
RegisterModule(Module * module)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 
DeRegisterModule(const Module * module)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 
Run(void * obj)124 bool ProcessThreadImpl::Run(void* obj)
125 {
126     return static_cast<ProcessThreadImpl*>(obj)->Process();
127 }
128 
Process()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