2008年4月18日星期五

理解libjingle的ThreadManager

Thread Local Storage(TLS)的作用。
进程中的所有线程共享进程的虚拟地址空间。方法中的局部变量对于每个运行这个方法的线程是独立唯一的。但是,全局的静态变量是被这个进程中的所有线程共享的。通过使用TLS你可以为每个线程提供独立的数据。

一般在process初始化时分配tls Index。这样随后这个process中的线程就可以通过这个index存储与每个线程自己相关的数据了。
msdn关于TlsAlloc()的说明:
Allocates a thread local storage (TLS) index. Any thread of the process can subsequently use this index to store and retrieve values that are local to the thread, because each thread receives its own slot for the index.
If the function succeeds, the return value is a TLS index. The slots for the index are initialized to zero.
The threads of the process can use the TLS index in subsequent calls to the TlsFree, TlsSetValue, or TlsGetValue functions. The value of the TLS index should be treated as an opaque value; do not assume that it is an index into a zero-based array
TLS indexes are typically allocated during process or dynamic-link library (DLL) initialization. After a TLS index has been allocated, each thread of the process can use it to access its own TLS storage slot. To store a value in its TLS slot, a thread specifies the index in a call to TlsSetValue. The thread specifies the same index in a subsequent call to TlsGetValue, to retrieve the stored value.
TLS indexes are not valid across process boundaries. A DLL cannot assume that an index assigned in one process is valid in another process.


libjingel中的ThreadManager。
这个类完成对所有Thread实例线程的管理。其中就分配了一个slot index用于保存current thread。

ThreadManager使用ScriticalSecion,ScriticalSection相当于java中的synchronize中使用的锁。
windows使用CRITICAL_SECTION 定义锁。POSIX使用pthread_mutex_t。
相应的方法分别是:
windows: InitializeCriticalSection(&crit_)、EnterCriticalSection(&crit_)、 LeaveCriticalSection(&crit_)、DeleteCriticalSection(&crit_)。
POSIX: pthread_mutex_init()、pthread_mutex_lock(&mutex_)、 pthread_mutex_destroy(&mutex_)、 pthread_mutex_unlock(&mutex_)
ScriticalScope则相当于java中的synchronize块。

CreateThread
Widows 下创建线程的签名。 HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpsa, DWORD cbStack, LPTHREAD_START_ROUTINE lpStartAddr, LPVOID lpvThreadParam, DWORD fdwCreate, LPDWORD lpIDThread);
lpStartAddr是线程运行起始地址,函数指针。lpvThreadParam为函数的参数。
thread_ = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PreRun, this, flags, NULL);
void *Thread::PreRun(void *pv) {
Thread *thread = (Thread *)pv;
ThreadManager::SetCurrent(thread); // 此处把thread放到了TLS中了。
thread->Run();
return NULL;
}


[都怀疑java的native code是不是都是用了ACE的东西了,至少思路该是一样的吧。]