Boost.Asio学习之Tutorial

本文介绍了Boost.Asio的核心概念及编程技巧,包括使用shared_ptr管理Tcp_Connection对象以简化资源管理,序列化异步操作的方法,以及如何在多线程环境中有效使用单个io_service实例。

boost的文档很全,两天时间看完tutorial,熟悉asio编程的基本套路。

所有代码可以参考http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/tutorial.html
或者https://github.com/NearXdu/AsioLearn

有几个注意的地方:

1.shared_ptr来管理Tcp_Connection对象

在tutorial_daytime3中有如下语句

boost::asio::async_write(socket_,boost::asio::buffer(message_),
            boost::bind(&tcp_connection::handle_write,
            shared_from_this(),//ensure the life tiem of the obj
            boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred));

首先shared_from_this()要保证当前的class继承于enable_shared_from_this
shared_ptr使得内存管理变得简单。
通过将shared_ptr绑定到异步操作中,首先保证对象的生命周期可以延长到异步调用结束;并且当io_service析构时,所有的shared_ptr引用将被销毁。

参考:http://stackoverflow.com/questions/3629557/boost-shared-from-this

the boost::asio::io_service destructor documentation explains it fairly well

The destruction sequence described above permits programs to simplify their resource management by using shared_ptr<>. Where an object’s lifetime is tied to the lifetime of a connection (or some other sequence of asynchronous operations), a shared_ptr to the object would be bound into the handlers for all asynchronous operations associated with it. This works as follows:

When a single connection ends, all associated asynchronous operations complete. The corresponding handler objects are destroyed, and all shared_ptr references to the objects are destroyed.
To shut down the whole program, the io_service function stop() is called to terminate any run() calls as soon as possible. The io_service destructor defined above destroys all handlers, causing all shared_ptr references to all connection objects to be destroyed.

Typically your objects will chain asynchronous operations where the handlers are bound to member functions using boost::bind and boost::shared_from_this(). There are some examples that use this concept.

2. 序列化异步操作

详见tutorial_timer5

我们知道io_service是 proactor的抽象,用来调用Asynchronous Event Demultiplexer,以及分派与事件相关的处理程序。

首先,在一个线程中至少有一个io_service对象,并且异步事件的调用是在io_service::run所在的线程,除此之外,我们的程序还可以有如下可能:
1.单线程但io_service对象
2.多线程单io_service对象
3.多线程多io_service对象

当出现多线程单io_service对象时,可以通过strand+wrap使得异步操作序列化,例如:

timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this)));
timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this)));

//其中异步完成回调
    void print1()
    {
        if (count_ < 10)
        {

        //std::cout << "Timer 1: " << count_ << std::endl;
        std::cout<<"Timer 1 "<<"myThreadId is "<<getThreadId()<<std::endl;
        ++count_;

        timer1_.expires_at(timer1_.expires_at() + boost::posix_time::seconds(1));
        //timer1_.async_wait(boost::bind(&printer::print1, this));

        timer1_.async_wait(strand_.wrap(boost::bind(&printer::print1, this)));
        }
    }

    void print2()
    {
        if (count_ < 10)
        {
        //std::cout << "Timer 2: " << count_ << std::endl;

        std::cout<<"Timer 2 "<<"myThreadId is "<<getThreadId()<<std::endl;
        ++count_;

        timer2_.expires_at(timer2_.expires_at() + boost::posix_time::seconds(1));

        //  timer2_.async_wait(boost::bind(&printer::print2, this));
        timer2_.async_wait(strand_.wrap(boost::bind(&printer::print2, this)));
        }
    }

运行程序,将看到,分别在不同线程调用的io_service::run会先完成time1和time2两个异步事件再进入另一个线程:
这里写图片描述

如果不使用会出现如下情况:
这里写图片描述

线程就切来切去了,在boost文档中,用chain这个单词,表示异步操作被串起来依次执行。

3.参考

1.http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/tutorial.html
2.http://blog.youkuaiyun.com/mmoaay/article/details/43759703

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值