Where am I

24.17. Instance Thread Storage

OpenInventor 8.0 introduced an alternate and more convenient mechanism for implementing per-thread data called “instance thread storage”. It allows you to easily declare class members whose value is thread dependent. Thread dependent storage for class members is implemented using the SbThreadStorage <> template.

This template has been designed to minimize source code changes. Here is an example:

The class definition:

class myClass
    {
    ...
      ...
      private:
      Obj* m_obj;
    }

becomes:

class myClass
    {
    ...
      ...
      private:
      SbThreadStorage<Obj*> m_obj;
    }

In most cases you do not need to change the way this member variable is used in your source code. The SbThreadStorage template takes care of all the thread dependent stuff.

Typical usage:

if (m_obj != NULL)
    m_obj->getProp();

is unchanged:

if (m_obj != NULL)
    m_obj->getProp();

Using the SbThreadStorage template introduces some limitations and constraints on the templated objects.

  • Making a call to m_obj->getProp(), only makes a call to getProp() for the current thread. In order to apply a call to the object for all running threads, use the SbThreadStorage::call() method. (Note: The SbThreadStorage template does not lock access to the templated object in any way. Thus, concurrent access to an objects thread dependent members may require adding mutexes in its source code.) For example: if m_obj is an SoCache*, calling m_obj.call(&SoCache::invalidate) applies the invalidate() method call on the m_obj owned by each of the current threads. It may be necessary in this case to add a mutex to lock access to m_obj while doing this kind of operation.

  • Only object references are currently supported by the template.

  • The Delete operator cannot be used on templated objects. You will need to implement an unref() method.

These limitations can be easily worked around using two possible solutions:

  1. Specialize the SbThreadStorage to properly manage one specific object type.

  2. Build an inner class containing all the members that are thread dependent:

    class myClass
        {
        ...
          ...
          Class MyInnerClass
          {
          MyInnerClass() { ... }
          void unref() { delete this; }
          int m_1;
            MyObj* m_2;
          };
    
        SbThreadStorage< MyInnerClass *> m_obj;
        }