C++,pthread和静态回调。 "this" 返回一个指针,指向派生的基类(第 2 部分)

c++ , pthread and static callbacks. "this" returns a pointer to the base class inctead of the derived one (part 2)

本文关键字:指针 派生 部分 基类 一个 静态 pthread 回调 C++ 返回 this      更新时间:2023-10-16

这个线程是从这里开始的,但由于缺乏一个完全好的例子(为了避免删除所有这些问题),它在这里重新编写。

因此,在下面的示例中,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 (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 */ 

cppthread.cpp

#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 = %pn", 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 parentObjn");
    }
    if (ret != 0)
    {
        printf("cppthread_create errorn");
        exit(EXIT_FAILURE);
    }
    else
    {
        //printf("cppthread::threadID= %lun",threadId);
    }
    return ret;
}
void cppthread::terminate()
{
    exitThread = true;
    join();
}
int cppthread::join()
{
    int status , ret;
    //printf("cppthread::join_threadID= %lun",threadId);
    ret = pthread_join(threadId,(void**)&status);
    if (ret != 0)
    {
        printf("cppthread_join error: ");
        switch (ret)
        {
            case EDEADLK: printf("deadlockn"); break;
            case EINVAL: printf("thread not joinablen"); break;
            case ESRCH: printf("threadID not foundn"); break;
            default : printf("unknown errorn"); break;
        }
    }
    return status;
}
//----------------------------------------------------------------------
void* threadCallback(void* obj)
{
    static_cast<cppthread*>(obj)->threadedFunc();
    return(0);
} // callback

线程写入.hpp

#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 */ 

线程写入.cpp

#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);
}

main.cpp

#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.

因此,从派生类"ThreadedWrite"中执行上述cppthread::spawn()调用,实际上提供了一个指向callback()函数的"this"指针,该指针指向cppthread::ThreadedFunc(),而不是ThreadedWrite::ThreadedFunc()

您还可以看到,我尝试(通过"instancePtr"基础结构)将指向"ThreadWrite"实例的指针传递回回调函数。但这也失败了。

此外,我最好尽可能保持cppthread类的通用性,以便在可能的情况下使用它。

请注意,如果我从threadwrite.cpp中删除"spawn(instancePtr)",并像下面这样从main.cpp调用spawn

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返回之前,您需要等待线程终止,因为这会破坏您的对象。

否则,您将面临比赛条件:

  1. 线程已启动
  2. 当您离开main时,thrrdupd开始被破坏
  3. CCD_ 10运行;此时对象不再是CCD_ 11而是CCD_
  4. ~cppthread运行并等待线程
  5. 线程调用回调,因为对象现在具有动态类型cppthread,所以调用cppthread::threadedFunc

5。可能发生在3.之前,在这种情况下,您将获得预期的输出。

如果您确保在步骤3等待线程完成。那么它就会正常工作。也许您可以在~ThreadedWrite内部呼叫terminate