Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
threadlocalobject.h
Go to the documentation of this file.
1 
18 #ifndef ION_BASE_THREADLOCALOBJECT_H_
19 #define ION_BASE_THREADLOCALOBJECT_H_
20 
21 #include <vector>
22 
23 #include "ion/base/allocatable.h"
24 #include "ion/base/allocator.h"
25 #include "ion/base/lockguards.h"
26 #include "ion/base/type_structs.h"
27 #include "ion/port/mutex.h"
28 #include "ion/port/threadutils.h"
29 
30 namespace ion {
31 namespace base {
32 
71 template <typename T> class ThreadLocalObject {
72  public:
76  : key_(port::CreateThreadLocalStorageKey()) {}
77 
80  explicit ThreadLocalObject(const AllocatorPtr& allocator)
81  : key_(port::CreateThreadLocalStorageKey()),
82  allocator_(allocator) {}
83 
86  DestroyAllInstances();
90  }
91 
94  const port::ThreadLocalStorageKey& GetKey() const { return key_; }
95 
99  T* Get() {
100  if (void* ptr = port::GetThreadLocalStorage(key_))
101  return static_cast<T*>(ptr);
102  else
103  return CreateAndStoreInstance();
104  }
105 
106  private:
109  template <typename InstanceType, bool IsAllocatable = false>
110  struct AllocationHelper {
111  static InstanceType* Allocate(const AllocatorPtr& allocator) {
112  return new InstanceType();
113  }
114  };
115  template <typename InstanceType> struct AllocationHelper<InstanceType, true> {
116  static InstanceType* Allocate(const AllocatorPtr& allocator) {
117  return new(allocator) InstanceType();
118  }
119  };
120 
123  T* CreateAndStoreInstance() {
124  T* instance = NULL;
125  if (key_ != port::kInvalidThreadLocalStorageKey) {
126  instance = AllocateInstance(allocator_);
127  port::SetThreadLocalStorage(key_, instance);
128  LockGuard guard(&mutex_);
129  instances_.push_back(instance);
130  }
131  return instance;
132  }
133 
136  static T* AllocateInstance(const AllocatorPtr& allocator) {
138  return HelperType::Allocate(allocator);
139  }
140 
142  void DestroyAllInstances() {
143  LockGuard guard(&mutex_);
144  const size_t num_instances = instances_.size();
145  for (size_t i = 0; i < num_instances; ++i)
146  delete instances_[i];
147  instances_.clear();
148  }
149 
153  AllocatorPtr allocator_;
155  std::vector<T*> instances_;
157  port::Mutex mutex_;
158 };
159 
160 } // namespace base
161 } // namespace ion
162 
163 #endif // ION_BASE_THREADLOCALOBJECT_H_
ThreadLocalStorageKey CreateThreadLocalStorageKey()
Thread-local storage functions.
Definition: threadutils.cc:367
GenericLockGuard< port::Mutex > LockGuard
Convenient typedefs for ion::port::Mutex.
Definition: lockguards.h:192
double value
ThreadLocalObject(const AllocatorPtr &allocator)
This constructor uses the given Allocator to construct T instances.
ThreadLocalObject()
The default constructor will use global operator new() to construct T instances.
SharedPtr< Allocator > AllocatorPtr
Definition: allocator.h:51
bool SetThreadLocalStorage(ThreadLocalStorageKey key, void *ptr)
Associates ptr with the thread-local storage area indicated by key.
Definition: threadutils.cc:374
pthread_key_t ThreadLocalStorageKey
Defines a type that is used to access thread-local storage.
Definition: threadutils.h:42
T * Get()
Returns a T instance for the current thread, creating it first if necessary.
const port::ThreadLocalStorageKey & GetKey() const
Returns the ThreadLocalStorageKey created by the instance.
void * GetThreadLocalStorage(ThreadLocalStorageKey key)
Returns the pointer to the thread-local storage area indicated by key.
Definition: threadutils.cc:382
bool DeleteThreadLocalStorageKey(ThreadLocalStorageKey key)
Deletes a key returned by CreateThreadLocalStorageKey().
Definition: threadutils.cc:387
This templated class makes it easy to create an instance of an object in thread-local storage...