Domanda

Ho un server di chat in C/Linux usando le prese TCP. Quando usi LiBev, sono in grado di creare un osservatore EV_IO per eventi di lettura una volta per una presa. Qualcosa di simile a:

ev_io* new_watcher = (ev_io*)malloc(sizeof(ev_io));

//initialize the watcher
ev_init(new_watcher, read_cb);

//set the fd and event to fire on write
ev_io_set(new_watcher, watcher->fd, EV_READ);

//start watching
ev_io_start(loop, new_watcher);

E questo funziona bene perché l'evento di lettura accenderà solo quando ci sono dati da leggere. Tuttavia, devo trattare gli eventi di scrittura in modo diverso perché sparano costantemente anche quando non ho dati da scrivere. Per risolvere questo problema ho il mio read_callback Creare un ev_io Watcher per un dati di scrittura solo quando ci sono dati pronti per essere scritti, quindi write_callback eliminerà l'osservatore dopo aver inviato il suo messaggio.

Ciò significa che sto assegnando, inizializzando, impostando, guardando, pagando e traffico l'osservatore di scrittura ogni volta che ho bisogno di gestire un messaggio. Temo di gestirlo in modo errato e inefficiente.

Qual è il metodo migliore per gestire gli eventi Write_Callback in Libev?

Grazie in anticipo.

È stato utile?

Soluzione

L'allocazione può aggiungere un po 'di sovraccarico, è possibile utilizzare una variabile statica anziché Malloc o Malloc una volta e gratuita solo dopo il completamento del ciclo dell'evento. Devi solo impostare prima di scrivere e non suonare dopo aver successo. Ma sì, è così che deve essere fatto.

Altri suggerimenti

Facile, c'è anche EV_IO_STO

Nel caso comune in cui raramente trabocca il buffer di scrittura (perché i tuoi dati sono piccoli e non si fa troppo spesso), puoi renderlo più efficiente cercando di scrivere i dati direttamente (se l'osservatore non è attivo) e solo Buffering dei dati e avviare Write Watcher se non si può scriverli completamente.

Secondo i presupposti sopra, questo significa che non è quasi mai necessario iniziare l'osservatore di scrittura. Lo svantaggio è un codice molto più complesso, quindi in molti casi, è meglio iniziare con il semplice "Aggiungi i dati per scrivere buffer, avviare l'osservatore, all'interno della logica del buffer è stato scritto completamente".

Il modo in cui ho risolto questa situazione era avere una funzione per scrivere dati che portano un puntatore al buffer e alla lunghezza. Memorizza il puntatore e la lunghezza in una struttura di dati in coda e consente l'evento di scrittura.

Quando il callback dell'evento di scrittura spara, controlla la coda di scrittura per vedere se ci sono scritture in sospeso. Se ce ne sono, prende la scrittura in sospeso successiva in coda e la scrive al descrittore di file. Quindi, poco prima che la callback di scrittura esca, controlla se la coda di scrittura in sospeso è vuota. In tal caso, allora disabilita l'evento di scrittura.

Se si crea le variabili globali degli oggetti di lettura/scrittura, verranno assegnati e liberati solo una volta. Abiliti l'evento di scrittura ogni volta che sai che ci sono dati da scrivere e li disabiliti una volta che non ci sono più dati da scrivere.

Il mio codice è un po 'più complicato della descrizione sopra, ma posterò un link qui solo per poter dare un'occhiata. Il codice di cui sto parlando in particolare è in aiofd.h e aiofd.c (aiofd == descrittore di file I/O asincrono): https://bitbucket.org/wookie/cutil/

Spero che questo aiuti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top