Возможно ли для pthread вызвать функцию start_routine того же класса? - PullRequest
0 голосов
/ 26 апреля 2020

Например,

class Foo
{
    void assingTask()
    {
        pthread_t myThread;
        int i;

        pthread_create(myThread, NULL, task, (void*) i)

    }

    void * task(void *val)
    {
        //DO Stuff
    }
};

Я продолжаю получать сообщение об ошибке, что «задача» не является функцией c. Все, что я видел в Интернете, упоминает, что есть находка эта . Решения проблем выходят за рамки моего уровня квалификации. Спасибо за помощь.

Ответы [ 2 ]

1 голос
/ 26 апреля 2020

Конечно, это возможно. Поместите свои данные в структуру и оберните их в функцию батута, чтобы перейти к функции вашего класса:

#include <pthread.h>
#include <stdint.h>

class Foo;

// the context passed to trapoline function
struct FooTaskTrampolineCtx {
    Foo *obj;
    void *val;
};

extern "C" void *FooTaskTrampoline(void *ptr);

struct Foo {
    void assingTask() {
        pthread_t myThread;
        int i;
        // note - memory allocated dynamically
        struct FooTaskTrampolineCtx *c = new FooTaskTrampolineCtx;
        c->obj = this;
        c->val = (void*)(uintptr_t)i;
        pthread_create(&myThread, NULL, FooTaskTrampoline, c);
    }

    void * task(void *val) {
        //DO Stuff
    }
};

extern "C" void FooTaskTrampolineCleanup(void *ptr) {
    struct FooTaskTrampolineCtx *c = (struct FooTaskTrampolineCtx *)ptr;
    delete c;
}

// trampolines to task method
extern "C" void *FooTaskTrampoline(void *ptr) {
    struct FooTaskTrampolineCtx *c = (struct FooTaskTrampolineCtx *)ptr;
    void *ret = NULL;
    // remember to pick out the trash the PThread(TM) way
    pthread_cleanup_push(FooTaskTrampolineCleanup, ptr);
    ret = c->obj->task(c->val);
    pthread_cleanup_pop(1);
    return ret;
}
1 голос
/ 26 апреля 2020

Проблема в том, что pthread_create - это функция C, а не C ++, поэтому использование ее из C ++ может быть сложным. Третий аргумент должен быть указателем function , но вы пытаетесь вызвать его с указателем method , что не одно и то же.

C ++ допускает неявное преобразование указателя метода stati c в указатель на функцию, так что вы можете делать с этим все, что хотите (вот почему вы получаете сообщение о том, что 'task' не является stati c - потому что если это так, его можно преобразовать в указатель на функцию и использовать). Обычно вы затем используете 4-й аргумент для хранения «this», поэтому вы можете затем вызывать не-stati c метод из stati c method

class Foo
{
    void assingTask()
    {
        pthread_t myThread;
        int i;

        pthread_create(&myThread, NULL, start_task, this)

    }
    static void *start_task(void *this_) {
        return static_cast<Foo *>(this_)->task();
    }

    void * task()
    {
        //DO Stuff
    }
};

Приведенный выше код имеет проблему, с которой вы " потерять дескриптор pthread_t (не храните его где-либо доступным), поэтому вы не можете присоединиться или отсоединиться от потока, но это можно исправить многими способами.

...