views:

268

answers:

6

What is a good way to implement a singleton that will be restricted only to the thread that seeks its instance? Is there a thread id or something that I can use to do that? I'm using Carbon threading API but will have to implement this on windows and pure POSIX later too, so any technique is appreciated.

+2  A: 

How about something similar to ThreadLocal in Java? Posix/Carbon should have something ThreadLocal right?

Satish
Yep, I didn't look enough before asking a question. There seems to be a pthread_self function in POSIX that returns the current thread id.http://opengroup.org/onlinepubs/007908775/xsh/pthread_self.html
toastie
+1  A: 

In the past, I have leveraged a hashmap or index to store data structures that are per-thread inside of a single global thread-safe data structure. For instance, if you provide the id for each thread as an incrementing integer, you can store your data structure in a pre-allocated array at the index of the thread it. If you are leveraging thread IDs that are provided by the operating system or need to be more flexible, then a thread safe HashMap or HashTable will come in quite handy.

Jacob

TheJacobTaylor
A: 

I'm not sure whether this will answer your question, but in my Design Pattern class, I've learned something like this:

- (id) getInstance{
     @synchronized(self){
          if (mySingletonInstance == nil){
               @synchronized(self){
                   mySingletonInstance = [[mySingleton alloc] init];
               }
          }
     }
     return mySingletonInstance;
}

Although the code is in Objective-C, the idea should be about the same in other language, IMHO.

unknownthreat
+1  A: 

I'd want to put the singleton pointer into whatever the system's thread local storage method is. You've named several, and I don't know the right incantations for them, but most threading systems have some kind of thread local storage concept.

If your threading system does not, AND your threading system does have a unique thread identifier, then a hash table (keyed by thread id) is probably your best bet.

Michael Kohne
A: 

If you're happy with pthreads, you should be looking at

This should cover OSX and linux (I haven't used Carbon, but I'm guessing that it uses real OS threads and therefore plays nicely with pthreads).

Windows has the same basic idea with different names and a slightly different interface:

http://msdn.microsoft.com/en-us/library/ms686991.aspx

This allows you to access the "singleton"(*) for a thread only from that thread, but it sounds like that's what you want. If you want to be able to access any thread's object from any other thread, then you need a structure keyed on a pthread_t, and almost certainly some synchronisation. You get pthread_t values (that is, thread IDs) from pthread_self or pthread_create.

(*) If you have one per thread, it's technically not a singleton...

Steve Jessop
A: 

We use a class that stores a map of thread id to data to implement our thread local storage. This seems to work very well, then an instance of this class can be placed anywhere you require thread local storage. Normally clients use an instance of as a static private field.

Here is a rough outline of the code

template <class T>
struct ThreadLocal {
    T & value()
    {
        LockGuard<CriticalSection> lock(m_cs);

        std::map<int, T>::iterator itr = m_threadMap.find(Thread::getThreadID());

        if(itr != m_threadMap.end())
                return itr->second;

        return m_threadMap.insert(
                std::map<int, T>::value_type(BWThread::getThreadID(), T()))
                        .first->second;
    }

    CriticalSection             m_cs;
    std::map<int, T>    m_threadMap;
};

This is then used as

class A {
    // ...

    void doStuff();
private:
   static ThreadLocal<Foo> threadLocalFoo;
};

ThreadLocal<Foo> A::threadLocalFoo;

void A::doStuff() {
    // ...
    threadLocalFoo.value().bar();
    // ...
}

This is simple and works on any platform where you can get the thread id. Note the Critical Section is only used to return/create the reference, once you have the reference all calls are outside the critical section.

iain