Chrome中的Thread类实现比较有意思,没有复杂的接口,没有很多可调控的参数,譬如线程优先级什么的。
线程类Thread定义在base命名空间里,是一个比较通用的基础类。位于文件src\base\thread.h。Thread继承于PlatformThread::Delegate类,除了提供易用的接口之外,比较中要的内容就是实现了线程入口函数,这种继承框架是基于跨平台考虑。跟平台相关的代码放在了PlatformThread类里,线程启动时,转调用它Delegate类的函数体就可以。以下是PlatformThread::Delegate类的说明:
// A simple thread abstraction that establishes a MessageLoop on a new thread.
// The consumer uses the MessageLoop of the thread to cause code to execute on
// the thread. When this object is destroyed the thread is terminated. All
// pending tasks queued on the thread's message loop will run to completion
// before the thread is terminated.
class Thread : PlatformThread:: Delegate {
PlatformThread::Delegate类定义在\src\base\platform_thread.h文件中,是一个接口。
// Implement this interface to run code on a background thread. Your
// ThreadMain method will be called on the newly created thread.
class Delegate {
public:
virtual ~ Delegate() {}
virtual void ThreadMain () = 0;
};
base::Thread实现了ThreadMain函数。
PlatformThread类里函数全部都是static,譬如Create线程函数:
static bool Create (size_t stack_size, Delegate * delegate,
PlatformThreadHandle* thread_handle );
传入delegate参数,提供线程入口函数,比如Thread,这个函数将会创建线程,在Windows平台会调用WIN32API函数CreateThread:
*thread_handle = CreateThread(
NULL, stack_size , ThreadFunc, delegate, flags , NULL);
DWORD __stdcall ThreadFunc( void* closure ) {
PlatformThread:: Delegate* delegate =
static_cast( closure);
delegate-> ThreadMain();
return NULL;
}
以上方法我们都干过。
在Thread类的实现,每个Thread都会有一个message_loop,用来处理各种message,更准确的说应该是Task。每个线程正常结束前,应该执行一个叫做ThreadQuitTask的task,它的执行体相当简单,就是调用MessageLoop的Quit函数。Thread类里维护着一个MessageLoop的指针, 你可能会认为它是一个指向堆上对象的指针,但是不是的,它是一个指向栈上对象的指针,类似的数据成员还有StartData* startup_data_(用来判断线程是否启动的标志量)。我们来看下Thread的线程函数体是怎样的:
void Thread :: ThreadMain() {
// The message loop for this thread.
MessageLoop message_loop (startup_data_ -> options. message_loop_type );
// Complete the initialization of our Thread object.
thread_id_ = PlatformThread ::CurrentId ();
PlatformThread:: SetName (name_ . c_str());
message_loop. set_thread_name (name_ );
message_loop_ = & message_loop ;
// Let the thread do extra initialization.
// Let's do this before signaling we are started.
Init();
startup_data_-> event .Signal ();
// startup_data_ can't be touched anymore since the starting thread is now
// unlocked.
message_loop. Run ();
// Let the thread do extra cleanup.
CleanUp();
// Assert that MessageLoop::Quit was called by ThreadQuitTask.
DCHECK( GetThreadWasQuitProperly ());
// We can't receive messages anymore.
message_loop_ = NULL ;
thread_id_ = 0;
}
注意的是,这个函数是执行在一个新的线程里。首先,它实例化一个局部MessageLoop,其实它就是这个线程的MessageLoop,用Thread::message_loop()函数返回的就是它的指针。接着调用message_loop::Run()函数来执行task,直到messageloop遇到ThreadQuitTask类型的task。注意的是,在线程执行过程,这个messageloop始终是可以访问的。线程销毁时,这个局部的messageloop就是销毁,线程的message loop也就销毁了。这种方式大大减少了对象生命期管理的问题,而且也减少了堆上对象创建销毁的开销。挺好。
bool Thread::Start() {
return StartWithOptions(Options());
}
bool Thread::StartWithOptions(const Options& options) {
DCHECK(!message_loop_);
SetThreadWasQuitProperly(false);
StartupData startup_data(options);
startup_data_ = &startup_data;
if (!PlatformThread::Create(options.stack_size, this, &thread_)) {
DLOG(ERROR) << "failed to create thread";
startup_data_ = NULL; // Record that we failed to start.
return false;
}
// Wait for the thread to start and initialize message_loop_
startup_data.event.Wait();
DCHECK(message_loop_);
return true;
}
传给StartWithOptions函数的options只是一个临时对象,而且start_data也是一个局部的,Thread::startup_data_指向的是这个局部变量。当线程函数启动之后,Start函数返回后,这个startup_data_存储的指针也就变成了野指针。Thread::Stop函数会将其reset到NULL。