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 释放进程中分配的索引值.

原文地址:https://www.cnblogs.com/fangkm/p/1508655.html