c ++,pthread和静态回调。 “这个”返回指向派生类的基类的指针(第2部分) [英] c++ , pthread and static callbacks. "this" returns a pointer to the base class inctead of the derived one (part 2)
问题描述
此主题已开始,但由于缺乏一个完全良好的例子(为了避免删除所有的问题)它在这里重写。
所以,在下面的例子中, void cppthread :: ThreadedFunc()
被派生为作为一个单独的线程执行。相反,我更喜欢 void ThreadedWrite :: ThreadedFunc()
来执行。我该怎么办? (代码后面还有一些细节)
cppthread.hpp
#ifndef CPPTHREAD_HPP
#define CPPTHREAD_HPP
#include< pthread.h>
using namespace std;
class cppthread
{
public:
cppthread();
virtual〜cppthread();
virtual void threadedFunc();
/// parentObj(即thispte from caller)是
///,以便执行正确的
/// threadedFunc(),即使派生类
///想生成一个线程
int spawn(void * parentObj = NULL);
void terminate();
protected:
pthread_mutex_t mtx ;
bool exitThread;
private:
/ *添加您的私有声明* /
int join();
pthread_t threadId;
};
#endif / * CPPTHREAD_HPP * /
cppthread.cpp
#include< stdio.h>
#include< errno.h>
#include< stdlib.h>
#includecppthread.hpp
void * threadCallback(void * obj);
cppthread :: cppthread()
{
exitThread = false;
pthread_mutex_init(& mtx,NULL);
}
cppthread ::〜cppthread()
{
if(!exitThread)
terminate();
pthread_mutex_destroy(& mtx);
}
void cppthread :: threadedFunc()
{
while(!exitThread)
{
printf(Hello from cppthread: :threadfunc。这不应该运行一次derived和redefined.\\\
);
}
if(exitThread)
{
printf(graceful exit from cppthread :: threadfunc。This should not be run once derived and redefined.\\\
);
}
pthread_exit((void *)0);
}
int cppthread :: spawn(void * parentObj)
{
int ret;
printf(parentObj =%p\\\
,parentObj);
if(parentObj == NULL)
{
ret = pthread_create(& threadId,0,& threadCallback,this);
printf(cppthread_create with \this \\\\
);
}
else
{
ret = pthread_create(& threadId,0,& threadCallback,parentObj);
printf(cppthread_create with parentObj \\\
);
}
if(ret!= 0)
{
printf(cppthread_create error\ n);
exit(EXIT_FAILURE);
}
else
{
// printf(cppthread :: threadID =%lu\\\
,threadId);
}
return ret;
}
void cppthread :: terminate()
{
exitThread = true;
join();
}
int cppthread :: join()
{
int status,ret;
// printf(cppthread :: join_threadID =%lu\\\
,threadId);
ret = pthread_join(threadId,(void **)& status);
if(ret!= 0)
{
printf(cppthread_join error:);
switch(ret)
{
case EDEADLK:printf(deadlock\\\
);打破;
case EINVAL:printf(thread not joinable\\\
);打破;
case ESRCH:printf(threadID not found\\\
);打破;
默认值:printf(unknown error\\\
);打破;
}
}
return status;
}
// ----------------------------------- -----------------------------------
void * threadCallback(void * obj)
{
static_cast< cppthread *>(obj) - > threadedFunc();
returns(0);
} // callback
threadedwrite.hpp
#ifndef THREADEDWRITE_HPP
#define THREADEDWRITE_HPP
#includecppthread.hpp
using namespace std ;
类ThreadedWrite:public cppthread
{
public:
ThreadedWrite(ThreadedWrite * mySelf);
virtual〜ThreadedWrite();
void threadedFunc();
void rrdupdate_thread();
///继承的重要成员:from cppthread
/// int spawn();
/// void terminate();
/// protected
/// pthread_mutex_t mtx;
/// bool exitThread;
private:
ThreadedWrite * instancePtr;
};
#endif / * THREADEDWRITE_HPP * /
threadedwrite.cpp
#include< iostream>
#includethreadedwrite.hpp
ThreadedWrite :: ThreadedWrite(ThreadedWrite * mySelf):instancePtr(mySelf)
{
cout< ; instancePtr =< instancePtr<< endl;
}
ThreadedWrite ::〜ThreadedWrite()
{
}
void ThreadedWrite :: threadedFunc b $ b {
if(!exitThread)
{
cout<< 这是ThreadedWrite :: threadedFunc()运行! << endl;
}
else
{
cout< ThreadedWrite :: threadedFunc必须存在<< endl;
}
pthread_exit((void *)0);
}
void ThreadedWrite :: rrdupdate_thread()
{
cout< 即将产卵< endl;
spawn(instancePtr);
}
main.cpp
#include< iostream>
#includethreadedwrite.hpp
using namespace std;
// -------主体------------------------------- -----------------------
int main(int argc,char * argv [])
{
ThreadedWrite thrrdupd (& thrrdupd);
cout<< hello from main 1<< & thrrdupd<< endl;
thrrdupd.rrdupdate_thread();
cout<< hello from main 2<< & thrrdupd<< endl;
return 0;
}
上面产生的输出 所以执行上面的 您还可以看到我通过instancePtr基础结构)将指向ThreadedWrite实例的指针传递回回调函数。但这也失败了。 此外,最好我想保持cppthread类尽可能一般为了能够使用它在可能的情况下。 注意,如果我从threadedwrite.cpp中删除spawn(instancePtr),并像这样从main.cpp中调用spawn: 我得到的输出是期望的像这样: 您需要等待线程终止 否则你有一个竞争条件: 这可能是5.可能发生在3.之前,在这种情况下你会得到预期的输出。 如果你确保等待线程完成在步骤3.然后它会工作正常。也许你可以在 this thread was started here but due to lack of an altogether good example (and in order to avoid delete all that question) it is re-written here. So, in the following example, the cppthread.hpp cppthread.cpp threadedwrite.hpp threadedwrite.cpp main.cpp The above produces the output (for me): So executing the above You can also see that I tried (through the "instancePtr" infrastructure) to pass a pointer to the instance of "ThreadedWrite" back to the callback function. But this failed too. Also, preferably I would like to keep cppthread class as generic as possible in order to be able to use it in may cases. Mind you, if I remove "spawn(instancePtr)" from threadedwrite.cpp , and call the spawn from main.cpp like this the output that I get Is the expected (and wanted) one and it looks like this:
You need to wait for the thread to terminate before you return from Otherwise you have a race condition: It is possible that 5. might happen before 3., in which case you will get the expected output. If you make sure you wait for the thread to finish at step 3. then it will work fine. Perhaps you could call 这篇关于c ++,pthread和静态回调。 “这个”返回指向派生类的基类的指针(第2部分)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
$ b
instancePtr = 0x7fff39d17860
hello from main 1 0x7fff39d17860
关于spawn
parentObj = 0x7fff39d17860
cppthread_create with parentObj
hello from main 2 0x7fff39d17860
从cppthread :: threadfunc退出。这不应该运行一次派生和重新定义。
cppthread :: spawn()
调用从派生类ThreadedWrite中实际提供了一个this指向 callback()
函数,指向 cppthread :: ThreadedFunc ()
,而不是 ThreadedWrite :: ThreadedFunc()
。
int main(int argc,char * argv [])
{
ThreadedWrite thrrdupd(& thrrdupd);
cout<< hello from main 1<< & thrrdupd<< endl;
thrrdupd.rrdupdate_thread();
thrrdupd.spawn();
cout<< hello from main 2<< & thrrdupd<< endl;
return 0;
}
instancePtr = 0x7ffd24b04ed0
hello from main 1 0x7ffd24b04ed0
要生成
parentObj =(nil)
cppthread_create with this this
hello from main 2 0x7ffd24b04ed0
这是ThreadedWrite :: threadedFunc()运行!
thrrdupd
在你离开 main
〜ThreadedWrite
此时对象不再是 ThreadedWrite
,而是 cppthread
。
〜cppthread
运行并等待线程。
cppthread
, cppthread :: threadedFunc
。
〜ThreadedWrite
里调用 terminate
?void cppthread::ThreadedFunc()
gets spawned to execute as a separate thread . Instead I would prefer void ThreadedWrite::ThreadedFunc()
to be executed. How can I do that? (some more details follow after the code)#ifndef CPPTHREAD_HPP
#define CPPTHREAD_HPP
#include <pthread.h>
using namespace std;
class cppthread
{
public:
cppthread();
virtual ~cppthread();
virtual void threadedFunc();
///parentObj (ie "this" pte from caller") is
///necessary in order to execute the correct
///threadedFunc() even when the derived class
///wants to spawn a thread.
int spawn(void *parentObj = NULL);
void terminate();
protected:
pthread_mutex_t mtx;
bool exitThread;
private:
/* add your private declarations */
int join();
pthread_t threadId;
};
#endif /* CPPTHREAD_HPP */
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include "cppthread.hpp"
void* threadCallback(void* obj);
cppthread::cppthread()
{
exitThread = false;
pthread_mutex_init(&mtx, NULL);
}
cppthread::~cppthread()
{
if (!exitThread)
terminate();
pthread_mutex_destroy(&mtx);
}
void cppthread::threadedFunc()
{
while ( !exitThread )
{
printf("Hello from cppthread::threadfunc. This should not be run once derived and redefined.\n");
}
if (exitThread)
{
printf("graceful exit from cppthread::threadfunc. This should not be run once derived and redefined.\n");
}
pthread_exit((void*)0);
}
int cppthread::spawn(void* parentObj)
{
int ret;
printf("parentObj = %p\n", parentObj);
if (parentObj == NULL)
{
ret = pthread_create(&threadId, 0, &threadCallback, this);
printf("cppthread_create with \"this\" \n");
}
else
{
ret = pthread_create(&threadId, 0, &threadCallback, parentObj);
printf("cppthread_create with parentObj\n");
}
if (ret != 0)
{
printf("cppthread_create error\n");
exit(EXIT_FAILURE);
}
else
{
//printf("cppthread::threadID= %lu\n",threadId);
}
return ret;
}
void cppthread::terminate()
{
exitThread = true;
join();
}
int cppthread::join()
{
int status , ret;
//printf("cppthread::join_threadID= %lu\n",threadId);
ret = pthread_join(threadId,(void**)&status);
if (ret != 0)
{
printf("cppthread_join error: ");
switch (ret)
{
case EDEADLK: printf("deadlock\n"); break;
case EINVAL: printf("thread not joinable\n"); break;
case ESRCH: printf("threadID not found\n"); break;
default : printf("unknown error\n"); break;
}
}
return status;
}
//----------------------------------------------------------------------
void* threadCallback(void* obj)
{
static_cast<cppthread*>(obj)->threadedFunc();
return(0);
} // callback
#ifndef THREADEDWRITE_HPP
#define THREADEDWRITE_HPP
#include "cppthread.hpp"
using namespace std;
class ThreadedWrite : public cppthread
{
public:
ThreadedWrite(ThreadedWrite* mySelf);
virtual ~ThreadedWrite();
void threadedFunc();
void rrdupdate_thread();
///inherited significant members: from cppthread
/// int spawn();
/// void terminate();
///protected
/// pthread_mutex_t mtx;
/// bool exitThread;
private:
ThreadedWrite* instancePtr;
};
#endif /* THREADEDWRITE_HPP */
#include <iostream>
#include "threadedwrite.hpp"
ThreadedWrite::ThreadedWrite(ThreadedWrite* mySelf):instancePtr(mySelf)
{
cout << "instancePtr = " << instancePtr << endl;
}
ThreadedWrite::~ThreadedWrite()
{
}
void ThreadedWrite::threadedFunc()
{
if ( !exitThread )
{
cout << "this is the ThreadedWrite::threadedFunc() running!" << endl;
}
else
{
cout << "ThreadedWrite::threadedFunc must exist now" << endl;
}
pthread_exit((void*)0);
}
void ThreadedWrite::rrdupdate_thread()
{
cout << "about to spawn" << endl;
spawn(instancePtr);
}
#include <iostream>
#include "threadedwrite.hpp"
using namespace std;
//-------main body------------------------------------------------------
int main(int argc, char* argv[])
{
ThreadedWrite thrrdupd(&thrrdupd);
cout << "hello from main 1 " << &thrrdupd << endl;
thrrdupd.rrdupdate_thread();
cout << "hello from main 2 " << &thrrdupd << endl;
return 0;
}
instancePtr = 0x7fff39d17860
hello from main 1 0x7fff39d17860
about to spawn
parentObj = 0x7fff39d17860
cppthread_create with parentObj
hello from main 2 0x7fff39d17860
graceful exit from cppthread::threadfunc. This should not be run once derived and redefined.
cppthread::spawn()
call from within the derived class "ThreadedWrite" , actually provides a "this" pointer to callback()
function that points to cppthread::ThreadedFunc()
, instead of ThreadedWrite::ThreadedFunc()
. int main(int argc, char* argv[])
{
ThreadedWrite thrrdupd(&thrrdupd);
cout << "hello from main 1 " << &thrrdupd << endl;
thrrdupd.rrdupdate_thread();
thrrdupd.spawn();
cout << "hello from main 2 " << &thrrdupd << endl;
return 0;
}
instancePtr = 0x7ffd24b04ed0
hello from main 1 0x7ffd24b04ed0
about to spawn
parentObj = (nil)
cppthread_create with "this"
hello from main 2 0x7ffd24b04ed0
this is the ThreadedWrite::threadedFunc() running!
main
, because that destroys your object.
thrrdupd
starts to be destoyed as you leave main
.~ThreadedWrite
runs; at this point the object is no longer a ThreadedWrite
but a cppthread
.~cppthread
runs and waits for the thread.cppthread
, cppthread::threadedFunc
is called.terminate
inside ~ThreadedWrite
?