### IThreadLocalStorage

  IThreadLocalStorage is a mechanism for creating per-thread data storage in a typesafe and convenient way. Most operating systems provide a mechanism to have data that is replicated for each thread. This provides a very easy means for subsystems to maintain information or context for multiple threads that might be concurrently using its services. However, the operating system interfaces for such storage is usually clunky and typeless. IThreadLocalStorage brings these APIs to you in a much more powerful way.

  When you create a thread local storage object, it automatically sets up per-thread storage for you. It lazily creates storage as required so its efficient. Since it is a template class, you must specialize it for a particular class type, which makes it typesafe as well. Once an object is created, each thread can treat it as though it were the only user of the object.

  In effect, IThreadLocalStorage is like a smart pointer except that it provides a unique pointer for each thread.

### IThreadLocalStorage - Member Functions and Data by Group

### Constructors & Destructor

Construct and destruct IThreadLocalStorage objects.

~IThreadLocalStorage

      public:
      ~IThreadLocalStorage()

  The destructor will free the data object for the thread in which the destructor occurs. The data object for for other threads that have used this object are not freed. They will be freed when those threads call freeAllStorage().

Supported Platforms

  Windows | OS/2 | AIX
  Yes | Yes | Yes

IThreadLocalStorage
  The thread local storage constructors set up the internal data structures required to track all of the threads that use the new thread local sorage object. It does NOT create any actual data yet. Each thread must create its own data, though it is usually done on the thread's behalf by subsystem code into which the threads call.

  Overload 1

      public:
      IThreadLocalStorage(const bool resettable)

  This constructor does the same as the default except that it allows you to indicate whether a thread's data can be overwritten. If you pass false, then multiple sets of a thread's pointer will cause an IInvalidRequest exception.

Supported Platforms

  Windows | OS/2 | AIX
  Yes | Yes | Yes

  Overload 2

      public:
      IThreadLocalStorage()

  The default constructor is the most often used constructor. A default constructed object does not allow multiple sets of the data objects. I.e., once a thread calls adoptStorage() it cannot call adoptStorage() again to overwrite the previous object. Since many uses of thread local data have this type of semantics, the class provides this checking to insure that overwrites do not happen accidentally.

Supported Platforms

  Windows | OS/2 | AIX
  Yes | Yes | Yes

### Access Operators

These operators allow you to access the stored data pointer. These only allow the calling thread to access the copy of the object that belongs to it!

operator *

      public:
      AType& operator *() const

  Returns a reference to the data object, when the thread local storage object is dereferenced. This is a convenience to allow you to assign objects to the data object easily or to use the data object easily directly from the thread local object.

Supported Platforms

  Windows | OS/2 | AIX
  Yes | Yes | Yes

operator ->

      public:
      AType* operator ->() const

  Returns a pointer to the data object, when the thread local storage object is dereferenced. This is a convenience to allow you to use the data object easily directly from the thread local object.

Supported Platforms

  Windows | OS/2 | AIX
  Yes | Yes | Yes

### Storage Management Methods

These methods allow you to manage the object stored in the thread local storage object. These methods only work on the copy of the object that belongs to the calling thread!

adoptStorage

      public:
      void adoptStorage(AType* toadopt)

  This method is called to store the storage for the calling thread. When a thread local object is created, it has no way of knowing how many threads are out there or whether they will ever need to use this object. So the construction of the thread local object does not create the data storage for each thread. That must be done within the context of each thread. So, if storage() returns 0, that means there is no object for the calling thread and adoptStorage() should be called to create a new object for the calling thread.

  If a thread never accesses a thread local storage object, then no data will ever be created for that thread. This is an efficient and simple approach, but it does mean that you must always check for the existence of the data (and allocate it if not) before accessing it.

  Note that each thread local storage object can be set up to allow or disallow multiple sets of the data object. If the object allows it, then calling adoptStorage() again will cause the previous object to be deleted and the new object stored. If the object does not allow it, then an InvalidRequest exception is thrown.

Exception

  IInvalidRequest | is thrown if the calling thread has already stored an object, and this object does not allow resetting of the data value. The ability to reset is indicated during construction.

Supported Platforms

  Windows | OS/2 | AIX
  Yes | Yes | Yes

freeStorage

      public:
      void freeStorage()

  This method will free the data object for the calling thread and will set the pointer for that thread back to 0. Subsequent calls to the same thread local storage object on that thread will return zero, until adoptStorage() is called again to store another data object.

Supported Platforms

  Windows | OS/2 | AIX
  Yes | Yes | Yes

get

      public:
      AType* get() const

  get() is a deprecated method that does the same thing as storage(). It is only maintained for backwards compability.

Supported Platforms

  Windows | OS/2 | AIX
  Yes | Yes | Yes

storage

      public:
      AType* storage() const

  Returns a pointer to the data object for the calling thread. If adoptStorage() has not been called (or it has but freeStorage() has been called since then), the return will be zero. Otherwise, it will be the pointer to the stored data object for the calling thread. This function does the same thing as the -> operator basically, so you can use whichever one you feel more comfortable with. The -> operator provides cleaner syntax for accessing the methods of the data object in general.

Supported Platforms

  Windows | OS/2 | AIX
  Yes | Yes | Yes

### IThreadLocalStorage - Inherited Member Functions and Data

#### Inherited Public Functions

  IThreadLocalBase

  -     static void freeAllStorage()

#### Inherited Public Data

  - None

#### Inherited Protected Functions

  IThreadLocalBase

  -     virtual ~IThreadLocalBase()

  -     void expandThreadSlots(const unsigned long newcount)

  -     virtual void freeStorage() = 0

  -     unsigned long getNextSlot()

  -     void* getSlot(const unsigned long index) const

  -     IThreadLocalBase()

  -     IThreadLocalBase(const IThreadLocalBase&)

  -     IThreadLocalBase& operator =(const IThreadLocalBase)

  -     void setSlot(const unsigned long index, void* data)

#### Inherited Protected Data

  - None