2009-12-06 21 views
6

Utilizzo socket asincroni sincroni per leggere dati su TCP da un thread in background. Questo è incapsulato in una classe "server".Boost di interrupt :: read asincrono asio?

Tuttavia, voglio che il thread esca quando viene chiamato il distruttore di questa classe. Il problema è che una chiamata a una delle funzioni di lettura si blocca, quindi il thread non può essere terminato facilmente. In Win32 c'è un'API per questo: WaitForMultipleObjects che farebbe esattamente quello che voglio.

Come ottenere un effetto simile con boost?

risposta

2

Nella nostra applicazione, impostiamo la condizione di "terminazione", quindi usiamo una connessione automatica alla porta su cui il thread è in ascolto, quindi si riattiva, prende nota della condizione di terminazione e termina.

Si può anche verificare l'implementazione di boost - se stanno facendo solo una lettura normale sul socket (cioè, non usando qualcosa come WaitForMultipleObjects internamente) allora si può probabilmente concludere che non c'è nulla da sbloccare in modo semplice e pulito il filo. Se sono in attesa su più oggetti (o su una porta di completamento) è possibile scavare intorno per vedere se la capacità di riattivare il thread di blocco è esposta all'esterno.

Infine, si potrebbe uccidere il thread - ma dovrete andare fuori di spinta per fare questo, e capire le conseguenze, come penzoloni o le risorse trapelate. Se stai chiudendo, questo potrebbe non essere un problema, a seconda di cosa stesse facendo quel thread.

2

Non ho trovato un modo semplice per farlo. Presumibilmente, ci sono modi per cancellare Win32 IOCP, ma non funziona bene su Windows XP. MS ha risolto il problema per Windows Vista e 7. L'approccio consigliato per annullare asio async_read o async_write consiste nel chiudere il socket.

  • [distruttore] nota che vogliamo teardown
  • [distruttore] chiudere il socket
  • [distruttore] aspettiamo i gestori di completamento

  • [di completamento] se abbattere e abbiamo appena fallito poiché il socket è stato chiuso, comunica al distruttore che i gestori del completamento sono stati completati.

  • [completamento] restituire immediatamente.

Fare attenzione se si sceglie di implementarlo. Chiudere la presa è abbastanza semplice. 'attendere i gestori del completamento', tuttavia, è un enorme understatment. Ci sono diversi casi d'angolo e condizioni di gara che possono verificarsi quando il thread del server e il suo distruttore interagiscono.

Questo è stato sufficiente che si costruisce un involucro di completamento (simile a io_service::strand sottile solo per gestire in modo sincrono annullamento di tutte le richiamate di completamento in sospeso.

1

Il modo migliore è quello di creare un socketpair(), (qualunque cosa sia in boost::asio gergo), aggiungi il lettore termina il ciclo degli eventi, quindi chiude la scrittura dello scrittore verso il basso.Si verrà svegliato immediatamente con un evento EOC su quel socket

Il thread deve quindi chiudersi volontariamente verso il basso.

La spawner del filo dovrebbe nel suo distruttore, hanno la seguente:

~object() 
{ 
    shutdown_queue.shutdown(); // ask thread to shut down 
    thread.join();    // wait until it does 
} 
-1

Uso socket.cancel(); per terminare tutte le operazioni asincrone attualmente bloccate su un socket. Potrebbe essere necessario uccidere i socket del client in un ciclo. Non ho mai dovuto chiudere il server in questo modo, ma puoi usare shared_from_this() ed eseguire cancel()/close() in un ciclo in modo simile a come l'esempio di chat boost async_writes su tutti i client.

Problemi correlati