答案#1:
锁定是一种可行的方法是正确的,但是有一种更简单的方法可以完成所有这些工作。Boost 在 ASIO 中有一个不错的小结构,称为strand
. 任何使用 strand 包装的回调都将被序列化,保证,无论哪个线程执行回调。基本上,它会为您处理任何锁定。
这意味着您可以拥有任意数量的编写器,并且如果它们都被同一股包裹(因此,在所有编写器之间共享您的单股),它们将连续执行。需要注意的一件事是确保您没有尝试使用内存中相同的实际缓冲区来执行所有写入。例如,这是要避免的:
char buffer_to_write[256]; // shared among threads
/* ... in thread 1 ... */
memcpy(buffer_to_write, packet_1, std::min(sizeof(packet_1), sizeof(buffer_to_write)));
my_socket.async_write_some(boost::asio::buffer(buffer_to_write, sizeof(buffer_to_write)), &my_callback);
/* ... in thread 2 ... */
memcpy(buffer_to_write, packet_2, std::min(sizeof(packet_2), sizeof(buffer_to_write)));
my_socket.async_write_some(boost::asio::buffer(buffer_to_write, sizeof(buffer_to_write)), &my_callback);
在那里,您正在共享您的实际写入缓冲区 ( buffer_to_write
)。如果你做了这样的事情,你会没事的:
/* A utility class that you can use */
class PacketWriter
{
private:
typedef std::vector<char> buffer_type;
static void WriteIsComplete(boost::shared_ptr<buffer_type> op_buffer, const boost::system::error_code& error, std::size_t bytes_transferred)
{
// Handle your write completion here
}
public:
template<class IO>
static bool WritePacket(const std::vector<char>& packet_data, IO& asio_object)
{
boost::shared_ptr<buffer_type> op_buffer(new buffer_type(packet_data));
if (!op_buffer)
{
return (false);
}
asio_object.async_write_some(boost::asio::buffer(*op_buffer), boost::bind(&PacketWriter::WriteIsComplete, op_buffer, boost::asio::placeholder::error, boost::asio::placeholder::bytes_transferred));
}
};
/* ... in thread 1 ... */
PacketWriter::WritePacket(packet_1, my_socket);
/* ... in thread 2 ... */
PacketWriter::WritePacket(packet_2, my_socket);
在这里,如果您也将您的链传递到 WritePacket 会有所帮助。不过,你明白了。
答案#2:
我认为您已经采取了非常好的方法。我将提供的一个建议是使用async_write
而不是,async_write_some
这样可以保证在调用回调之前写入整个缓冲区。