2011-01-13 13 views
23

Sto cercando di integrare D-Bus con la mia applicazione boost::asio.Async attendere sul descrittore di file utilizzando Boost Asio

D-Bus ha un'API che enumera una serie di descrittori di file Unix (principalmente socket ma potrebbero anche essere FIFO) da guardare. Quando questi descrittori hanno qualcosa da leggere, dovrei informare l'API D-Bus in modo che possa leggerli e fare la cosa.

Attualmente sto facendo questo:

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

Ma il gestore viene chiamato subito dicendo che ha 0 byte da leggere. Mi piacerebbe che fosse chiamato solo quando c'è qualcosa da leggere, ma boost :: asio NON lo può leggere. Dovrebbe agire proprio come glorificato select(). C'è un modo semplice per farlo?

PS: utilizzo estesamente il boost::asio nel mio software, questa è solo una piccola parte di esso, quindi mi piacerebbe non dipendere da glib o altri mainloops.

+0

Qual è l'API D-Bus che stai utilizzando? È l'API C di basso livello? –

risposta

26

Questo è precisamente il problema null_buffers per designed per.

volte un programma è da integrarsi con una libreria di terze parti che vuole per eseguire l'I/O operazioni di sé. Per facilitare questo, Boost.Asio include un tipo null_buffers che può essere utilizzato con operazioni di lettura e scrittura . Un'operazione null_buffers non viene restituita finché l'oggetto I/O non è "pronto" per eseguire l'operazione.

A titolo di esempio, per eseguire un non bloccante leggere qualcosa di simile alla possono essere utilizzati seguente:

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

C'è anche un excellent example incluse nella documentazione.

+0

Questo era proprio quello che stavo cercando. Si integra perfettamente. Molte grazie! –

+1

Ciao Sam, puoi spiegare di più sull'eccellente esempio incluso nella documentazione che hai menzionato? Voglio usare 'third_party_lib.session' per leggere/AsyncRead/Write/AsyncWrite qualcosa, come posso farlo? Non sono ancora così chiaro. L'esempio che simula il third_party_lib mi ha veramente confuso. Grazie. –

+0

@Peter si prega di fare una nuova domanda, includere quale parte dell'esempio trovi confusa. –