2011-09-30 17 views
19

Come definire le variabili statiche locali (che mantengono il suo valore tra le chiamate di funzione) che non sono condivise tra thread diversi?Come definire variabili locali statiche locali del thread?

Sto cercando una risposta sia in C e C++

+0

Quale sistema operativo stai utilizzando? TLS non è portabile tra unixen e windows. – bdonlan

+3

C++ 11 introduce un'altra durata di memorizzazione chiamata ['thread_local'] (http://en.cppreference.com/w/cpp/language/storage_duration). Prova a usarlo. – Nawaz

+0

Il sistema operativo è Windows ... –

risposta

9

su Windows utilizzando API di Windows: TlsAlloc()/TlsSetValue()/TlsGetValue()

su Windows usando il compilatore intrinseca: utilizzare _declspec(thread)

su Linux (diverse POSIX? ??): get_thread_area() e relativi

+0

dopo aver letto su MSDN, le funzioni di Tls sono esattamente ciò che stavo cercando. –

+2

hai dimenticato TlsFree :-) –

2

L'attuale standard di C non ha alcun modello per le discussioni o simili, quindi non è possibile ottenere una risposta, lì.

L'utilità prevista da POSIX è pthread_[gs]etspecific.

La versione successiva dello standard C aggiunge thread e ha un concetto di memoria locale .

-3

È possibile creare una struttura dati allocata dall'heap per ogni thread.

Esempio:

struct ThreadLocal 
{ 
    int var1; 
    float var2; 
    //etc.. 
} 
8

Basta usare static e __thread nella tua funzione.

Esempio:

int test(void) 
{ 
     static __thread a; 

     return a++; 
} 
+3

è standard __thread? –

+2

@Ali: no, è un'estensione fornita da GCC e alcuni altri compilatori. Su MSVC, penso che tu usi '__declspec (thread)'. –

+3

__thread funziona su linux, bsd, aix e con xl_c, gcc e molti altri compilatori. può essere banalmente # definito su __declspec (thread) su Windows. –

1

È possibile rendere il proprio specifico thread storage locale come Singleton per ID thread. Qualcosa del genere:

struct ThreadLocalStorage 
{ 
    ThreadLocalStorage() 
    { 
     // initialization here 
    } 
    int my_static_variable_1; 
    // more variables 
}; 

class StorageManager 
{ 
    std::map<int, ThreadLocalStorage *> m_storages; 

    ~StorageManager() 
    { // storage cleanup 
     std::map<int, ThreadLocalStorage *>::iterator it; 
     for(it = m_storages.begin(); it != m_storages.end(); ++it) 
      delete it->second; 
    } 

    ThreadLocalStorage * getStorage() 
    { 
     int thread_id = GetThreadId(); 
     if(m_storages.find(thread_id) == m_storages.end()) 
     { 
      m_storages[thread_id] = new ThreadLocalStorage; 
     } 

     return m_storages[thread_id]; 
    } 

public: 
    static ThreadLocalStorage * threadLocalStorage() 
    { 
     static StorageManager instance; 
     return instance.getStorage(); 
    } 
}; 

GetThreadId(); è una funzione specifica della piattaforma per determinare l'id del thread del chiamante. Qualcosa di simile a questo:

int GetThreadId() 
{ 
    int id; 
#ifdef linux 
    id = (int)gettid(); 
#else // windows 
    id = (int)GetCurrentThreadId(); 
#endif 
    return id; 
} 

Ora, all'interno di una funzione filo è possibile utilizzare sia l'archiviazione locale:

void threadFunction(void*) 
{ 
    StorageManager::threadLocalStorage()->my_static_variable_1 = 5; //every thread will have 
                  // his own instance of local storage. 
} 
+0

Avrai anche bisogno della sincronizzazione (come un mutex di lettura/scrittura) per proteggere 'm_storages' dall'accesso da più thread. –

+0

ovviamente. hai ragione. – GreenScape

+0

Non solo m_storages, ma anche std :: map e localmente "istanza di StorageManager statico"; non è thread-safe In codice nativo implementare un singleton ad alta efficienza non è un compito facile, vedi "C++ ei pericoli del blocco a doppio controllo" di Scott Meyers e Andrei Alexandrescu. http://erdani.com/publications/DDJ_Jul_Aug_2004_revised.pdf – zhaorufei

2

È inoltre possibile utilizzare le C++ 11 Discussione aggiunte di archiviazione locale se si ha accesso a C++ 11.

Problemi correlati