用类的非静态成员函数作为线程入口函数的方法--转

 

一个类里的函数,通常要作为线程的入口函数,必须把它指定为static类型。
static类型的类成员函数,并不具有this指针,也不能访问到protected或private类型的类成员。

因为以上的不便,我们会想,怎样把一个普通的类成员函数,当作线程的“入口函数”呢?
方法还是有的,具体说来:
1. 创建一个线程,将类指针this和“入口函数”当作参数传入, 其实这里的“入口函数”已经不是线程真正的入口函数了.
2. 利用->*操作符, 调用该“入口函数”, (this->*入口函数) (arg)

得益于c++的强大模版, 下面是该过程的一个封装, 使用也很简单:
相对于pthread的 pthread_create (thread_id, attr, entry, arg),
如果要把类成员函数当作线程入口, 只需要多加一个this,
thread_proxy(this, thread_id, attr, entry, arg)

/
//代码

#include <cstdio>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>


template <class T>
class thread_proxy_imp
{
protected:
typedef struct
{
T *obj;
void (T::*start_routine)(void *);
void *arg;
sem_t sem;
} thread_param;

    static void *thread_proxy_entry (void *arg)
{
thread_param *param_ptr = static_cast<thread_param *> (arg);
thread_param param = *param_ptr;
sem_post (&param_ptr->sem);

        /* 注意 ->* 操作符 */
(param.obj->*param.start_routine) (param.arg);
}

public:
int pthread_create (
T *obj,
pthread_t *thread,
const pthread_attr_t *attr,
void (T::*start_routine)(void *),
void *arg)
{
int rt;
thread_param param = {obj, start_routine, arg};
/* 为防止param在新线程使用它之前被析构,加上一个semaphore. */
sem_init (&param.sem, 0, 0);
rt = ::pthread_create (thread, attr, &thread_proxy_imp::thread_proxy_entry, static_cast<void *> (&param));
sem_wait (&param.sem);
sem_destroy (&param.sem);
return rt;
}
};


template <class T>
int thread_proxy (
T *obj,
pthread_t *thread,
const pthread_attr_t *attr,
void (T::*start_routine)(void *),
void *arg)  
{
return thread_proxy_imp<T> ().pthread_create (obj, thread, attr, start_routine, arg);
}

class C
{
public:
pthread_t m_thread;
int create_thread ()
{
thread_proxy(this, &m_thread, NULL, &C::thread_entry, (void *) 56);           
}
protected:
void thread_entry (void *arg)
{
for (int i = 0; i < 10; i++)
{
printf ("arg: %d\n", arg);
sleep (1);
}
};
};

int main ()
{
C c;
c.create_thread ();
pthread_join (c.m_thread, NULL);
printf ("exit ...\n");
return 0;
}

===================================================================================

[问题提出]
如何用非静态的类成员函数,作为线程函数!

[问题解答]
可以使用它的隐藏参数,作为线程函数的参数,这样就可匹配参数!

[程序实现]
#include <windows.h>
#include <conio.h>
#include <stdio.h>


class t
{
public:
void Run();
t();

protected:
char c[256];
DWORD WINAPI ThreadFunc();
};

typedef DWORD (WINAPI   t::* pThreadFunc)();

t::t()
{
strcpy(c, "Welcome to use thread proc");
}

DWORD WINAPI t::ThreadFunc()
{
MessageBox(NULL, c, "xixi", MB_OK);
return 0;
}

typedef DWORD (WINAPI * PTHREADFUNC)(LPVOID);

void t::Run()
{
pThreadFunc p = ThreadFunc;
DWORD dwAddress;
memcpy(&dwAddress,&p,sizeof(p));

PTHREADFUNC p1;
memcpy(&p1, &dwAddress, sizeof(p1));

DWORD dwTID;

HANDLE hf;
hf = CreateThread(NULL, 0, p1, this, 0, &dwTID);
if (hf){
CloseHandle(hf);
}
}

void main()
{

t t1;
t1.Run();
getch();
}

==================================================================================

使用就太简单了:任何含有线程成员函数的类,之需要做成这个类的派生类,

然后就可以随时使用 StartThread(TMethod fMethod, TParam& rParam) 函
数,第一个参数是要运行的成员函数,第二个参数是欲调用该成员函数的参
数。呵呵,连 this 都不用传了!

参数这里以后还要继续改进,使得对无参数等情况支持得更好,过两天有空
再帖吧。


#include "stdafx.h"
#include <windows.h>
#include <process.h>
#include <iostream>
using namespace std;

class ClassWithThreadMethod {
public:
template <class TMethod, class TParam> class CThreadMethod {
public:
typedef int(__stdcall ClassWithThreadMethod::*IMethod)(TParam);
uintptr_t StartThread(ClassWithThreadMethod* pObj, TMethod fMethod,
TParam& rParam) {
uintptr_t hThread = 0;
if (pObj && fMethod) {
pObject = pObj, fIMethod = (IMethod)fMethod, oParam = rParam;
hThWait = CreateEvent(NULL, TRUE, FALSE, NULL);
hThread = _beginthreadex(NULL, 0, ThreadFunc, this, 0, &hThread);
CloseHandle((WaitForSingleObject(hThWait ,INFINITE), hThWait));
}
return hThread;
}
private:
static unsigned __stdcall ThreadFunc(void* pThreadMethod) {
CThreadMethod TMCopy = *((CThreadMethod*)pThreadMethod);
#include <iostream>
using namespace std;

class ClassWithThreadMethod {
public:
template <class TMethod, class TParam> class CThreadMethod {
public:
typedef int(__stdcall ClassWithThreadMethod::*IMethod)(TParam);
uintptr_t StartThread(ClassWithThreadMethod* pObj, TMethod fMethod,
TParam& rParam) {
uintptr_t hThread = 0;
if (pObj && fMethod) {
pObject = pObj, fIMethod = (IMethod)fMethod, oParam = rParam;
hThWait = CreateEvent(NULL, TRUE, FALSE, NULL);
hThread = _beginthreadex(NULL, 0, ThreadFunc, this, 0, &hThread);
CloseHandle((WaitForSingleObject(hThWait ,INFINITE), hThWait));
}
return hThread;
}
private:
static unsigned __stdcall ThreadFunc(void* pThreadMethod) {
CThreadMethod TMCopy = *((CThreadMethod*)pThreadMethod);
SetEvent(((CThreadMethod*)pThreadMethod)->hThWait);
return (TMCopy.pObject->*TMCopy.fIMethod)(TMCopy.oParam);
}
IMethod fIMethod;
TParam   oParam;
HANDLE   hThWait;
ClassWithThreadMethod* pObject;
};

template <class TMethod, class TParam>
HANDLE StartThread(TMethod fMethod, TParam& rParam)

{
CThreadMethod<TMethod, TParam> oTMethod;
return (HANDLE)oTMethod.StartThread(this, fMethod, rParam);
}
};


int g_nGlobal=0;

class CMyThread : public ClassWithThreadMethod
{
public:

CMyThread() : m_nNumber(0) { }

struct DualParam {
int nParam1;
int nParam2;
} oParam;

int __stdcall MyThreadMethod(int nParam1, int nParam2)
{
m_nNumber = nParam1 * 1000 + nParam2 + 1;
g_nGlobal = nParam2 * 1000 + nParam1 + 1;
return 0;
}


void TestThreadMethod() {
oParam.nParam1 = 3;
oParam.nParam2 = 9;
HANDLE hThread = StartThread(MyThreadMethod, oParam);
CloseHandle((WaitForSingleObject(hThread,INFINITE), hThread));
}

int m_nNumber;
};

CMyThread MyThread;

int main(int argc, char* argv[])
{
MyThread.TestThreadMethod();
cout << g_nGlobal << " " << MyThread.m_nNumber << endl;
return 0;
}

转自:http://hi.baidu.com/%B8%DF%C9%BD%C1%F7%CB%AE/blog/item/6fa91a4c27c584ffd62afc46.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值