Запустите поток, используя указатель метода - PullRequest
3 голосов
/ 21 декабря 2010

Я пытаюсь разработать абстракцию потока (поток POSIX и поток из Windows API), и мне бы очень хотелось, чтобы он мог запускать их с указателем метода, а не указателем функции.

То, что я хотел бы сделать, - это абстракция потока, являющегося классом с чисто виртуальным методом runThread, который будет внедрен в будущий класс с многопоточностью.

Я пока не знаю о потоке Windows, но чтобы запустить поток POSIX, вам нужен указатель на функцию, а не указатель на метод. И мне не удается найти способ связать метод с экземпляром, чтобы он мог работать как функция. Я, вероятно, просто не могу найти ключевые слова (и я много искал), я думаю, что это в значительной степени то, что делает Boost :: Bind (), поэтому оно должно существовать.

Вы можете мне помочь?

Ответы [ 4 ]

9 голосов
/ 21 декабря 2010

Не делай этого.Используйте boost::thread.

С помощью boost::thread вы можете запускать темы с любым функтором подписи void(), поэтому вы можете использовать std::mem_fun и std::bind1st, как в

struct MyAwesomeThread
{
    void operator()()
    {
        // Do something with the data
    }

    // Add constructors, and perhaps a way to get
    // a result back

private:
    // some data here
};

MyAwesomeThread t(parameters)
boost::thread(std::bind1st(std::mem_fun_ref(&t::operator()), t));

РЕДАКТИРОВАТЬ: Если вы действительно хотите абстрагировать потоки POSIX (это не сложно), вы можете сделать (я оставляю вам инициализацию pthread_attr)

class thread
{
    virtual void run() = 0; // private method

    static void run_thread_(void* ptr)
    {
        reinterpret_cast<thread*>(ptr)->run();
    }

    pthread_t thread_;
    pthread_attr_t attr_;

public:
    void launch() 
    {
        pthread_create(&thread_, &attr_, &::run_thread_, reinterpret_cast<void*>(this));
    }
};

, но boost::thread является переносимым, гибким ипрост в использовании.

2 голосов
/ 21 декабря 2010

Вы действительно должны использовать Boost.Thread.Но если вы не можете, и вызов для запуска потока позволяет передать параметр в вашу функцию потока, общая идиома состоит в том, чтобы иметь автономную или статическую функцию-член, которая приводит параметр к указателю объекта.например,

class Thread {
public:
  void start() { start_thread(_work, this); }  // whatever call starts a thread

  void work() {} // does thread work

private:
  static void _work(void* param) {
    (reinterpret_cast<Thread*>(param))->work();
  }
}
1 голос
/ 21 декабря 2010

Вам нужен C ++ API для работы с потоками.Что-то вроде boost :: thread (это почти тот же API, который будет в новом C ++).API потоков ОС обычно находятся на C, и вы просто НЕ МОЖЕТЕ передавать им нестатические указатели на функции-члены или функторы (именно это создает boost :: bind).

0 голосов
/ 22 декабря 2010

Ну, на самом деле это упражнение, и я не имею права использовать что-либо (даже Boost).Конечно, я НЕ ДОЛЖЕН делать это таким образом (мне нужно только разработать абстракцию потока), я просто хотел бы: я однажды использовал абстракцию потока SFML, и мне просто понравилось.Это такой сексуальный способ справиться с этим.

Ферруччо, кажется, хорошо!Если метод work () является чисто виртуальным, он может быть реализован в любом классе, реализующем абстракцию потока ... и он будет работать просто отлично, верно?(Я не совсем уверен, что так и будет, но, исходя из моих базовых знаний C ++, думаю, что так и должно быть?)

...