How to define thread-local local static variables?

17,606

Solution 1

on Windows using Windows API: TlsAlloc()/TlsSetValue()/TlsGetValue()

on Windows using compiler intrinsic: use _declspec(thread)

on Linux (other POSIX???) : get_thread_area() and related

Solution 2

Just use static and __thread in your function.

Example:

int test(void)
{
        static __thread a;

        return a++;
}

Solution 3

You can also use the C++11 thread local storage additions if you have access to C++11.

Solution 4

The current C standard has no model for threads or alike, so you can't get an answer, there.

The utility foreseen by POSIX for that is pthread_[gs]etspecific.

The next version of the C standard adds threads and has a concept of thread local storage.

Solution 5

You can make your own thread specific local storage as singleton per thread ID. Something like this:

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(); is a platform specific function for determining caller's thread id. Something like this:

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

Now, within a thread function you can use it's local storage:

void threadFunction(void*)
{
  StorageManager::threadLocalStorage()->my_static_variable_1 = 5; //every thread will have
                                                           // his own instance of local storage.
}
Share:
17,606
Hayri Uğur Koltuk
Author by

Hayri Uğur Koltuk

software engineer

Updated on June 12, 2022

Comments

  • Hayri Uğur Koltuk
    Hayri Uğur Koltuk almost 2 years

    How to define local static variables (that keeps its value between function calls) that are not shared among different threads?

    I am looking for an answer both in C and C++

  • Hayri Uğur Koltuk
    Hayri Uğur Koltuk over 12 years
    after reading on MSDN, Tls functions are exactly what i was looking for.
  • Mike Seymour
    Mike Seymour over 12 years
    @Ali: no, it's an extension provided by GCC and a few other compilers. On MSVC, I think you use __declspec(thread) instead.
  • Mike Seymour
    Mike Seymour over 12 years
    You'll also need synchronisation (such as a read/write mutex) to protect m_storages from access by multiple threads.
  • zhaorufei
    zhaorufei almost 11 years
    Not only m_storages, but also std::map and the locally "static StorageManager instance;" is not thread safe. In native code implement a high efficiency singleton is not a easy task, see "C++ and the Perils of Double-Checked Locking" by Scott Meyers and Andrei Alexandrescu. erdani.com/publications/DDJ_Jul_Aug_2004_revised.pdf
  • Erik Aronesty
    Erik Aronesty about 9 years
    __thread works on linux, bsd, aix, and with the xl_c, gcc, and many other compilers. it can be trivially #defined to __declspec(thread) on windows.
  • Lothar
    Lothar over 6 years
    It does not work with gcc or clang on macOS because it requires operating system support.