现在的位置: 首页 > 综合 > 正文

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

2014年02月26日 ⁄ 综合 ⁄ 共 2499字 ⁄ 字号 评论关闭

//
// 引用计数在长时间线程过程中的使用
// 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;
}

抱歉!评论已关闭.