ACE_TSS研究

线程局部存储(TLS)在多线程编程过程中很有用.静态TLS使用方便,但不适合动态链接环境。动态TLS常用的API如下:

DWORD TlsAlloc(void); //查找进程的线程本地存储器的位标志,返回未使用的位标志索引。PS:其返回的索引,在进程的每个线程均保留这个索引

BOOL TlsSetValue( DWORD dwTlsIndex, LPVOID lpTlsValue );  //将一个值放入线程的线程局部存储数组

LPVOID TlsGetValue( DWORD dwTlsIndex);     //获取线程指定索引位置的值

BOOL TlsFree( DWORD dwTlsIndex);  //释放进程和所有线程指定位置的索引

ACE中对线程局部存储做了封装,封装位于ACE_TSS类.该类是模板类,并重载了->和*操作符,使用起来与智能指针类似.ACE_TSS的使用示例如下:

// 线程局部变量,该变量是int类型
ACE_TSS < int >   data;

void   ThreadCall()
{
    
char   szBuffer[ 1024 ];
    
// 访问线程局部变量
    ACE_OS::sprintf( szBuffer,  " 当前线程ID: %d  ACE_TSS值:%d  \n " * data, ACE_Thread::self() );
    AtlTrace( szBuffer );
    ACE_OS::sleep( 
1  );
}

DWORD  WorkFunc( 
void *  )
{
    
// 设置线程局部变量为当前线程的ID
     * data   =  ACE_OS::thr_self();
    ThreadCall();
    
return   0 ;
}
.
// 创建10个线程
ACE_Thread_Manager::instance() -> spawn_n(  10 , (ACE_THR_FUNC)WorkFunc, NULL, THR_NEW_LWP );
// 等待所有线程结束
ACE_Thread_Manager::instance() -> wait();

使用起来真的很酷,完全隐藏了实现细节.跟踪ACE_TSS的实现源码,简要地分析一下实现过程:

重载的->和*操作符都调用了成员方法ts_get,该方法首先检测是否已经从进程中分配索引,如果没有,则先调用ts_init从进程中分配索引。随后调用ACE_Thread::getspecific获取调用线程某索引处的值,如果还没有值,则调用make_TSS_TYPE分配一个指针值,make_TSS_TYPE也只是简单地调用ACE_NEW_RETURN分配动态对象.分配后调用ACE_Thread::setspecific设置到某索引处.最后值得一提的是清除工作,在析构函数中首先调用ACE_OS::thr_key_detach释放已经分配的内存指针,继而调用ACE_OS::thr_keyfree 释放进程中分配的索引值.

你可能感兴趣的:(c)