4

我试图理解 boost::asio 但有一些问题。在这个例子中,如果我错了,请纠正我。

  1. 消息通过引用 write() 方法和值给 do_write() 给出。所以我认为这没问题,即使 do_write 是由 io_service.post 完成的,boost::bind 也是按值绑定消息的。

  2. 但是为什么write_msgs_队列没有互斥锁,因为 std::deque 可能会移动或复制其元素,如果需要并且 io_service::run 有它自己的线程,则不能确保数据是一致的。

  3. 用指针来做不是更好吗?如果消息太长,则必须始终按值复制。但是使用 new 和 delete 它们将在发送之前创建并在发送之后删除。然后我会像这样发送

代码

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));
4

1 回答 1

5

1) 是正确的以及 2) 有效的原因。

您在这里不需要互斥锁,因为主线程和客户端处理程序线程之间的同步是通过该io_service::post方法完成的。post实际上并没有执行任何操作,而是将回调(绑定方法)添加到回调处理程序,回调处理程序是执行的线程,io_service::run并且 std::deque 只能由运行的一个线程访问io_service::run

3) 这是线程安全、异常安全和所有权的问题。

关于线程安全,您需要 100% 确保在调用后write只有一个线程会访问指针指向的字符串。
所有权和异常安全是这里更有趣的一点。如果您只想在双端队列中存储普通指针,则会遇到异常安全问题,因为在抛出异常的情况下,您的字符串将不再被删除。为了规避这个问题,您需要一个智能指针(例如:std::unique_ptr),这需要 C++11 移动语义或 shared_ptr,这会增加引用计数的额外开销。最干净的解决方案是将 C++11 移动语义与纯字符串结合使用。您可以将缓冲区移动到写入函数并进一步移动到处理程序中,并具有无复制和异常安全的额外好处。
谈论性能和复制之前的另一点是,您应该衡量这是否真的是一个问题,并且您是否没有受到网络 I/O 等不同事物的瓶颈。

于 2013-03-19T11:49:37.373 回答