moztw.org

Gecko內部探索 – 如何使用 Thread

俗話說得好: 每個偉大系統背後都有個好用的 Thread 機制,Gecko 也不例外,本篇台客文就是介紹在 Gecko 裡 thread 的一些基本使用方式及相關的 class 。

首先, Gecko 內部的 thread 基本上是使用 nsIThread 這個介面,透過 NS_NewThread 來產生, thread 會有一個 job queue, thread 會一直執行 queue 裡面的 job,如果沒有 job 時,則是停留在 queue 內部,此時不會耗費額外的 cpu;而由 NS_NewThread 所產生的 thread 會由另外一個 class,nsThreadManager 來管理,當系統要停止時, nsThreadManager 便會把他所管理的所有 thread 分別呼叫 nsIThread::Shutdown ,來將旗下的 thread 停止。

下面我們來看一段簡單的程式碼

nsCOMPtr<nsIThread> sThread;

class HelloThread : public RefCounted {
public:
void HelloWorld() {
printf("我是台客");
}
};

void InititalizeThread() {
NS_NewThread(getter_AddRefs(sThread));
}

void ReleaseThread() {
sThread->Shutdown();
}

void AddJob() {
nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(new HelloThread(), &HelloThread::HelloWorld);
sThread->Dispatch(event, NS_DISPATCH_NORMAL);
}

123456789101112131415161718192021

nsCOMPtr<nsIThread> sThread; class HelloThread : public RefCounted {public: void HelloWorld() { printf("我是台客"); }}; void InititalizeThread() { NS_NewThread(getter_AddRefs(sThread));} void ReleaseThread() { sThread->Shutdown();} void AddJob() { nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(new HelloThread(), &HelloThread::HelloWorld); sThread->Dispatch(event, NS_DISPATCH_NORMAL);}

以上的程式碼就是實作一個簡單的 HelloThread ,當使用者呼叫了 AddJob 時,便會新增一個 job 到 sThread 的 queue 裡面,然後 sThread 便會去執行 HelloWorld 這個 function 印出 “我是台客”。

下面是幾個常見的問題,

  • HelloThread 是否一定要繼承 RefCounted ? 不用,只要有實作 AddRef 和 Release 即可
  • 我是否可以將 job 指定給 main thread? 可以的,你只要呼叫 NS_DispatchToMainThread。
  • sThread->Shutdown 時,若還有 job 在 thread 內部會怎樣? Shutdown 是一個 blocking function ,會將thread 內部所有的 job 都執行完,才會離開。
  • 千萬不要 sThread本身呼叫 Shutdown ,這樣會導致 dead lock。