asio :: io_service立即结束工作 [英] asio::io_service is ending immediately with work

查看:118
本文介绍了asio :: io_service立即结束工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习io_service并使用共享指针.我希望代码可以无限工作,直到我调用stop方法或类似的东西为止.不幸的是,在屏幕上看到workHandler的输出后,程序关闭了.谁能解释为什么会这样?

I'm trying to learn io_service and work with shared pointers. I want the code to work infinitely until I call stop method or sth like this. Unfortunately after seeing workHandler's output on the screen the program shutdowns. Can anybody explain why this happen?

#include <boost/asio.hpp>
#include <iostream>
#include <atomic>
#include <memory>
#include <thread>
#include <vector>

class Service : public std::enable_shared_from_this<Service> {
    std::shared_ptr<boost::asio::io_service> _service;
    std::shared_ptr<boost::asio::io_service::work> _work;
    std::vector<std::thread> _threads;
    std::atomic<bool> _started{false};

public:
    Service() 
    : _service(std::make_shared<boost::asio::io_service>()),
    _work(std::make_shared<boost::asio::io_service::work>(*_service))
    {}

    void start() { 
        auto self(this->shared_from_this());
        auto startHandler = [this, self]() {
            std::cout << "StartHandler\n";
            while(!_started) _service->run();
        };

        _threads.emplace_back(std::thread(startHandler));
    }

    std::shared_ptr<boost::asio::io_service>& get() { return _service; }
};

class Worker : public std::enable_shared_from_this<Worker> {
    std::shared_ptr<Service> _service;
    std::shared_ptr<boost::asio::io_service> _io_service;

public:
    Worker(const std::shared_ptr<Service>& service)
    : _service(service),
    _io_service(_service->get())
    {}

    void work() {
        auto self(this->shared_from_this());
        auto workHandler = [this, self]() {
            std::cout << "WorkHandler\n";
        };

        _io_service->post(workHandler);
    }
};

int main() {
    auto ser = std::make_shared<Service>();
    ser->start();
    auto worker = std::make_shared<Worker>(ser);
    worker->work();
}

推荐答案

您正在遇到不确定的行为.

You're running into undefined behaviour.

您的处理程序可以捕获指向Service/Work对象的共享指针.但是没有什么可以阻止 main 退出,这将运行退出处理程序并拆除全局库基础结构.这不是你想要的.

Your handlers capture shared pointers to the Service/Work objects alright. But nothing stops main from exiting, which will run exit handlers and tear down global library infrastructure. This is not what you want.

问题是由过度使用共享指针引起的.共享指针仅对共享所有权有利.在您的大多数代码中,没有共享所有权( main 拥有服务!).简化:

The problems are caused by an over-use of shared pointers. Shared pointers are ONLY good for shared ownership. In the majority of your code there is no shared ownership (main owns the Service!). Simplify:

在Coliru上直播

Live On Coliru

#include <boost/asio.hpp>
#include <boost/optional.hpp>
#include <iostream>
#include <memory>
#include <thread>
#include <list>

namespace ba = boost::asio;

class Service {
    ba::io_service _service;
    boost::optional<ba::io_service::work> _work {_service};
    std::list<std::thread> _threads;

public:
    ~Service() {
        _work.reset(); // allow service to complete
        for (auto& thread : _threads)
            if (thread.joinable())
                thread.join();
    }

    void start() { 
        _threads.emplace_back([this] {
            _service.run();
        });
    }

    ba::io_service& get() { return _service; } 
};

class Worker : public std::enable_shared_from_this<Worker> {
    ba::io_service& _io;

public:
    Worker(Service& service) : _io(service.get()) {}

    void work() {
        auto self(shared_from_this());
        auto workHandler = [self]() {
            std::cout << "WorkHandler " << std::endl;
        };

        _io.post(workHandler);
    }
};

int main() {
    Service ser;
    ser.start();

    std::make_shared<Worker>(ser)->work();
}

打印

WorkHandler

但最重要的是:不调用UB并通过加入线程来干净地退出.

But most importantly: doesn't invoke UB and exits cleanly through joining the threads.

这篇关于asio :: io_service立即结束工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆