2012-05-23 14 views
5

Il mio codice utilizza boost :: asio e io_service in una singola discussione per eseguire varie operazioni socket. Tutte le operazioni sono asincrone e ogni gestore dipende dallo boost::system::error_code (in particolare) per determinare il risultato dell'operazione.boost :: gestori async async richiamati senza errori dopo l'annullamento

Ha funzionato perfettamente fino a quando ho modificato la logica per rendere più simultanee connessioni e scegliere quella più veloce. Cioè, quando il primo gestore di async_read_some si attiva, annullo altri socket (shutdown, close - everything) e procedo con quello corrente. Nel 95% dei casi gli handler di lettura di altri socket vengono richiamati con l'errore operation_aborted. Tuttavia, a volte, questi gestori di lettura vengono richiamati senza errori, dicendomi che hanno ricevuto N byte correttamente.

ma la documentazione per lo zoccolo :: cancel() states:

Questa funzione fa sì che tutti eccezionali asincrono collegare, inviare e ricevere operazioni di finire immediatamente, ei gestori per operazioni annullate saranno superato la Errore boost::asio::error::operation_aborted.

Quindi, le domande: Posso davvero fare affidamento sull'errore operation_aborted nel codice di produzione? Se posso, è un bug in Asio da boost 1.46.1? Se non posso, c'è qualche documentazione ufficiale riguardo a questo?

+1

Sembra nel tuo caso che più gestori abbiano "eseguito l'operazione" prima che l'annullamento sia stato richiamato. Puoi fare affidamento su 'operation_aborted' per essere passato a tutti i gestori che non sono già stati eseguiti (e sono in attesa di essere chiamati). – Chad

risposta

11

Ok, le risposte:

  1. No, non posso contare su solo l'errore operation_aborted.
  2. Ovviamente, non è un bug in Asio, solo una mancanza di esperienza al mio fianco.
  3. C'è un po 'di documentation ufficiale. E 'per timer, non prese, tuttavia gli stessi principi si applicano:

Se il timer è già scaduto quando annullare() è chiamato, quindi i gestori per le operazioni di attesa asincrone volontà:

  • sono già stati invocati; oppure
  • sono stati messi in coda per l'invocazione nel prossimo futuro.

Fondamentalmente, ho sbagliato nel presupposto che se uso un singolo filo per io_service, allora ogni operazione sarà bloccato mentre alcuni gestore viene eseguito.

Il comportamento che sto segnalando in realtà ha molto senso e sembra che tutti quelli che usano Asio lo sappiano.Ho sfogliato le mailing list di Asio e ho trovato molte discussioni sull'argomento here, here, here e here.

Ad esempio, un'operazione di scrittura può completata con successo, mentre sei all'interno di un gestore, ma prima di aver trovato il tempo di chiamare presa si annullano, provocando il suo gestore di completamento per essere pubblicato alla coda. A quanto ho capito, il codice di errore è determinato dallo stato dell'operazione completata, non dallo stato del socket nel momento in cui il gestore viene prelevato dalla coda ed eseguito.

+1

+1 per la bella risposta alla tua stessa domanda –

2

Considerare due connessioni che stabiliscono allo stesso tempo. Entrambi i gestori spareranno, uno verrà gestito per primo, il secondo è in coda (o viene gestito su un thread diverso). Si può pensare ad altri esempi come quello.

Quindi per implementare il tuo requisito hai bisogno di un po 'più di logica.