2011-09-30 7 views
19

Comment définir des variables statiques locales (qui gardent leur valeur entre les appels de fonction) qui ne sont pas partagées entre différents threads?Comment définir des variables statiques locales locales au thread?

Je cherche une réponse à la fois en C et C++

+0

Quel système d'exploitation utilisez-vous? TLS n'est pas portable entre unixen et Windows. – bdonlan

+3

C++ 11 introduit une autre durée de stockage appelée ['thread_local'] (http://en.cppreference.com/w/cpp/language/storage_duration). Essayez de l'utiliser. – Nawaz

+0

OS est Windows ... –

Répondre

9

sur Windows en utilisant l'API de Windows: TlsAlloc()/TlsSetValue()/TlsGetValue()

sur Windows en utilisant le compilateur intrinsèque: utilisez _declspec(thread)

sur Linux (système POSIX? ??): get_thread_area() et connexes

+0

après avoir lu sur MSDN, les fonctions Tls sont exactement ce que je cherchais. –

+2

vous avez oublié TlsFree :-) –

2

La norme actuelle de C n'a pas de modèle pour les fils ou aussi bien, vous ne pouvez pas obtenir une réponse, là. L'utilité prévue par POSIX est pthread_[gs]etspecific.

La prochaine version de la norme C ajoute des threads et a un concept de stockage local de thread .

-3

Vous pouvez créer une structure de données allouée à partir du tas pour chaque thread.

Exemple:

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

Utilisez simplement static et __thread dans votre fonction.

Exemple:

int test(void) 
{ 
     static __thread a; 

     return a++; 
} 
+3

est __thread standard? –

+2

@Ali: non, c'est une extension fournie par GCC et quelques autres compilateurs. Sur MSVC, je pense que vous utilisez '__declspec (thread)' à la place. –

+3

__thread fonctionne sur linux, bsd, aix, et avec xl_c, gcc, et beaucoup d'autres compilateurs. il peut être trivialement # défini à __declspec (thread) sur windows. –

1

Vous pouvez faire votre propre fil spécifique de stockage local singleton par ID de fil. Quelque chose comme ceci:

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(); est une fonction spécifique à la plateforme pour déterminer l'identifiant du thread de l'appelant. Quelque chose comme ceci:

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

maintenant, dans une fonction de fil que vous pouvez utiliser est le stockage local:

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

Vous aurez également besoin d'une synchronisation (comme un mutex en lecture/écriture) pour protéger 'm_storages' de l'accès par plusieurs threads. –

+0

bien sûr. vous avez raison. – GreenScape

+0

Non seulement m_storages, mais aussi std :: map et l'instance "StorageManager statique" localement; n'est pas thread-safe. En implémentation de code natif, un singleton à haute efficacité n'est pas une tâche facile, voir "C++ et les dangers du verrouillage à double vérification" par Scott Meyers et Andrei Alexandrescu. http://erdani.com/publications/DDJ_Jul_Aug_2004_revised.pdf – zhaorufei

2

Vous pouvez également utiliser les modules de stockage local de fil 11 C++ si vous avez accès à C++ 11.