Aquí está mi aplicación:impulso asio async_write: cómo no entrelazado llamadas async_write?
- cliente A envía un mensaje al Cliente B
- proceso de servidor el mensaje por
async_read
la cantidad correcta de los datos y esperará a que los nuevos datos del cliente A (a fin de no bloquear el cliente a) - después servidor procesará la información (probablemente hacer una consulta MySQL ) y luego enviar el mensaje al cliente B con
async_write
.
El problema es que, si el cliente A envía el mensaje muy rápido, async_writes
intercalará antes de que el controlador de async_write anterior se llama.
¿Hay una manera sencilla de evitar este problema?
EDIT 1: Si un cliente C envía un mensaje al Cliente B justo después el cliente A, debería aparecer el mismo problema ...
EDIT 2: Esto funcionaría? porque parece bloquear, no sé dónde ...
namespace structure {
class User {
public:
User(boost::asio::io_service& io_service, boost::asio::ssl::context& context) :
m_socket(io_service, context), m_strand(io_service), is_writing(false) {}
ssl_socket& getSocket() {
return m_socket;
}
boost::asio::strand getStrand() {
return m_strand;
}
void push(std::string str) {
m_strand.post(boost::bind(&structure::User::strand_push, this, str));
}
void strand_push(std::string str) {
std::cout << "pushing: " << boost::this_thread::get_id() << std::endl;
m_queue.push(str);
if (!is_writing) {
write();
std::cout << "going to write" << std::endl;
}
std::cout << "Already writing" << std::endl;
}
void write() {
std::cout << "writing" << std::endl;
is_writing = true;
std::string str = m_queue.front();
boost::asio::async_write(m_socket,
boost::asio::buffer(str.c_str(), str.size()),
boost::bind(&structure::User::sent, this)
);
}
void sent() {
std::cout << "sent" << std::endl;
m_queue.pop();
if (!m_queue.empty()) {
write();
return;
}
else
is_writing = false;
std::cout << "done sent" << std::endl;
}
private:
ssl_socket m_socket;
boost::asio::strand m_strand;
std::queue<std::string> m_queue;
bool is_writing;
};
}
#endif
Tenga en cuenta que asíncrono de escritura es mucho menos valioso que asíncrono leer. La mayoría de las escrituras son prácticamente instantáneas, ya que el SO almacenará los datos de forma local. Por otro lado, las lecturas pueden bloquear la espera del lado remoto y no hay nada que se pueda hacer localmente. La escritura síncrona es, por lo tanto, una forma viable de implementar la secuencia. Esto también resuelve el problema de la propiedad de los datos: el código anterior es incorrecto ya que 'str' se destruye cuando' write() 'regresa, lo que puede suceder antes de que 'boost :: asio_async_write()' acceda al búfer. – MSalters