当前位置:  开发笔记 > 编程语言 > 正文

c ++,pthread和静态回调."this"返回指向基类的指针而不是派生类(第2部分)

如何解决《c++,pthread和静态回调."this"返回指向基类的指针而不是派生类(第2部分)》经验,为你挑选了1个好方法。

这个线程是在这里开始的,但是由于缺乏一个完整的好例子(并且为了避免删除所有那个问题),这里重写了它.

因此,在以下示例中,void cppthread::ThreadedFunc()生成的gets作为单独的线程执行.相反,我宁愿void ThreadedWrite::ThreadedFunc()被执行.我怎样才能做到这一点?(代码后面还有一些细节)

cppthread.hpp

#ifndef CPPTHREAD_HPP
#define CPPTHREAD_HPP

#include 

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

#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(obj)->threadedFunc();
    return(0);
} // callback

threadedwrite.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 */ 

threadedwrite.cpp

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

#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()从派生类"ThreadedWrite"中执行上述调用,实际上提供了一个"this"指向指向的callback()函数cppthread::ThreadedFunc(),而不是ThreadedWrite::ThreadedFunc().

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

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

请注意,如果我从threadedwrite.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!

Alan Stokes.. 5

在返回之前,您需要等待线程终止main,因为这会破坏您的对象.

否则你有竞争条件:

    线程已启动.

    thrrdupd当你离开时,你开始生气main.

    ~ThreadedWrite运行; 在这一点上,对象不再是一个ThreadedWrite而是一个cppthread.

    ~cppthread 运行并等待线程.

    该线程调用回调,因为该对象现在具有动态类型cppthread,因此cppthread::threadedFunc被调用.

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

如果您确保等待线程在步骤3完成,那么它将正常工作.也许你可以terminate在里面打电话~ThreadedWrite



1> Alan Stokes..:

在返回之前,您需要等待线程终止main,因为这会破坏您的对象.

否则你有竞争条件:

    线程已启动.

    thrrdupd当你离开时,你开始生气main.

    ~ThreadedWrite运行; 在这一点上,对象不再是一个ThreadedWrite而是一个cppthread.

    ~cppthread 运行并等待线程.

    该线程调用回调,因为该对象现在具有动态类型cppthread,因此cppthread::threadedFunc被调用.

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

如果您确保等待线程在步骤3完成,那么它将正常工作.也许你可以terminate在里面打电话~ThreadedWrite

推荐阅读
农大军乐团_697
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有