57 votes

Comment allouer thread local storage?

J'ai une variable dans ma fonction qui est statique, mais je voudrais qu'il soit statique par thread.

Comment puis-je allouer la mémoire de mon C++ de la classe de telle sorte que chaque thread possède 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 sur Linux. Je ne suis pas à l'aide de C++0x et c'est gcc v3.4.6.

69voto

ravenspoint Points 8840
#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();

64voto

Deqing Points 2178

Il est intéressant de noter que le C++11 introduit l' thread_local mot-clé.

Voici un exemple de durée de Stockage des prescripteurs:

#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");
    {
        std::lock_guard<std::mutex> lock(cout_mutex);
        std::cout << "Rage counter for main: " << rage << '\n';
    }

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

    return 0;
}

De sortie possibles:

Rage counter for a: 2
Rage counter for main: 1
Rage counter for b: 2

14voto

tvn Points 444

boost::thread_specific_ptr est le meilleur moyen, comme solution portable.

Sur Linux et GCC, vous pouvez utiliser __thread modificateur.

Si votre variable d'instance va ressembler:

static __thread MyClass *instance = new MyClass();

11voto

Jason Points 20479

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();
}

3voto

Nawaz Points 148870

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

Et puis vous pouvez voir cet exemple.

Aussi, soyez conscient des Règles et des Limites pour l'utilisation de TLS

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X