2013-04-22 10 views
5

Zaimplementowałem rodzaj "wątku lokalnego singletona" używając pthread TLS, i zastanawiałem się, jak (i ​​kiedy) mogę ewentualnie usunąć pthread_key_t w tym przypadku, ponieważ tak jak jest teraz, pamięć używana przez klucz TLS nigdy nie będzie uwolniony.Pthread Thread-Local-Singleton, kiedy zwolnić klucz TLS?

jego wykorzystania tego jest pozwolić klasy A pochodzą z ThreadLocalSingleton < > co sprawia, że ​​nitki lokalnej Singleton, zakładając, że ma tylko prywatne konstruktorów i ThreadLocalSingleton < > jest przyjacielem A.

Och, a także - czy widzisz jakieś problemy z tą implementacją; czy przeoczyłem coś ważnego?

#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

Według Kerrisk w [Linux Programming Interface: A Linux and UNIX System Programming Handbook] (http://www.amazon.com/dp/1593272200), wierzę, że używasz * danych specyficznych dla wątków * ('pthread_key_create 'i przyjaciele) raczej * Wątek lokalna pamięć masowa * (słowo kluczowe __thread' na zmiennych statycznych i globalnych). – jww

Odpowiedz

2

Twoje wdrożenie wygląda bardzo elegancko.

Według Open Group Specification of pthread_key_create, nie trzeba ustawić odniesienie do NULL w destruktora:

Opcjonalna funkcja destruktor może wiązać się z każdej wartości klucza. Na wyjściu wątku, jeśli wartość klucza ma wskaźnik nieniszczący NULL, a wątek ma wartość nie-NULL powiązaną z tym kluczem, wartość klucza jest ustawiona na NULL, a następnie wskazywana funkcja jest wywoływana z poprzednio powiązana wartość jako jedyny argument.

Myślę, że to również oznacza, że ​​kluczowy obiekt sam zostanie automatycznie usunięty przez pthread. Musisz tylko zająć się tym, co jest przechowywane za kluczem, co jest dokładnie tym, co robi twój delete ((T*)obj);.