2011-07-04 10 views
8

Estoy manteniendo una biblioteca que tiene una función que necesita variables específicas de subprocesos. Debido a un error en gcc 4.2, si defino static __thread en x; cuando se llama a la función de biblioteca a través de la API sin nombre de PERL, se cuelga.Cómo crear pthread variables específicas sin __thread

Me gustaría definir las variables locales del subproceso usando pthread_key_create(), pero necesito hacerlo en la biblioteca, y no recibo ninguna llamada especial cuando se crea un subproceso.

¿Cómo creo una variable local de subproceso, solo si no existe? Algo así como

pthread_key_t tlsKey = 0; 
int x; 

myfunc() 
{ 
    if (pthread_key_t == 0){ 
     pthread_key_create(&tlsKey, NULL); 
     pthread_setspecific(tlsKey, &x); 
    } 
    int& myx = pthread_getspecific(tlskey); 
    if (myx == 0){ 
     myx=1; 
     something_under_myx_lock(); 
     myx = 0; 
    } else { 
     cout << "locked in thread\n"; 
    } 

}

Nota: si usted se pregunta, la razón por la que necesita un bloqueo dentro de la rosca es hacer de esta señal de la función de seguridad, así como el hilo de seguridad.

Respuesta

6

hacer algo una vez que utilice pthread_once:

pthread_key_t tls_key; 
pthread_once_t tls_init_flag=PTHREAD_ONCE_INIT; 

extern "C" 
{ 
    static void tls_destructor(void*); // run when thread exits to cleanup TLS data 
    static void create_tls_key() 
    { 
     if(pthread_key_create(&tls_key,tls_destructor)) 
     { 
      abort(); 
     } 
    } 
} 

pthread_key_t get_tls_key() 
{ 
    pthread_once(&tls_init_flag,create_tls_key); 
    return tls_key; 
} 

A continuación, puede llamar get_tls_key() con seguridad de su devolución de llamada para obtener la clave TLS sin preocuparse por la creación de dos llaves.

+0

¿Por qué el 'extern" C "'? – dbbd

+0

La pregunta está etiquetada como "C++", así que supongo que asker usa un compilador de C++. 'pthread_once' es una función C, y espera que la función pasada sea un puntero a una función C. Las funciones C++ y C no tienen necesariamente la misma convención de llamadas/ABI, por lo que 'extern" C "' es técnicamente necesario. En algunos compiladores/plataformas, puede omitirse. –