Создание потока, привязанного к io_service внутри структуры - PullRequest
1 голос
/ 20 апреля 2020

Я пытаюсь создать простую структуру, которая содержит объект boost :: thread. Конструктор этой структуры (ApplicationPair) требует передачи ссылочного объекта io_service и метода; сейчас я использую метод void без параметров, для простоты. После этого поток создается с помощью boost :: bind.

ApplicationPair.h

#ifndef APPLICATIONPAIR_H
#define APPLICATIONPAIR_H

#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <cstdarg>

template<typename T>
struct ApplicationPair
{
    ApplicationPair(boost::asio::io_service& iSvc, boost::function<T()> func ) : _func(func)
    {
        iSvc.post(boost::bind(&ApplicationPair<T>::run, this));
        thr = boost::thread(boost::bind(&boost::asio::io_service::run, &iSvc));
    }
    ApplicationPair() = delete;
    ~ApplicationPair() { if (thr.joinable()) thr.join(); }

    void run(); 
    boost::thread thr;
    boost::function<T()> _func;
};

#endif

Идея заключается в том, что каждый новый объект ApplicationPair, который я создаю, будет иметь свой собственный поток на io_service и запустит любой метод, который я захочу при создании экземпляра.

Вот основной:

main. cpp

#include <boost/date_time/posix_time/posix_time.hpp>
#include <iostream>
#include <cstdio>

boost::asio::io_service iSvc;

void HelloWorld()
{
    std::cout << "HelloWorld\n";
}

template<typename T>
void ApplicationPair<T>::run()
{
    this->_func();
}
int main()
{
    ApplicationPair<void> p1(boost::ref(iSvc), HelloWorld);
    ApplicationPair<void> p2(boost::ref(iSvc), HelloWorld);
    ApplicationPair<void> p3(boost::ref(iSvc), HelloWorld);
    return 0;
} 

И вот тут я понимаю, что дела идут ужасно: мой ожидаемый результат будет 3 отпечатка «HelloWorld», однако я получаю только 2. Что еще более странно, что если я запусту отладку и продолжу дальнейшие инструкции по инструкции, HelloWorld напечатано только один раз!

Честно говоря, я ничего не понимаю, но мне ясно, что я не до конца понимаю, как работают многопоточность и io_services, а документация на Boost.org ВСЕ не помогает.

1 Ответ

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

Как вы и подозревали, вы упускаете некоторые ключевые моменты в ASIO.

Вы заявляете, что хотите, чтобы каждая ApplicationPair имела свой собственный поток на io_service. Это не совсем так. После вызова io_service.run () в потоке этот поток теперь принадлежит io_service. Io_service будет планировать события так, как считает нужным.

Думайте об этом больше как о пуле потоков, вы отправляете задачу в io_service, и он планирует их в пуле.

Кроме того, вы должны посмотреть на берегах. Это как ASIO-версия мьютекса. Он работает аналогично, но концептуально отличается. boost :: asio strand example

Это может показаться не важным здесь, потому что вы не читаете или не пишете из переменных, однако std :: cout глобальный ресурс, которым вы должны управлять.

Я пытался переделать ваш код, чтобы дать вам пример, но эти различия значительно изменят его. И я не совсем уверен, какова ваша конечная цель, поэтому трудно привести пример.

Также вот несколько хороших видео на YouTube: asio :: strand основы asio

...