Как определить локальные потоковые локальные статические переменные? - PullRequest
21 голосов
/ 30 сентября 2011

Как определить локальные статические переменные (которые сохраняют свое значение между вызовами функций), которые не используются разными потоками?

Я ищу ответ как на C, так и на C ++

Ответы [ 5 ]

12 голосов
/ 30 сентября 2011

в Windows с использованием Windows API: TlsAlloc () / TlsSetValue () / TlsGetValue ()

в Windows с использованием встроенного компилятора: используйте _declspec (thread)

в Linux (другой POSIX ???): get_thread_area () и связанных

9 голосов
/ 30 сентября 2011

Просто используйте static и __thread в своей функции.

Пример:

int test(void)
{
        static __thread a;

        return a++;
}
2 голосов
/ 30 сентября 2011

Вы также можете использовать дополнения локального хранилища потока C ++ 11, если у вас есть доступ к C ++ 11.

2 голосов
/ 30 сентября 2011

В текущем стандарте C нет модели для потоков или тому подобного, поэтому вы не можете получить ответ.

Предусмотренная POSIX утилита для этого pthread_[gs]etspecific.

Следующая версия стандарта C добавляет потоки и имеет понятие локальное хранилище потоков .

1 голос
/ 30 сентября 2011

Вы можете создать свое собственное локальное хранилище для отдельных потоков в виде идентификатора для каждого потока. Примерно так:

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 (); является платформо-зависимой функцией для определения идентификатора потока вызывающей стороны. Примерно так:

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

Теперь внутри функции потока вы можете использовать ее локальное хранилище:

void threadFunction(void*)
{
  StorageManager::threadLocalStorage()->my_static_variable_1 = 5; //every thread will have
                                                           // his own instance of local storage.
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...