2011-01-13 14 views
23

Estoy tratando de integrar D-Bus con mi aplicación boost::asio.Async wait on file descriptor using Boost Asio

D-Bus tiene una API que enumera un conjunto de descriptores de archivos Unix (principalmente sockets pero también podrían ser FIFO) para ser vistos. Cuando esos descriptores tienen algo que leer, debería informar a la API de D-Bus para que pueda leerlos y hacerlo.

Actualmente estoy haciendo esto:

using boost::asio::posix::stream_descriptor; 
void read_handle(stream_descriptor* desc, const boost::system::error_code& ec, 
       std::size_t bytes_read) 
{ 
    if (!ec) { 
     stream_descriptor::bytes_readable command(true); 
     descriptor->io_control(command); 
     std::size_t bytes_readable = command.get(); 
     std::cout << "It thinks I should read" << bytes_readable 
      << " bytes" << std::endl; 
    } else { 
     std::cout << "There was an error" << std::endl; 
    } 
} 

void watch_descriptor(boost::asio::io_service& ios, int file_descriptor) 
{ 
    // Create the asio representation of the descriptor 
    stream_descriptor* desc = new stream_descriptor(ios); 
    desc->assign(file_descriptor); 

    // Try to read 0 bytes just to be informed that there is something to be read 
    std::vector<char> buffer(0); 
    desc->async_read_some(boost::asio::buffer(buffer, 0), 
     boost::bind(read_handle, desc, _1, _2)); 
} 

Pero el gestor se llama de inmediato diciendo que tiene 0 bytes a leer. Me gustaría que se llame solo cuando haya algo que leer, pero boost :: asio NO PUEDE leerlo. Debería actuar como una glorificada select(). ¿Hay una manera simple de hacer eso?

PD: Estoy usando ampliamente boost::asio en mi software, esto es solo una pequeña parte, por lo que me gustaría no depender de glib u otros mainloops.

+0

¿Cuál es la API de D-Bus que está utilizando? ¿Es la API C de bajo nivel? –

Respuesta

26

Este es precisamente el problema null_buffers era designed para.

A veces un programa debe integrarse con una biblioteca de terceros que quiere para llevar a cabo la propia S operaciones de E /. Para facilitar esto, Boost.Asio incluye un tipo null_buffers que se puede usar con operaciones de lectura y escritura . Una operación null_buffers no se devuelve hasta que el objeto de E/S sea "listo" para realizar la operación.

A modo de ejemplo, para realizar una no-bloqueo leer algo así como el siguiente puede ser usado:

ip::tcp::socket socket(my_io_service); 
... 
ip::tcp::socket::non_blocking nb(true); 
socket.io_control(nb); 
... 
socket.async_read_some(null_buffers(), read_handler); 
... 
void read_handler(boost::system::error_code ec) 
{ 
    if (!ec) 
    { 
    std::vector<char> buf(socket.available()); 
    socket.read_some(buffer(buf)); 
    } 
} 

También hay un excellent example incluido en la documentación.

+0

Esto era justo lo que estaba buscando. Se integró perfectamente. ¡Muchas gracias! –

+1

Hola Sam, ¿puedes explicar más sobre el excelente ejemplo incluido en la documentación que mencionaste? Quiero usar 'third_party_lib.session' para leer/AsyncRead/Write/AsyncWrite algo, ¿cómo puedo hacerlo? Todavía no estoy tan claro. El ejemplo que simula el third_party_lib me confundió en realidad. Gracias. –

+0

@Peter por favor haga una nueva pregunta, incluya qué parte del ejemplo le resulta confuso. –

Cuestiones relacionadas