san*_*ank 4 c++ concurrency boost boost-asio
我正在学习使用Boost ASIO.以下是从Boost ASIO文档中提供的聊天示例中复制的一些代码,
typedef std::deque<chat_message> chat_message_queue;
class chat_client
{
public:
chat_client(boost::asio::io_service& io_service,
tcp::resolver::iterator endpoint_iterator)
: io_service_(io_service),
socket_(io_service)
{
boost::asio::async_connect(socket_, endpoint_iterator,
boost::bind(&chat_client::handle_connect, this,
boost::asio::placeholders::error));
}
void write(const chat_message& msg)
{
io_service_.post(boost::bind(&chat_client::do_write, this, msg));
}
void close()
{
io_service_.post(boost::bind(&chat_client::do_close, this));
}
private:
void handle_connect(const boost::system::error_code& error)
{
//Implementation
}
void handle_read_header(const boost::system::error_code& error)
{
//Implementation
}
void handle_read_body(const boost::system::error_code& error)
{
//Implementation
}
void do_write(chat_message msg)
{
bool write_in_progress = !write_msgs_.empty();
write_msgs_.push_back(msg);
if (!write_in_progress)
{
boost::asio::async_write(socket_,
boost::asio::buffer(write_msgs_.front().data(),
write_msgs_.front().length()),
boost::bind(&chat_client::handle_write, this,
boost::asio::placeholders::error));
}
}
void handle_write(const boost::system::error_code& error)
{
//Implementation
}
void do_close()
{
socket_.close();
}
private:
boost::asio::io_service& io_service_;
tcp::socket socket_;
chat_message read_msg_;
chat_message_queue write_msgs_;
};
Run Code Online (Sandbox Code Playgroud)
写操作是异步的,并且没有使用锁周围的成员变量write_msgs_
和read_msgs_
.这里不应该存在并发问题吗?
它是安全的拨打电话,以post
从运行线程io_service::run?
怎么样dispatch
?如何从未运行的线程进行相同的调用io_service::run
?
在doSend()
,他们为什么要推送消息write_msgs_
而不是直接发送消息?同样在同一个函数中,为什么他们检查是否write_msgs_
为空,只有当它不是时,继续发送?是否write_msgs_.empty() = false
意味着写入正在进行?怎么样?
如果do_write()
仅在一个线程中调用,那么为什么我需要一个队列来维护一系列发送?难道不能io_service
完成手头的任务然后执行所谓的异步操作do_write
吗?在上面提到的例子中使用a dispatch
而不是post
有所作为吗?
虽然写入是异步的,但这里没有多线程:do_write()
在一个线程中调用.当然,发送的缓冲区必须是活动的并且保持不变,直到调用完成处理程序.
从任何线程调用post()和dispatch()都是安全的.阅读io_service文档的 "线程安全"部分.
如果async_write
正在进行,并且async_write
再次调用同一个套接字,则数据的发送顺序是未定义的.换句话说,数据将被搞砸.解决这个问题的最简单方法是建立一个消息队列:每次async_write
完成,发出另一个消息async_write
.(顺便说一下,同样适用于async_read
.)为什么write_msgs_.empty() = false
意味着写入正在进行?因为只要write_msgs_
是非空的,handle_write
(前一个的完成处理程序async_write
)就会发出另一个问题async_write
.write_msgs_
空循环时此循环中断.
此操作是根据对流的async_write_some函数的零次或多次调用实现的,并且称为组合操作.程序必须确保流不执行任何其他写操作(例如async_write,流的async_write_some函数或执行写入的任何其他组合操作),直到此操作完成.
至于dispatch
vs post
- 据我所知,在上面的例子中,它们是可以互换的.如果我们不希望同步调用发布的仿函数,则使用post是必不可少的.
归档时间: |
|
查看次数: |
2494 次 |
最近记录: |