为了学习多线程,现在开始着手研究chorme的线程模型。话了几个小时看了几篇文章,了解了一下chrome线程工作的基本原理。
这里贴出几篇有代表性的:
1.http://www.chromium.org/developers/design-documents/threading
2.http://blog.csdn.net/milado_nju/article/details/8027625
3.http://bigasp.com/archives/478#comment-22185
4.http://blog.csdn.net/awebkit/article/details/7896894
还是有很多大牛对chrome进行了研究,既然还不能总括全局,那么就庖丁解牛吧,从最基本的code开始看。
首先是thread类。我对其中的代码,取消了注释,不然行数太多。
class BASE_EXPORT Thread : PlatformThread::Delegate
{
public:
struct Options
{
Options() : message_loop_type(MessageLoop::TYPE_DEFAULT), stack_size(0) {}
Options(MessageLoop::Type type, size_t size)
: message_loop_type(type), stack_size(size) {}
MessageLoop::Type message_loop_type;
size_t stack_size;
};
explicit Thread(const char* name);
virtual ~Thread();
void init_com_with_mta(bool use_mta) {
DCHECK(!started_);
com_status_ = use_mta ? MTA : STA;
}
bool Start();
bool StartWithOptions(const Options& options);
void Stop();
void StopSoon();
MessageLoop* message_loop() const { return message_loop_; }
scoped_refptr<MessageLoopProxy> message_loop_proxy() const
{
return message_loop_ ? message_loop_->message_loop_proxy() : NULL;
}
const std::string& thread_name() const { return name_; }
PlatformThreadHandle thread_handle() { return thread_; }
PlatformThreadId thread_id() const { return thread_id_; }
bool IsRunning() const;
void SetPriority(ThreadPriority priority);
protected:
virtual void Init() {}
virtual void Run(MessageLoop* message_loop);
virtual void CleanUp() {}
static void SetThreadWasQuitProperly(bool flag);
static bool GetThreadWasQuitProperly();
void set_message_loop(MessageLoop* message_loop)
{
message_loop_ = message_loop;
}
enum ComStatus {
NONE,
STA,
MTA,
};
virtual void ThreadMain() OVERRIDE;
ComStatus com_status_;
bool started_;
bool stopping_;
bool running_;
struct StartupData;
StartupData* startup_data_;
PlatformThreadHandle thread_;
MessageLoop* message_loop_;
PlatformThreadId thread_id_;
std::string name_;
friend void ThreadQuitHelper();
DISALLOW_COPY_AND_ASSIGN(Thread);
};
namespace
{
base::LazyInstance<base::ThreadLocalBoolean> lazy_tls_bool =
LAZY_INSTANCE_INITIALIZER;
}
void ThreadQuitHelper()
{
MessageLoop::current()->QuitWhenIdle();
Thread::SetThreadWasQuitProperly(true);
}
struct Thread::StartupData
{
const Thread::Options& options;
WaitableEvent event;
explicit StartupData(const Options& opt)
: options(opt),
event(false, false)
{}
};
Thread::Thread(const char* name)
:
com_status_(NONE),
started_(false),
stopping_(false),
running_(false),
startup_data_(NULL),
thread_(0),
message_loop_(NULL),
thread_id_(kInvalidThreadId),
name_(name)
{
}
Thread::~Thread()
{
Stop();
}
bool Thread::Start()
{
Options options;
if (com_status_ == STA)
options.message_loop_type = MessageLoop::TYPE_UI;
return StartWithOptions(options);
}
bool Thread::StartWithOptions(const Options& options)
{
DCHECK(!message_loop_);
DCHECK((com_status_ != STA) ||
(options.message_loop_type == MessageLoop::TYPE_UI));
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;
return false;
}
base::ThreadRestrictions::ScopedAllowWait allow_wait;
startup_data.event.Wait();
startup_data_ = NULL;
started_ = true;
DCHECK(message_loop_);
return true;
}
void Thread::Stop()
{
if (!started_)
return;
StopSoon();
PlatformThread::Join(thread_);
DCHECK(!message_loop_);
started_ = false;
stopping_ = false;
}
void Thread::StopSoon()
{
DCHECK_NE(ANNOTATE_UNPROTECTED_READ(thread_id_), PlatformThread::CurrentId());
if (stopping_ || !message_loop_)
return;
stopping_ = true;
message_loop_->PostTask(FROM_HERE, base::Bind(&ThreadQuitHelper));
}
bool Thread::IsRunning() const
{
return running_;
}
void Thread::SetPriority(ThreadPriority priority)
{
DCHECK_NE(thread_id_, kInvalidThreadId);
PlatformThread::SetThreadPriority(thread_, priority);
}
void Thread::Run(MessageLoop* message_loop)
{
message_loop->Run();
}
void Thread::SetThreadWasQuitProperly(bool flag)
{
lazy_tls_bool.Pointer()->Set(flag);
}
bool Thread::GetThreadWasQuitProperly()
{
bool quit_properly = true;
return quit_properly;
}
void Thread::ThreadMain()
{
{
scoped_ptr<MessageLoop> message_loop(
new MessageLoop(startup_data_->options.message_loop_type));
thread_id_ = PlatformThread::CurrentId();
PlatformThread::SetName(name_.c_str());
ANNOTATE_THREAD_NAME(name_.c_str()); // Tell the name to race detector.
message_loop->set_thread_name(name_);
message_loop_ = message_loop.get();
scoped_ptr<win::ScopedCOMInitializer> com_initializer;
if (com_status_ != NONE)
{
com_initializer.reset((com_status_ == STA) ?
new win::ScopedCOMInitializer() :
new win::ScopedCOMInitializer(win::ScopedCOMInitializer::kMTA));
}
Init();
running_ = true;
startup_data_->event.Signal();
Run(message_loop_);
running_ = false;
CleanUp();
com_initializer.reset();
DCHECK(GetThreadWasQuitProperly());
message_loop_ = NULL;
}
}