现在的服务端程序都是多线程的并且其中有大量的工作现场,如何知道每一个工作线程都在干什么?
在服务端程序实现时必须考虑到一些工作需要耗时较长,甚至可能因为死锁等原因导致一些线程进入了某个调用就退步出来的情况,这个时候增加远程连接对服务端程序内部工作状态的查看功能就必不可少了;
本文基于一个服务端程序的线程运行信息管理的实现介绍原理并给出代码
首先我们要考虑到对线程运行信息的访问不能有频繁的锁操作,其次该信息应该能够根据使用情况自动的为每个需要运行信息的线程分配的存储空间并且各不关联,同时需要所有线程的运行信息能够进行遍历,这样就可以考虑这样实现:
- 线程的运行信息存储在线程专用存储中,这样不但数据各个线程分开避免了锁的开销,而且方便编写程序(就像使用一个单独的成员变量一样);
- 每一个线程的运行信息结构的指针和线程的ID关联起来放置到哈希映射表中,这样便于对所有使用了运行信息的线程进行遍历;
- 由于运行信息记录的是一个工作线程的工作过程,因此是一个开始工作时记录,结束工作时清除的类似栈的数据信息;
同时因为运行信息只记录需要时间较长并且可能引起无法返回的工作,所以信息量不会很大,因此使用使用一个固定大小的结构定义出来,然后使用 ACE_TSS 模板来自动进行线程专用存储的管理,同时使用 ACE_Hash_Map_Manager 来关联线程ID和运行信息指针;
下面是实现:
#pragma once
//==================================================================================================
// 概述:
// 线程状态管理器:管理各个线程的运行状态
//==================================================================================================
struct StatusManager
{
public:
//----------------------------------------------------------------------------------------------
// 概述:
// 设置线程的运行信息
//----------------------------------------------------------------------------------------------
static ACE_UINT32 SetRunInfo( const char * RunInfo )
{
TASK_RUN_INFO & TaskRunInfo = GetInstance( ).GetTaskRunInfo( );
CHK_EXP_RUN( TaskRunInfo.Number >= MAX_TRI_NUMBER , MAX_TRI_NUMBER );
TASK_RUN_STATUS & Status = TaskRunInfo.Status[ TaskRunInfo.Number ];
strncpy( Status.String , RunInfo , MAX_TRI_LENGTH - 1 );
ACE_OS::gettimeofday( ).msec( Status.DateTime );
return TaskRunInfo.Number ++ ;
}
//----------------------------------------------------------------------------------------------
// 概述:
// 清除线程的运行信息
//----------------------------------------------------------------------------------------------
static ACE_UINT32 ClrRunInfo( ACE_UINT32 RunInfoID )
{
TASK_RUN_INFO & TaskRunInfo = GetInstance( ).GetTaskRunInfo( );
CHK_EXP_RUN( TaskRunInfo.Number <= RunInfoID , RunInfoID );
// 消除指定信息及其以后的信息
return TaskRunInfo.Number = RunInfoID ;
}
protected:
//----------------------------------------------------------------------------------------------
// 概述:
// 定义数据结构和哈希映射类型
//----------------------------------------------------------------------------------------------
enum TASK_RUN_INFO_CAPACITY { MAX_TRI_NUMBER = 255 , MAX_TRI_LENGTH = 120 };
struct TASK_RUN_STATUS { ACE_UINT64 DateTime; char String[ MAX_TRI_LENGTH ]; };
struct TASK_RUN_INFO { ACE_UINT32 Number; TASK_RUN_STATUS Status[ MAX_TRI_NUMBER ]; };
struct S_TASK_RUN_INFO : public TASK_RUN_INFO { S_TASK_RUN_INFO( ) { memset( this , 0 ,sizeof( * this ) ); } };
typedef ACE_Hash_Map_Manager< ACE_thread_t , TASK_RUN_INFO * , ACE_Thread_Mutex > ACE_Hash_Map_Task_Run_Info;
//----------------------------------------------------------------------------------------------
// 概述:
// 获取线程运行信息结构引用
//----------------------------------------------------------------------------------------------
inline TASK_RUN_INFO & GetTaskRunInfo( )
{
ACE_thread_t Thread = ACE_Thread_Manager::instance( )->thr_self( );
S_TASK_RUN_INFO * lpTaskRunInfo = TaskRunInfo;
HashRunInfo.rebind( Thread , lpTaskRunInfo );
return * lpTaskRunInfo ;
}
//----------------------------------------------------------------------------------------------
// 概述:
// 获取状态管理器
//----------------------------------------------------------------------------------------------
static StatusManager & GetInstance( )
{
static StatusManager sxStatusManager;
return sxStatusManager;
}
protected:
//----------------------------------------------------------------------------------------------
ACE_Hash_Map_Task_Run_Info HashRunInfo;
ACE_TSS< S_TASK_RUN_INFO > TaskRunInfo;
};
//==================================================================================================
// 概述:
// 任务运行信息自动设置清除类
//==================================================================================================
struct DPS_Task_Run_Info
{
inline DPS_Task_Run_Info( const char * Format ,
![](https://images.cnblogs.com/dot.gif)
{
char RunInfo[ 128 ] ={ "" };
va_list args; va_start( args , Format );
vsnprintf( RunInfo , 120 , Format , args );
m_nTaskRunInfo = StatusManager::SetRunInfo( RunInfo );
}
inline ~DPS_Task_Run_Info( )
{
StatusManager::ClrRunInfo( m_nTaskRunInfo );
}
ACE_UINT32 m_nTaskRunInfo;
};
//==================================================================================================
// 概述:
// 根据编译选项来控制是否需要运行时任务信息
//==================================================================================================
#ifdef _DPS_DISABLE_TASK_RUN_INFO_
# define TASK_RUN_INFO( Format ,
![](https://images.cnblogs.com/dot.gif)
# define TASK_RUN_INFO_EX( Name , Format ,
![](https://images.cnblogs.com/dot.gif)
#else
# define TASK_RUN_INFO( Format ,
![](https://images.cnblogs.com/dot.gif)
# define TASK_RUN_INFO_EX( Name , Format ,
![](https://images.cnblogs.com/dot.gif)
#endif
由于宏中使用了可变参数,所以需要 VC 7.1 及其以上版本才能正常编译,如果不需要可变参数以及信息的格式化功能,那么稍作修改即可使用在 VC6 上