2013-04-22 11 views
5

Ho implementato una sorta di "thread local singleton" usando pthread TLS, e mi chiedevo come (e quando) potrei eliminare il pthread_key_t in questo caso, perché come ora, la memoria utilizzata dalla chiave TLS non sarà mai free'd.Thread Pthread-Local-Singleton, quando rilasciare la chiave TLS?

L'utilizzo previsto di questo è di lasciare che una classe Una deriva da ThreadLocalSingleton <A> che fa un un filo Singleton locale, partendo dal presupposto che A ha solo i costruttori privati ​​e ThreadLocalSingleton <Un> è un amico di A.

Oh e anche - vedi qualche problema con questa implementazione; ho trascurato qualcosa di importante?

#include <pthread.h> 
#include <iostream> 

template <class T> 
class ThreadLocalSingleton 
{ 
private: 
    static pthread_key_t tlsKey; 
    static pthread_once_t tlsKey_once; 

    static void tls_make_key() 
    { 
     (void)pthread_key_create(&ThreadLocalSingleton::tlsKey, ThreadLocalSingleton::tls_destructor); 
    } 

    static void tls_destructor(void* obj) 
    { 
     delete ((T*)obj); 
     pthread_setspecific(tlsKey, NULL); // necessary or it will call the destructor again. 
    } 

public: 

    /* 
    * A thread-local singleton getter, the resulted object must never be released, 
    * it is auto-released when the thread exits. 
    */ 
    static T* getThreadInstance(void) 
    { 
     pthread_once(&tlsKey_once, ThreadLocalSingleton::tls_make_key); 
     T* instance = (T*)pthread_getspecific(tlsKey); 
     if(!instance) 
     { 
      try 
      { 
       instance = new T; 
       pthread_setspecific(tlsKey, instance); 
      } 
      catch (const char* ex) 
      { 
       printf("Exception during thread local singleton init: %s\n",ex); 
      } 
     } 
     return instance; 
    } 
}; 
template <class T> 
pthread_key_t ThreadLocalSingleton<T>::tlsKey; 
template <class T> 
pthread_once_t ThreadLocalSingleton<T>::tlsKey_once = PTHREAD_ONCE_INIT; 
+0

Secondo Kerrisk in [L'interfaccia di programmazione Linux: un manuale di programmazione di sistema Linux e UNIX] (http://www.amazon.com/dp/1593272200), credo che si stia utilizzando * Dati specifici del thread * ('pthread_key_create 'e amici) piuttosto * Thread Local Storage * (parola chiave' __thread' su variabili statiche e globali). – jww

risposta

2

La tua implementazione sembra molto elegante.

Secondo il Open Group Specification of pthread_key_create, non è necessario impostare il riferimento a NULL nel distruttore:

una funzione distruttore opzionale può essere associata a ciascun valore della chiave. All'uscita del thread, se un valore chiave ha un puntatore del destructor non NULL e il thread ha un valore non NULL associato a quella chiave, il valore della chiave è impostato su NULL, quindi la funzione puntata viene chiamata con il valore valore precedentemente associato come argomento esclusivo.

Penso che questo implichi anche che l'oggetto chiave stesso verrà autodistrato da pthread. Devi solo occuparti di ciò che è memorizzato dietro la chiave, che è esattamente ciò che fa il tuo delete ((T*)obj);.