您的位置:首页 > 其它

引用计数自动管理对象的生存周期

2009-12-24 16:09 169 查看
//

// 引用计数在长时间线程过程中的使用

// cheungmine

//

#include <assert.h>

#include <stdio.h>

#include <stdlib.h>

#include <windows.h>

#include <process.h>

// It should be used if the worker class will use CRT functions

static HANDLE CrtCreateThread(LPSECURITY_ATTRIBUTES lpsa,

DWORD dwStackSize,

LPTHREAD_START_ROUTINE pfnThreadProc,

LPVOID pvParam,

DWORD dwCreationFlags,

LPDWORD pdwThreadId)

{

// _beginthreadex calls CreateThread which will set the last error value before it returns

return (HANDLE) _beginthreadex(lpsa,

dwStackSize,

(unsigned int (__stdcall *)(void *)) pfnThreadProc,

pvParam,

dwCreationFlags,

(unsigned int *) pdwThreadId);

}

class CUserdata

{

public:

CUserdata():m_data(100)

{

printf("CUserdata()/n");

}

~CUserdata()

{

printf("~CUserdata()/n");

}

int m_data;

};

template< typename _Type > class ThreadParamT

{

volatile ULONG m_cRef;

// 私有的析构方法保证由引用计数自动管理对象的生存期

~ThreadParamT()

{

printf("~ThreadParamT()::m_cRef=%d/n", m_cRef);

}

public:

ULONG AddRef()

{

return (ULONG) InterlockedIncrement((volatile LONG*)&m_cRef);

}

ULONG Release()

{

if (InterlockedDecrement((volatile LONG*)&m_cRef)==0)

{

delete this;

return 0;

}

return m_cRef;

}

ThreadParamT():

m_cRef(1)

{

printf("ThreadParamT()::m_cRef=%d/n", m_cRef);

}

_Type t;

};

// 线程过程: 长时间执行的 线程过程

// AddRef() 和 Release()必须在线程中成对调用

static DWORD WINAPI LongTimeThreadProc( LPVOID lpParam )

{

ThreadParamT<CUserdata> *pthrParam = (ThreadParamT<CUserdata> *) lpParam;

// 入口处立即增加引用计数

pthrParam->AddRef();

// 模拟执行一个长时间的任务

printf("LongTimeThreadProc::Do a long time job....../n");

SleepEx(10000, 0);

// 返回时必须减少引用计数

pthrParam->Release();

return 0;

}

int main()

{

// 创建线程过程参数, 这个参数传递给线程之后, 生存期就由引用计数控制

ThreadParamT<CUserdata> * thrParam = new ThreadParamT<CUserdata>();

DWORD dwThrId;

HANDLE hThread = CrtCreateThread(0, 0, LongTimeThreadProc, (LPVOID)thrParam, 0, &dwThrId);

// 下面的代码假设我们来不急等待线程执行结束

// 此时, thrParam 的生存期有引用计数管理是适当的

DWORD dwRet = WaitForSingleObject(hThread, 5000);

assert(dwRet==WAIT_TIMEOUT);

CloseHandle(hThread);

// 此时仍可访问线程数据, 注意是否使用关键区保护

printf("此时仍可访问线程数据: %d/n", thrParam->t.m_data);

// 此时释放引用计数, 如果线程未结束, 则数据并未释放

thrParam->Release();

SleepEx(6000, 0);

printf("thrParam 已经不可用, 此时不可访问线程数据: %d/n", thrParam->t.m_data);

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: