195 lines
5.2 KiB
C++
195 lines
5.2 KiB
C++
|
/*
|
||
|
* Copyright (c) 2011 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 "process_thread_impl.h"
|
||
|
#include "module.h"
|
||
|
#include "trace.h"
|
||
|
|
||
|
namespace webrtc {
|
||
|
ProcessThread::~ProcessThread()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
ProcessThread* ProcessThread::CreateProcessThread()
|
||
|
{
|
||
|
WEBRTC_TRACE(kTraceModuleCall, kTraceUtility, -1, "CreateProcessThread()");
|
||
|
return new ProcessThreadImpl();
|
||
|
}
|
||
|
|
||
|
void ProcessThread::DestroyProcessThread(ProcessThread* module)
|
||
|
{
|
||
|
WEBRTC_TRACE(kTraceModuleCall, kTraceUtility, -1, "DestroyProcessThread()");
|
||
|
delete module;
|
||
|
}
|
||
|
|
||
|
ProcessThreadImpl::ProcessThreadImpl()
|
||
|
: _timeEvent(*EventWrapper::Create()),
|
||
|
_critSectModules(*CriticalSectionWrapper::CreateCriticalSection()),
|
||
|
_thread(NULL)
|
||
|
{
|
||
|
WEBRTC_TRACE(kTraceMemory, kTraceUtility, -1, "%s created", __FUNCTION__);
|
||
|
}
|
||
|
|
||
|
ProcessThreadImpl::~ProcessThreadImpl()
|
||
|
{
|
||
|
delete &_critSectModules;
|
||
|
delete &_timeEvent;
|
||
|
WEBRTC_TRACE(kTraceMemory, kTraceUtility, -1, "%s deleted", __FUNCTION__);
|
||
|
}
|
||
|
|
||
|
WebRtc_Word32 ProcessThreadImpl::Start()
|
||
|
{
|
||
|
CriticalSectionScoped lock(_critSectModules);
|
||
|
if(_thread)
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
_thread = ThreadWrapper::CreateThread(Run, this, kNormalPriority,
|
||
|
"ProcessThread");
|
||
|
unsigned int id;
|
||
|
WebRtc_Word32 retVal = _thread->Start(id);
|
||
|
if(retVal >= 0)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
delete _thread;
|
||
|
_thread = NULL;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
WebRtc_Word32 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;
|
||
|
}
|
||
|
|
||
|
WebRtc_Word32 ProcessThreadImpl::RegisterModule(const Module* module)
|
||
|
{
|
||
|
WEBRTC_TRACE(kTraceModuleCall, kTraceUtility, -1,
|
||
|
"RegisterModule(module:0x%x)", module);
|
||
|
CriticalSectionScoped lock(_critSectModules);
|
||
|
|
||
|
// Only allow module to be registered once.
|
||
|
ListItem* item = _modules.First();
|
||
|
for(WebRtc_UWord32 i = 0; i < _modules.GetSize() && item; i++)
|
||
|
{
|
||
|
if(module == item->GetItem())
|
||
|
{
|
||
|
return -1;
|
||
|
}
|
||
|
item = _modules.Next(item);
|
||
|
}
|
||
|
|
||
|
_modules.PushFront(module);
|
||
|
WEBRTC_TRACE(kTraceInfo, kTraceUtility, -1,
|
||
|
"number of registered modules has increased to %d",
|
||
|
_modules.GetSize());
|
||
|
// 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;
|
||
|
}
|
||
|
|
||
|
WebRtc_Word32 ProcessThreadImpl::DeRegisterModule(const Module* module)
|
||
|
{
|
||
|
WEBRTC_TRACE(kTraceModuleCall, kTraceUtility, -1,
|
||
|
"DeRegisterModule(module:0x%x)", module);
|
||
|
CriticalSectionScoped lock(_critSectModules);
|
||
|
|
||
|
ListItem* item = _modules.First();
|
||
|
for(WebRtc_UWord32 i = 0; i < _modules.GetSize() && item; i++)
|
||
|
{
|
||
|
if(module == item->GetItem())
|
||
|
{
|
||
|
int res = _modules.Erase(item);
|
||
|
WEBRTC_TRACE(kTraceInfo, kTraceUtility, -1,
|
||
|
"number of registered modules has decreased to %d",
|
||
|
_modules.GetSize());
|
||
|
return res;
|
||
|
}
|
||
|
item = _modules.Next(item);
|
||
|
}
|
||
|
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.
|
||
|
WebRtc_Word32 minTimeToNext = 100;
|
||
|
{
|
||
|
CriticalSectionScoped lock(_critSectModules);
|
||
|
ListItem* item = _modules.First();
|
||
|
for(WebRtc_UWord32 i = 0; i < _modules.GetSize() && item; i++)
|
||
|
{
|
||
|
WebRtc_Word32 timeToNext =
|
||
|
static_cast<Module*>(item->GetItem())->TimeUntilNextProcess();
|
||
|
if(minTimeToNext > timeToNext)
|
||
|
{
|
||
|
minTimeToNext = timeToNext;
|
||
|
}
|
||
|
item = _modules.Next(item);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(minTimeToNext > 0)
|
||
|
{
|
||
|
if(kEventError == _timeEvent.Wait(minTimeToNext))
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
if(!_thread)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
{
|
||
|
CriticalSectionScoped lock(_critSectModules);
|
||
|
ListItem* item = _modules.First();
|
||
|
for(WebRtc_UWord32 i = 0; i < _modules.GetSize() && item; i++)
|
||
|
{
|
||
|
WebRtc_Word32 timeToNext =
|
||
|
static_cast<Module*>(item->GetItem())->TimeUntilNextProcess();
|
||
|
if(timeToNext < 1)
|
||
|
{
|
||
|
static_cast<Module*>(item->GetItem())->Process();
|
||
|
}
|
||
|
item = _modules.Next(item);
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
} // namespace webrtc
|