Подтвердить что ты не робот

Использование boost-потока и нестатической функции класса

Итак, я провел некоторое исследование и обнаружил, что вы можете создать объект boost:: thread и начать с нестатической функции класса с помощью "this" и boost:: bind и т.д. Это действительно не имеют для меня большой смысл, и все примеры, которые я смог найти, имели объект boost:: thread, запущенный в том же классе, что и функция, с которой он начинался, поэтому это можно было бы использовать. Тем не менее, я запускаю поток в другом классе, поэтому, боюсь, используя "this", я буду говорить, что "this" - это класс, из которого я создаю поток, а не тот, в котором находится функция ( Вероятно, я ошибаюсь, мне нужно узнать больше об этом парне "this"). Вот пример моего источника, с которым я столкнулся.

ANNGUI.h

class ANNGUI
{
private:
    boost::thread *GUIThread;
    Main *GUIMain;
public:
    // Creates the entire GUI and all sub-parts.
    int CreateGUI();
}

ANNGUI.cpp

int ANNGUI::CreateGUI()
{
        GUIMain = new Main();
    GUIThread = new boost::thread(GUIMain->MainThreadFunc);
};

Это не весь источник, но я думаю, что моя проблема здесь где-то, я знаю, что мне приходится иметь дело с "this", но я не уверен, как это сделать. Я мог бы использовать статическую функцию, но я действительно не хотел, чтобы мои переменные были статическими. Спасибо.

Кроме того, есть ли какой-либо очень хороший ресурс для использования каких-либо ускорительных библиотек? Их документация на веб-сайте кажется хорошей, но над моей головой.

4b9b3361

Ответ 1

Ключевое слово this используется с boost::bind, когда объект функции, который вы создаете, привязан к функции-члену объекта. Функции-члены не могут существовать отдельно от экземпляров, поэтому при создании объекта-функтора из функции-члена с помощью boost::bind вам нужен указатель на экземпляр. Именно это и есть ключевое слово this. Если вы используете ключевое слово this внутри функции-члена класса, то вы получаете указатель на текущий экземпляр этого класса.

Если вы должны были вызвать bind извне функции класса, вы можете сказать что-то вроде:

int main()
{
  Foo f;
  boost::thread* thr = new boost::thread(boost::bind(&Foo::some_function, &f));
}

Здесь мы используем Foo:: some_function как нашу функцию потока. Но мы не можем использовать this, потому что мы вызываем bind из main. Но то же самое можно было бы сделать, используя this, если бы мы вызвали bind изнутри функции-члена Foo, например:

void Foo::func1()
{
  boost::thread* thr = new boost::thread(boost::bind(&Foo::some_function, this));
}

Если функция-член является статической или просто является регулярной (не-членной) функцией, вам вообще не нужен указатель экземпляра. Вы просто сделали бы:

boost::thread* thr = new boost::thread(some_regular_function);

Ответ 2

Как уже упоминалось, когда вы хотите вызвать метод объекта в новом потоке, вы должны указать адрес этого объекта. Но вам не нужно вызывать boost::bind, вы можете использовать перегруженный конструктор boost::thread следующим образом:

GUIThread = new boost::thread(&Main::MainThreadFunc, GUIMain);

Если метод находится в том же классе, вы используете this для получения адреса текущего экземпляра, например:

t = new boost::thread(&myclass::compute, this);

Если у метода есть параметры, вы можете указать их после второго аргумента, например:

t = new boost::thread(&myclass::compute, this, p1, p2);

Ответ 3

boost:: bind - ваш друг (иногда это может быть грубый способ показать его)!

использовать GUIThread = new boost::thread(boost::bind(&Main::MainThreadFunc, GUIMain));

а затем сделайте свой MainThreadFunc регулярным членом. Это означает, что вы можете использовать переменные экземпляра напрямую, как обычно.

Что-то вроде этого:

class GUIMain {
public:
  GUIMain() : m_Member(42) {}

  void MainThreadFunc() {
    // use all members as you would normally do
    std::cout << m_Member << std::endl;
  }

private:
  int m_Member;
};

Ответ 4

В таких случаях полезно рассматривать нестатические функции-члены как свободные функции, которые принимают this как первый параметр, например, в вашем случае void MainThreadFunc(Main* this).

boost::thread принимает нулевой функтор, поэтому вам нужно передать ему нулевой функтор, который содержит ссылку на экземпляр GUIMain и вызывает GUIMain->MainThreadFunc, который, как я объяснил выше, будет чем-то вроде MainThreadFunc(GUIMain),

Boost (и теперь также С++ с TR1) предоставляет помощники для создания таких функторов, а именно boost::bind (или, альтернативно, boost::lambda::bind). Выражение boost::bind(f, arg1, arg2, ...) означает "возвращает нулевой функтор, который вызывает f(arg1, arg2, ...)".

Тем не менее, вы можете использовать следующее выражение для создания потока:

GUIThread = new boost::thread(boost::bind(&Main::MainThreadFunc, GUIMain))

Ответ 5

Если ваш объект является функтором, то есть имеет operator(), вы можете передать его экземпляр boost::thread. operator() не обязательно должен быть статичным. Например:

#include <boost/thread.hpp>

struct th {
    void operator()();
};

void th::operator()()
{
    for (;;) {
        // stuff
    }
}

int main()
{
    th t;
    boost::thread my_thread( t ); // takes a copy of t !
    my_thread.join(); // blocks
    return 0;
}