2014-12-05 12 views
9

Sto cercando di capire le chiamate boost::asio::streambuf::consume() e boost::asio::streambuf::commit(). Nei documenti, abbiamo gli esempi,Quando chiamo boost :: asio :: streambuf :: consume() e boost :: asio :: streambuf :: commit()?

boost::asio::streambuf b; 
std::ostream os(&b); 
os << "Hello, World!\n"; 

// try sending some data in input sequence 
size_t n = sock.send(b.data()); 

b.consume(n); // sent data is removed from input sequence 

e

boost::asio::streambuf b; 

// reserve 512 bytes in output sequence 
boost::asio::streambuf::mutable_buffers_type bufs = b.prepare(512); 

size_t n = sock.receive(bufs); 

// received data is "committed" from output sequence to input sequence 
b.commit(n); 

std::istream is(&b); 
std::string s; 
is >> s; 

capisco queste due chiamate per quanto ho capito quello che dice la documentazione su di loro - chiamare consume() per rimuovere caratteri dalla sequenza di input all'interno dello boost::asio::streambuf e chiamare commit() per spostare i caratteri dalla sequenza di output di boost::asio::streambuf alla sequenza di input. Giusto.

Quando posso chiamare in realtà? Guardando alla fonte boost::asio::read_until(), abbiamo

template <typename SyncReadStream, typename Allocator> 
std::size_t read_until(SyncReadStream& s, 
    boost::asio::basic_streambuf<Allocator>& b, char delim, 
    boost::system::error_code& ec) 
{ 
    std::size_t search_position = 0; 
    for (;;) 
    { 
    // Determine the range of the data to be searched. 
    typedef typename boost::asio::basic_streambuf< 
     Allocator>::const_buffers_type const_buffers_type; 
    typedef boost::asio::buffers_iterator<const_buffers_type> iterator; 
    const_buffers_type buffers = b.data(); 
    iterator begin = iterator::begin(buffers); 
    iterator start_pos = begin + search_position; 
    iterator end = iterator::end(buffers); 

    // Look for a match. 
    iterator iter = std::find(start_pos, end, delim); 
    if (iter != end) 
    { 
     // Found a match. We're done. 
     ec = boost::system::error_code(); 
     return iter - begin + 1; 
    } 
    else 
    { 
     // No match. Next search can start with the new data. 
     search_position = end - begin; 
    } 

    // Check if buffer is full. 
    if (b.size() == b.max_size()) 
    { 
     ec = error::not_found; 
     return 0; 
    } 

    // Need more data. 
    std::size_t bytes_to_read = read_size_helper(b, 65536); 
    b.commit(s.read_some(b.prepare(bytes_to_read), ec)); 
    if (ec) 
     return 0; 
    } 
} 

Si può vedere che, come dice la documentazione, boost::asio::read_until() è implementato in termini di SyncReadStream s' read_some().

Per me, che dice che

  1. SyncReadStream::read_some() non chiama boost::asio::streambuf::commit()
  2. boost::asio::read_until() SI chiamare boost::asio::streambuf::commit()
  3. Nessuno di questi sembra essere documentato - né in boost::asio::read_until() 'documentazione s, nè in SyncReadStream' s documenti.
  4. Non so se dovrei chiamare lo boost::asio::streambuf::commit()?

con il mio codice sincrono di certo non mi sembra di averne bisogno, non quando sto chiamando le funzioni libere boost::asio::read() e boost::asio::read_until(). Lo ho nel mio codice asincrono nei miei gestori, soprattutto perché gli esempi che ho usato ce l'hanno, ma non sono sicuro di chiamarlo allora. Quando provo a usare uno boost::asio::streambuf con stringstream e std::string, il numero commit() non sembra avere un ruolo - niente viene fermato o bloccato senza chiamare lo sullo streambuf.

Qualcuno può risolvere questo per me?

+0

Mi piacerebbe vedere una documentazione definitiva su questo. Non riesco a trovare nulla. – EML

risposta

1

read_until utilizza read_some nella sua implementazione. Quindi, chiama streambuf::commit e read_until non (direttamente).

In genere non è necessario chiamare commit e consume, ma se si vuole fare qualcosa con i dati del buffer, questo può essere un modo per farlo. Ad esempio, se si utilizza un protocollo binario, che non può essere verificato correttamente con read_until.

4

Asio definisce una serie di auxiliary free functions (read_xxx) che accettano asio::streambuf, e la cura per prepare e commit esso.

D'altra parte, se si desidera utilizzare asio::streambuf con lower-level functions che accettano un modello di MutableBufferSequence concept, devi chiamare streambuf::prepare(), che restituisce un oggetto che soddisfa MutableBufferSequence concetto, passare questo oggetto come un buffer, e dopo la funzione lo riempie - chiama commit().

In entrambi i casi, dopo aver letto n byte di dati da streambuf, è necessario chiamare consume(n) - per consumare la sequenza di input.