2014-04-24 11 views
12

Sto cercando qualcosa potrebbe essere utilizzato per polling (come select, kqueue, epoll cioè non occupato polling) in C/C++. In altre parole, ho bisogno di bloccare un thread e quindi di riattivarlo in un altro thread con il più piccolo overhead possibile.Esistono equivalenti al futex in Linux/Unix?

A mutex + condition variable funziona, ma c'è un sacco di spese generali. Anche un futex funziona, ma è solo per Linux (o forse no?). La sincronizzazione aggiuntiva non è necessaria finché il polling funziona correttamente, ad es. nessuna gara quando chiamo wait e wake in due thread.

Modifica: Se tale "funzione" non esiste in FreeBSD, come crearne una con tipi e chiamate di sistema incorporati in C++ 11?

Edit2: Dal momento che questa domanda è migrato a SO, mi piacerebbe per renderlo più generale (non per FreeBSD solo)

+0

Devi anche bloccare su _multiple_ sources o solo uno? 'select',' poll' ecc. sono normalmente usati per (de) multiplexing di più fds, non solo per bloccarne uno. – Useless

+0

@Utile Uno è abbastanza buono. Hai ragione, 'select' non è un buon esempio qui. L'ho menzionato solo per illustrare che non desidero * busy waiting * – GuLearn

+0

Dopo la migrazione, mi sono confuso riguardo al "target" per questa domanda. Stai cercando la risposta per FreeBSD, POSIX o C++ 11 standard? –

risposta

2

Volete semafori e non mutex per la segnalazione tra l'una discussioni ..

http://man7.org/linux/man-pages/man3/sem_wait.3.html

semafori può essere utilizzato come un banco come se si dispone di una coda, si incrementerà (post) al semaforo ogni volta che si inserisce un messaggio, e il vostro decremento del ricevitore (attesa) sul semaforo per ogni messaggio tira fuori. Se il contatore raggiunge lo zero, il ricevitore bloccherà fino a quando non verrà pubblicato qualcosa.

Quindi uno schema tipico è quello di combinare un mutex e un semaforo come;

sender: 
    mutex.lock 
    insert message in shared queue 
    mutex.unlock 
    semaphore.post 

receiver: 
    semaphore.wait 
    mutex.lock 
    dequeue message from shared structure 
    mutex.unlock 
3

semafori non sono mutex, e funzionerebbero con leggermente meno overhead (evitando il mutex + condvar ri-lock, per esempio)

notare che, poichè qualsiasi soluzione in cui un filo ospitare fino risvegliato comporterà un kernel syscall, non è ancora economico. Supponendo x86_64 glibc e le libc FreeBSD sono entrambe le implementazioni ragionevoli, il costo inevitabile sembra essere:

sincronizzazione
  1. modalità utente del conteggio (con un CAS o simile) gestione
  2. kernel della coda di attesa e filo sonno/attendere

Suppongo che il mutex + spese generali condvar siete preoccupati è la sequenza cond_wait-> ri-Lock> sbloccare, che è infatti evitato qui.

+0

Sto bene con il syscall e il cambio di contesto perché ho un sacco di thread non occupati. La mia preoccupazione per il semaforo è che potrebbe essere anche meno efficiente della variabile di condizione 'mutex' +': http: //www.freebsd.org/cgi/man.cgi? query = sema & sektion = 9. L'uomo sem_overview' in Ubuntu non ha detto nulla sulle prestazioni. Potrei aver bisogno di confrontarlo da solo. – GuLearn

+0

La fonte glibc per x86 mostra che implementa semafori utilizzando il futex syscall per gestire i camerieri e un CAS dello spazio utente per il contatore (ad esempio [questo pseudocodice] (https://sourceware.org/git/?p=glibc.git; a = blob; f = nptl/DISEGNO-sem.txt; hb = HEAD)). Non so quanto potrebbe essere più economico, ma dovrai investigare il comportamento su altre piattaforme. – Useless

+0

Il [codice libc di FreeBSD] (http://svnweb.freebsd.org/base/head/lib/libc/gen/sem_new.c?view=markup&pathrev=232144) sembra simile ... – Useless