Вопрос

Недавно я разрабатывал библиотеку классов Thread, я создал абстрактный класс Thread, подобный следующему:

class Thread {
public:
    run() { /*start the thread*/ }
    kill() { /*stop the thread*/ }
protected:
    virtual int doOperation(unsigned int, void *) = 0;
};

Классы реальных потоков унаследовали бы этот абстрактный класс и реализовали doOperation метод по своей собственной логике, что-то похожее на Шаблон стратегии.

Проблема в том, что я полагаюсь на серверную библиотеку C, которая определяет запуск потока в следующей функции:

int startThread(char* name, (int)(*)(unsigned int, void*), int, int, int, void*);

Как вы можете видеть;второй параметр - это указатель функции на цикл потока (основная функция), и вот в чем проблема;поскольку я использую эту C-функцию для запуска потока в run метод, я передаю адрес doOperation ко второму параметру, и это невозможно сделать из-за несоответствия типов.

Я пытался использовать reinterpret_cast чтобы вернуть указатель, но I ISO-C ++ запрещает возвращать указатель на неинициализированный элемент функции.Я не знаю, как преодолеть этот конфликт, использование статического метода - единственное решение, я думаю, но это разрушает мой шаблон проектирования!

Это было полезно?

Решение

Во-первых, обязательно прочтите ссылку, предоставленную Майклом Берром, поскольку она содержит полезную информацию.Тогда вот псевдокод на C ++ для этого:

int wrapperDoOperation(int v, void *ctx)
{
    Thread *thread = (Thread *)ctx;
    return thread->doOperation(v);
}

class Thread {
public:
    run() {
         startThread("bla", wrapperDoOperation, bla, bla, bla, (void *)this);
    }
    kill() { /*stop the thread*/ }
protected:
    virtual int doOperation(unsigned int) = 0;

friend wrapperDoOperation ......;
};

Идея заключается в том, что doOperation, будучи функцией-членом Thread, не нуждается в контексте void *, вы можете просто сохранить все, что вы передали бы в качестве контекста в самом объекте.Следовательно, вы можете использовать указатель void для передачи фактического значения этого указателя в doOperation.Обратите внимание, что сведения о void * скрыты от пользователей вашего класса, что приятно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top