crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Помогите понять boost::thread
igor_bogomolov
  опции профиля:
сообщение 27.7.2009, 22:58
Сообщение #1


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


Всем привет.
Начал потихоньку осваивать boost. Возникло несколько вопросов.

Имею примерно такой код
MSK.h
#include <boost/thread/thread.hpp>

class MSK {
public:
    MSK();
protected:
    static void RoutinePnP();
private:
    boost::thread _pnpthread;
};
MSK.cpp
#include <iostream>
#include <boost/thread/xtime.hpp>

MSK::MSK()
{
    _pnpthread = boost::thread(&RoutinePnP);
}

void MSK::RoutinePnP()
{
    for(;;) {
        std::cout << "PnP run..." << std::endl;

        // приостанавливаем поток на 10 секунд
        boost::xtime xt;
        boost::xtime_get(&xt, boost::TIME_UTC);
        xt.sec += 10;
        boost::thread::sleep(xt);
    }
}
main

int main()
{
    MSK msk;

    std::cout << "message1" << std::endl;
    std::cout << "message2" << std::endl;
    std::cout << "message3" << std::endl;
    std::cout << "message4" << std::endl;

    while(1) sleep(1);
    return EXIT_FAILURE;
}



В результате получаю:
Цитата
PnP run...
message1 \
message2 | Эти сообщения я получаю только через 10 секунд
message3 | т.е. основной поток получается заблоктрованным
message4 /
PnP run...
PnP run...
PnP run...
PnP run...
и т.д....



1) Где и что я делаю не правильно. Почему блокируется основной поток? Или это просто доступ к самой консоли блокируется?
2) Как нормально приостановить поток средствами boost, не привязываясь к системному времени.
3) Что делать если RoutinePnP у меня не может быть статической? Есть ли возможность передать в поток не статический метод класса? Или тут единственный вариант - создавать глобальный метод и делать его дружественным для класса MSK?
--------------------------------------------
4) (не по теме) Где то читал что в boost есть аналог Q_PROPERTY(...), что то не могу найти. (((
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Andrew Selivanov
  опции профиля:
сообщение 28.7.2009, 15:44
Сообщение #2


Участник
**

Группа: Участник
Сообщений: 249
Регистрация: 9.10.2007
Из: Москва
Пользователь №: 3

Спасибо сказали: 15 раз(а)




Репутация:   6  


Я бы рекомендовал для начала изучить неплохие примеры из Thread: C:\boost\boost_1_37_0\libs\thread\example\

На третий вопрос отвечу кодом из примера про голодных философов (starvephil.cpp):
class thread_adapter
{
public:
    thread_adapter(void (*func)(void*), void* param)
        : _func(func), _param(param)
    {
    }
    void operator()() const { _func(_param); }
private:
    void (*_func)(void*);
    void* _param;
};


Привязываем потоки к конкретным объектам через thread_adapter и делаем join (join грубо говоря обозначает не убивать этот поток пока не завершаться присоединённые к нему потоки, у тебя эту роль играет вечный sleep())
    phil p[] = { phil(0), phil(1), phil(2), phil(3), phil(4) };
    boost::thread thrd_phil0(thread_adapter(&phil::do_thread, &p[0]));
    boost::thread thrd_phil1(thread_adapter(&phil::do_thread, &p[1]));
    boost::thread thrd_phil2(thread_adapter(&phil::do_thread, &p[2]));
    boost::thread thrd_phil3(thread_adapter(&phil::do_thread, &p[3]));
    boost::thread thrd_phil4(thread_adapter(&phil::do_thread, &p[4]));


    thrd_phil0.join();
    thrd_phil1.join();
    thrd_phil2.join();
    thrd_phil3.join();
    thrd_phil4.join();


Цитата
2) Как нормально приостановить поток средствами boost, не привязываясь к системному времени.

Насколько я помню никак

Цитата
1) Где и что я делаю не правильно. Почему блокируется основной поток? Или это просто доступ к самой консоли блокируется?


MinGW 3.4.5/Boost 1.37
Ничего нигде не блокируется.
Я обычно что то в этом духе делаю:
#include <iostream>
#include <boost/thread/xtime.hpp>
#include <boost/thread/thread.hpp>

//для SetConsoleCtrlHandler ...
#include <windows.h>

class MSK {
public:
    MSK() : is_running(false)
    {

    }

    void run()
    {
        is_running = true;
        while(is_running)
        {
            std::cout << "PnP run...\n";

            // приостанавливаем поток на 10 секунд
            boost::xtime xt;
            boost::xtime_get(&xt, boost::TIME_UTC);
            xt.sec += 10;
            boost::thread::sleep(xt);
        }
        std::cout << "[run] ok\n";
    }

    void stop()
    {
        is_running = false;
    }

    static void do_thread(void* param)
    {
        static_cast<MSK*>(param)->run();
    }

private:
    bool is_running;
};

class thread_adapter
{
public:
    thread_adapter(void (*func)(void*), void* param)
        : _func(func), _param(param)
    {
    }
    void operator()() const { _func(_param); }
private:
    void (*_func)(void*);
    void* _param;
};

MSK msk;

BOOL WINAPI stop_handler(DWORD ctrl_type)
{
    switch (ctrl_type)
    {
    case CTRL_C_EVENT:
    case CTRL_BREAK_EVENT:
    case CTRL_CLOSE_EVENT:
    case CTRL_SHUTDOWN_EVENT:
        std::cout << "waiting to stop...\n";
        msk.stop();
        return TRUE;
    default:
        return FALSE;
    }
}

int main()
{
    std::cout << "[start]\n";

    boost::thread msk_thrd(thread_adapter(&MSK::do_thread, &msk));

    SetConsoleCtrlHandler(&stop_handler, TRUE);

    msk_thrd.join();

    std::cout << "[stop]\n";

    return 0;
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Гость_true_goth_*
сообщение 20.3.2010, 10:51
Сообщение #3





Гости








    


Цитата(igor_bogomolov @ 27.7.2009, 22:58) *
Всем привет.
Начал потихоньку осваивать boost. Возникло несколько вопросов.

Имею примерно такой код
MSK.h
#include <boost/thread/thread.hpp>

class MSK {
public:
    MSK();
protected:
    static void RoutinePnP();
private:
    boost::thread _pnpthread;
};
MSK.cpp
#include <iostream>
#include <boost/thread/xtime.hpp>

MSK::MSK()
{
    _pnpthread = boost::thread(&RoutinePnP);
}

void MSK::RoutinePnP()
{
    for(;;) {
        std::cout << "PnP run..." << std::endl;

        // приостанавливаем поток на 10 секунд
        boost::xtime xt;
        boost::xtime_get(&xt, boost::TIME_UTC);
        xt.sec += 10;
        boost::thread::sleep(xt);
    }
}
main

int main()
{
    MSK msk;

    std::cout << "message1" << std::endl;
    std::cout << "message2" << std::endl;
    std::cout << "message3" << std::endl;
    std::cout << "message4" << std::endl;

    while(1) sleep(1);
    return EXIT_FAILURE;
}



В результате получаю:
Цитата
PnP run...
message1 \
message2 | Эти сообщения я получаю только через 10 секунд
message3 | т.е. основной поток получается заблоктрованным
message4 /
PnP run...
PnP run...
PnP run...
PnP run...
и т.д....



1) Где и что я делаю не правильно. Почему блокируется основной поток? Или это просто доступ к самой консоли блокируется?
2) Как нормально приостановить поток средствами boost, не привязываясь к системному времени.
3) Что делать если RoutinePnP у меня не может быть статической? Есть ли возможность передать в поток не статический метод класса? Или тут единственный вариант - создавать глобальный метод и делать его дружественным для класса MSK?
--------------------------------------------
4) (не по теме) Где то читал что в boost есть аналог Q_PROPERTY(...), что то не могу найти. (((


нужный код найдешь тут, безо всяких тридадаптеров, у буст есть спецовая boost::bind для таких целей, мне очень пригодилась
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 20.3.2010, 17:53
Сообщение #4


Профессионал
*****

Группа: Модератор
Сообщений: 1594
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 219 раз(а)




Репутация:   12  


во-первых, в какой системе работаешь и какой компилятор?
далее, по пунктам:
1. это неноральное поведение, поток никак не может блокироаться в данном случае. 37-й буст - довольно старая версия. возможно, потоки были доработаны с тех пор. хотя я не сталкивалась с подобным глюком, но это может оказаться глюком библиотеки. возьми для начала новый буст.
также обязательно проверь, что компилишь проект с опциями мультипоточности (это важно, буст может работать неправильно, если эти опции не включены).

2. что значит "не привязываясь к системному времени? this_thread::sleep принимает и абсолютное, и относительное время. это перегруженная функция и можно скармливать ему и абсолютно время, и интервалы в формате posix_time::seconds, posix_time::microseconds, и т.д., в зависимости от возможностей твоей системы и макросов, которые ты указал для сборки.

3. создавай функтор с оператором operator() и передавай его. а в нём юзай что хочешь.

Сообщение отредактировал Iron Bug - 20.3.2010, 17:54
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
igor_bogomolov
  опции профиля:
сообщение 21.3.2010, 3:02
Сообщение #5


Профессионал
*****

Группа: Сомодератор
Сообщений: 1215
Регистрация: 22.3.2009
Из: Саратов
Пользователь №: 630

Спасибо сказали: 235 раз(а)




Репутация:   29  


Iron Bug, спасибо за помощь, но тема достаточно устарела и ответы я давно получил )
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Iron Bug
  опции профиля:
сообщение 21.3.2010, 8:21
Сообщение #6


Профессионал
*****

Группа: Модератор
Сообщений: 1594
Регистрация: 6.2.2009
Из: Yekaterinburg
Пользователь №: 533

Спасибо сказали: 219 раз(а)




Репутация:   12  


а, не заметила даты. просто последний ответ был вчера. поэтому подумала, что тема новая. ну ладно, пусть будет.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 6.4.2020, 8:26