Thread以组合方式扩展了boost::thread
事件队列的实现和事件传递部分的代码很巧妙。
扩展了以下功能:
1、线程消息队列
2、线程删除自身
3、sleep
1、线程消息队列的实现方式:
void Thread::runEvents() {
RecursiveMutex::ScopedLock scopedLock(_threadMutex);
while (true) {
while (!_eventQueue.empty()) {//处理所有入栈事件
IThreadEvent *event = _eventQueue.front();
_eventQueue.pop();
scopedLock.unlock();//保护_eventQueue,在取出后,事件可以继续入队列。
event->callback();//处理事件
OWSAFE_DELETE(event);//释放事件
scopedLock.lock();//保护_eventQueue,不允许操作_eventQueue
}
//所有事件已经处理完毕
if (_terminate) {
return;
}
//继续等待事件_threadMutex必须已经lock,进入等待后_threadMutex被自动unlock
_threadCondition.wait(scopedLock);//_threadMutex
//当wait返回时,_threadMutex上的锁会重新加上
}
}
_eventQueue即为消息队列
传递消息的函数postEvent
注意参数为IThreadEvent,内含一个回调函数callback
当一个线程向Thread类型的线程传递事件时,需要把处理该事件的函数一并传递给目标线程。
这样做的直接目的就是在目标线程内调用该函数对象。即在void Thread::runEvents()内的event->callback();调用之。
关于IThreadEvent在后面说明。先说明消息队列的具体实现。
void Thread::runEvents()内
取出一个事件:
IThreadEvent *event = _eventQueue.front();
_eventQueue.pop();
处理一个事件:
event->callback();
OWSAFE_DELETE(event);//释放事件占用的堆空间。
等待一个事件:
_threadCondition.wait(scopedLock);
传递消息的函数postEvent的说明:
void Thread::postEvent(IThreadEvent * event) {
//自动锁,构造时_threadMutex.lock析构时_threadMutex.unlock
RecursiveMutex::ScopedLock scopedLock(_threadMutex);
//事件入队列
_eventQueue.push(event);
//手动为_threadMutex解锁,runEvents内_threadCondition wait一个RecursiveMutex::ScopedLock对象。该对象以_threadMutex构造。
scopedLock.unlock();
_threadCondition.notify_all();//唤醒在_threadCondition上wait的所有线程(实际只有本线程)。
}
注意scopedLock.unlock()之后,在postEvent时不会再次调用unlock
原因见scoped_lock的析构函数 ~scoped_lock()
如下:
explicit scoped_lock(Mutex& mx, bool initially_locked=true)
: m_mutex(mx), m_locked(false)
{
if (initially_locked) lock();
}
~scoped_lock()
{
if (m_locked) unlock();
}
void lock()
{
if (m_locked) throw lock_error();
lock_ops<Mutex>::lock(m_mutex);
m_locked = true;
}
void unlock()
{
if (!m_locked) throw lock_error();
lock_ops<Mutex>::unlock(m_mutex);
m_locked = false;
}
scoped_lock内部记录了m_locked的状态,因此当手动unlock后,该对象析构后不再unlock
关于boost::condition
condition是一个简单的同步对象,用于使一个线程等待一个特定的条件成立(比如
资源可用)。一个condition对象总是和一个lock对象配合使用。wait系列函数调用后,
必须已经通过lock对象加上了锁。当线程陷入等待时,condtion
对象将释放lock对象上的锁,当wait返回时,lock对象上的锁会重新加上,
这一unlock/lock动作由conditon对象自动完成。
2、删除自身
声明:
Thread.h:
public:
/**
* Defines whether the thread should delete itself at end.
*/
OWTHREAD_API void setAutoDelete(bool);
/**
* Returns true if the thread will autodelete itself.
*/
OWTHREAD_API bool getAutoDelete() const;
protect:
/**
* If set to true, the class will automatically delete itself when run()
* returns.
* default is false.
*/
bool _autoDelete;
Thread.cpp实现删除自身的代码:
runThread是一个线程启动代理函数,调用了虚函数run(),run即为线程函数。
void Thread::runThread() {
{
RecursiveMutex::ScopedLock scopedLock(_threadMutex);
_threadRunning = true;
}
if(_terminate == true)//线程对象未启动已被删除
{
printf("==##[error]thd del before actually running!##==/n");
return;
}
run();
bool autoDelete;
{
RecursiveMutex::ScopedLock scopedLock(_threadMutex);
_threadRunning = false;
autoDelete = _autoDelete;
}
if (autoDelete) {//这里实现自删除
delete this;
}
}