thread_specific_ptr

This is a way to create "thread specific data". For example, you could create a "global" variable that is global to all functions, but local to each thread that accesses it. For example, errno is often implemented this way.

Metrowerks::thread_specific_ptr is a templated smart pointer that you can pass a new pointer to. It will associate that pointer with whatever thread passed it in (via its reset function). Other threads won't see that pointer. They will see NULL until they pass in their own heap-based data. The smart pointer will take care of releasing the heap data when the thread exits.

Listing: Class thread_specific_ptr synopsis
template <typename T>
class thread_specific_ptr
{
public:
    thread_specific_ptr();
    ~thread_specific_ptr();
    T* get() const;
    T* operator->() const {return get();}
    T& operator*() const  {return *get();}
    T* release();
   void reset(T* p = 0);
};

You can have as many thread_specific_ptr's as you want, and pointing to whatever type you desire. The thread_specific_ptr is not copyable or assignable, but you can assign a pointer to it.

Listing: Example of assigning a pointer
thread_specific_ptr<int> my_data;
...
my_data.reset(new int(3));
From then on, the thread that called reset can access that data like:
std::cout << *my_data;
*my_data = 4;
// etc.

You can release the memory with my_data.release(). This transfers pointer ownership back to you, so you must then delete the pointer. But you need not call release just to prevent memory leaks. thread_specific_ptr will automatically delete its data. And you can put in a new pointer by calling reset again. thread_specific_ptr will make sure the original pointer gets properly deleted. Do not use the array form of new with thread_specific_ptr. It will be using delete to free your pointer.

Listing: Example of freeing a pointer
#include <iostream>
#include <ewl_thread>

Metrowerks::thread_specific_ptr<int> value;
void increment()
{
   ++*value;
}

Metrowerks::mutex cout_mutex;
void thread_proc()
{
    value.reset(new int(0));
    for (int i = 0; i < 1000; ++i)
        increment();

    Metrowerks::mutex::scoped_lock lock(cout_mutex);
    std::cout << *value << '
}

int main()
{
    Metrowerks::thread_group threads;
    for (int i = 0; i < 5; ++i)
        threads.create_thread(&thread_proc);

    thread_proc();
    threads.join_all();
}

Should print out

 1000

  1000

  1000

  1000

  1000

  1000  

Once for main, and once for the five threads. Note how no locking is necessary in accessing the "global" thread_specific_ptr. It is as if each thread has its own local copy of this global.