web-dev-qa-db-fra.com

Comment allouer le stockage local des threads?

J'ai une variable dans ma fonction qui est statique, mais j'aimerais qu'elle soit statique par thread.

Comment puis-je allouer la mémoire pour ma classe C++ de sorte que chaque thread ait sa propre copie de l'instance de classe?

AnotherClass::threadSpecificAction()
{
  // How to allocate this with thread local storage?
  static MyClass *instance = new MyClass();

  instance->doSomething();
}

C'est sous Linux. Je n'utilise pas C++ 0x et c'est gcc v3.4.6.

56
WilliamKF
#include <boost/thread/tss.hpp>
static boost::thread_specific_ptr< MyClass> instance;
if( ! instance.get() ) {
    // first time called by this thread
    // construct test element to be used in all subsequent calls from this thread
    instance.reset( new MyClass);
}
    instance->doSomething();
67
ravenspoint

Il est à noter que C++ 11 introduit le thread_local mot-clé.

Voici un exemple de spécificateurs de durée de stockage :

#include <iostream>
#include <string>
#include <thread>
#include <mutex>

thread_local unsigned int rage = 1; 
std::mutex cout_mutex;

void increase_rage(const std::string& thread_name)
{
    ++rage;
    std::lock_guard<std::mutex> lock(cout_mutex);
    std::cout << "Rage counter for " << thread_name << ": " << rage << '\n';
}

int main()
{
    std::thread a(increase_rage, "a"), b(increase_rage, "b");
    increase_rage("main");

    a.join();
    b.join();

    return 0;
}

Sortie possible:

Rage counter for a: 2
Rage counter for main: 2
Rage counter for b: 2
64
Deqing

boost::thread_specific_ptr est le meilleur moyen en tant que solution portable.

Sous Linux et GCC, vous pouvez utiliser __thread modificateur .

Votre variable d'instance ressemblera donc à:

static __thread MyClass *instance = new MyClass();
14
tvn

Si vous utilisez Pthreads, vous pouvez effectuer les opérations suivantes:

//declare static data members
pthread_key_t AnotherClass::key_value;
pthread_once_t AnotherClass::key_init_once = PTHREAD_ONCE_INIT;

//declare static function
void AnotherClass::init_key()
{
    //while you can pass a NULL as the second argument, you 
    //should pass some valid destrutor function that can properly
    //delete a pointer for your MyClass
    pthread_key_create(&key_value, NULL);
}

void AnotherClass::threadSpecificAction()
{
  //Initialize the key value
  pthread_once(&key_init_once, init_key);

  //this is where the thread-specific pointer is obtained
  //if storage has already been allocated, it won't return NULL

  MyClass *instance = NULL;
  if ((instance = (MyClass*)pthread_getspecific(key_value)) == NULL)
  {
    instance = new MyClass;
    pthread_setspecific(key_value, (void*)instance);
  }

  instance->doSomething();
}
11
Jason

C++ 11 spécifie un thread_local type de stockage, utilisez-le.

AnotherClass::threadSpecificAction()
{
  thread_local MyClass *instance = new MyClass();
  instance->doSomething();
}

Une optimisation facultative consiste également à allouer sur le stockage local des threads.

4
Arne

Si vous travaillez avec MSVC++, vous pouvez lire Thread Local Storage (TLS)

Et puis vous pouvez voir ceci exemple .

Faites également attention aux Règles et limitations pour TLS

3
Nawaz

Sous Windows, vous pouvez utiliser TlsAlloc et TlsFree pour allouer du stockage dans le stockage local des threads.

Pour définir et récupérer des valeurs avec TLS, vous pouvez utiliser TlsSetValue et TlsGetValue , respectivement

Ici vous pouvez voir un exemple sur la façon dont il serait utilisé.

3
Tony The Lion

Juste une note latérale ... MSVC++ prend en charge déclspec (thread) de VSC++ 2005

#if (_MSC_VER >= 1400)
  #ifndef thread_local     
    #define thread_local __declspec(thread)
  #endif
#endif

Le problème principal est (qui est résolu dans boost :: thread_specific_ptr) les variables marquées avec lui ne peuvent pas contenir ctor ou dtor.

2
Arek Bal

Folly (Facebook Open-source Library) a une implémentation portable de Thread Local Storage.

Selon ses auteurs:

Amélioration du stockage local des threads pour les types non triviaux (vitesse similaire à pthread_getspecific mais ne consomme qu'une seule pthread_key_t et 4x plus rapide que boost::thread_specific_ptr).

Si vous recherchez une implémentation portable de thread de stockage local, cette bibliothèque est une bonne option.

1
chema989