2012-07-18 7 views
5

Sto cercando di capire come sbarazzarmi di una dipendenza da pthread_timedjoin_np perché sto cercando di creare codice su OSX.alternativa a pthread_timedjoin_np

In questo momento ho una coda di thread da cui provengo, che fa pthread_timedjoin_np e se non restituiscono, vengono reinseriti in coda.

La fine della funzione thread chiamata per ogni thread esegue una pthread_exit (0); in modo che il thread di ricezione possa controllare un valore di ritorno pari a zero.

Ho pensato di provare a utilizzare pthread_cond_timedwait() per ottenere un effetto simile, tuttavia penso che manchi un passaggio.

Ho pensato che sarei stato in grado di rendere il segnale A del filo lavoratore una condizione AND pthread_exit() all'interno di un mutex, e il thread di lavoro B potrebbe essere attivato sul segnale e quindi pthread_join(). Il problema è che il thread B non sa quale thread ha lanciato il segnale condizionale. Devo passarlo esplicitamente come parte del segnale conditonale o cosa?

Grazie

Derek

+0

Non un duplicato, ma alcune delle risposte possono essere utili: http: // StackOverflow.it/questions/73468/non-blocking-pthread-join – Corbin

risposta

1

Coda produttore-consumatore. Avere i thread in coda * e quindi i loro risultati (se presenti) nella coda prima che escano. Attendi in coda.

Nessun polling, nessuna latenza.

Con il progetto corrente, è necessario unire() i thread restituiti ottenere il valoreptr e assicurarsi che vengano distrutti.

Forse potresti passare a un threadpool reale, in cui gli elementi delle attività vengono accodati ai thread che non terminano mai (eliminando così il thread creare/terminare/distruggere il sovraccarico)?

+0

re: real threadpool..ho avuto questa idea prima. Sto lavorando nel framework Qt e ho usato il loro pool/modello futuro prima, ma non sono sicuro che se riuscirò a usarlo nel nome della portabilità di questo codice – Derek

+0

ho finito per provare a implementare qualcosa come questo - in origine il thread principale era solo quello di buttare tutti gli operai in una coda, ma l'ho rielaborato un po 'per far sì che i woeker si aggiungano a una coda quando hanno finito, e poi lanciano un segnale di condizione per lasciarne un altro thread sa di estrarre qualcosa dalla coda e farne parte. – Derek

4

Ecco un'implementazione portabile di pthread_timedjoin_np. E 'un po' costoso, ma è una sostituzione completa drop-in:

struct args { 
    int joined; 
    pthread_t td; 
    pthread_mutex_t mtx; 
    pthread_cond_t cond; 
    void **res; 
}; 

static void *waiter(void *ap) 
{ 
    struct args *args = ap; 
    pthread_join(args->td, args->res); 
    pthread_mutex_lock(&args->mtx); 
    args->joined = 1; 
    pthread_mutex_unlock(&args->mtx); 
    pthread_cond_signal(&args->cond); 
    return 0; 
} 

int pthread_timedjoin_np(pthread_t td, void **res, struct timespec *ts) 
{ 
    pthread_t tmp; 
    int ret; 
    struct args args = { .td = td, .res = res }; 

    pthread_mutex_init(&args.mtx, 0); 
    pthread_cond_init(&args.cond, 0); 
    pthread_mutex_lock(&args.mtx); 

    ret = pthread_create(&tmp, 0, waiter, &args); 
    if (ret) goto done; 

    do ret = pthread_cond_timedwait(&args.cond, &args.mtx, ts); 
    while (!args.joined && ret != ETIMEDOUT); 

    pthread_mutex_unlock(&args.mtx); 

    pthread_cancel(tmp); 
    pthread_join(tmp, 0); 

    pthread_cond_destroy(&args.cond); 
    pthread_mutex_destroy(&args.mtx); 

    return args.joined ? 0 : ret; 
} 

Ci possono essere piccoli errori da quando ho scritto questo sul posto e non l'ho provato, ma il concetto è sana.

+0

Prima di pubblicare avevo in realtà un piano simile a Martins, se questo non sembra funzionare bene farò un tentativo. – Derek

+0

La soluzione di Martin è più pulita dal punto di vista di non avere sprechi di spese generali ed essere concettualmente migliori. Il mio è solo un rimpiazzo sostitutivo della funzione non portabile che consente di correggere il codice non portatile senza ridisegnare nulla. –

0

soluzione con alarm.

pthread deve abilitare l'annullamento, quindi può essere interrotto da esterno (anche con pthread_timedjoin_np).

pthread_timedjoin_np restituire con ETIMEOUT dopo il tempo di attesa.

  1. set alarm, utilizzare alarm può anche dare il segnale "TIMEOUT".
  2. In handler, solo pthread_cancel it. (solo il timeout esegue questo).
  3. pthread_join nella filettatura principale.
  4. ripristinare alarm

scrivo codice di prova qui: github