Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
staticsafedeclare.h
Go to the documentation of this file.
1 
18 #ifndef ION_BASE_STATICSAFEDECLARE_H_
19 #define ION_BASE_STATICSAFEDECLARE_H_
20 
21 #include <stdint.h>
22 
23 #include <type_traits>
24 #include <vector>
25 
26 #include "ion/base/lockguards.h"
27 #include "ion/base/shareable.h"
28 #include "ion/base/sharedptr.h"
29 #include "ion/base/static_assert.h"
30 #include "ion/port/atomic.h"
31 #include "ion/port/mutex.h"
32 
67 
70 #define ION_SAFE_ASSIGN_STATIC_POINTER( \
71  type, variable, new_variable, add_func, destroyer) \
72  type null = NULL; \
73  if (variable.compare_exchange_strong(null, new_variable)) { \
74  add_func(#type, new_variable); \
75  } else { \
76  destroyer new_variable; \
77  }
78 
80 #define ION_DECLARE_SAFE_STATIC( \
81  type, variable, constructor, add_func, destroyer) \
82  static std::atomic<type> atomic_##variable; /* Zero-initialized */ \
83  ION_STATIC_ASSERT(std::is_pointer<type>::value, \
84  "static variables must be of pointer type"); \
85  type variable = atomic_##variable.load(std::memory_order_acquire); \
86  if (variable == 0) { \
87  type new_##variable = constructor; \
88  ION_SAFE_ASSIGN_STATIC_POINTER( \
89  type, atomic_##variable, new_##variable, add_func, destroyer); \
90  variable = atomic_##variable.load(std::memory_order_acquire); \
91  }
92 
94 
99 
100 
102 #define ION_DECLARE_SAFE_STATIC_ARRAY(type, variable, count) \
103  ION_DECLARE_SAFE_STATIC( \
104  type*, \
105  variable, \
106  new type[count], \
107  ion::base::StaticDeleterDeleter::GetInstance()->AddArrayToDelete, \
108  delete[])
109 
111 #define ION_DECLARE_SAFE_STATIC_POINTER(type, variable) \
112  ION_DECLARE_SAFE_STATIC( \
113  type*, \
114  variable, \
115  new type, \
116  ion::base::StaticDeleterDeleter::GetInstance()->AddPointerToDelete, \
117  delete)
118 
122 #define ION_DECLARE_SAFE_STATIC_POINTER_WITH_CONSTRUCTOR( \
123  type, variable, constructor) \
124  ION_DECLARE_SAFE_STATIC( \
125  type*, \
126  variable, \
127  constructor, \
128  ion::base::StaticDeleterDeleter::GetInstance()->AddPointerToDelete, \
129  delete)
130 
131 namespace ion {
132 namespace base {
133 
135  public:
136  explicit StaticDeleterBase(const std::string& name) : type_name_(name) {}
137  virtual ~StaticDeleterBase() {}
138 
140  const std::string& GetTypeName() const { return type_name_; }
141 
142  protected:
143  std::string type_name_;
144 };
145 
151 template <typename T> class StaticDeleter : public StaticDeleterBase {
152  public:
153  StaticDeleter(const std::string& name, T* pointer_to_delete)
154  : StaticDeleterBase(name),
155  pointer_to_delete_(pointer_to_delete) {}
156 
157  private:
160  ~StaticDeleter() override {
161  delete pointer_to_delete_;
162  }
163 
165  T* pointer_to_delete_;
166 };
167 
169 template <typename T> class StaticDeleter<T[]> : public StaticDeleterBase {
170  public:
171  StaticDeleter(const std::string& name, T* pointer_to_delete)
172  : StaticDeleterBase(name),
173  pointer_to_delete_(pointer_to_delete) {}
174 
175  private:
178  ~StaticDeleter() override {
179  delete [] pointer_to_delete_;
180  }
181 
183  T* pointer_to_delete_;
184 };
185 
192 class ION_API StaticDeleterDeleter : public Shareable {
193  public:
195  ~StaticDeleterDeleter() override;
196 
198  template <typename T>
199  void AddPointerToDelete(const std::string& name, T* ptr) {
200  LockGuard locker(&mutex_);
201  deleters_.push_back(new StaticDeleter<T>(name, ptr));
202  }
204  template <typename T>
205  void AddArrayToDelete(const std::string& name, T* ptr) {
206  LockGuard locker(&mutex_);
207  deleters_.push_back(new StaticDeleter<T[]>(name, ptr));
208  }
211  template <typename T>
212  void IgnoreInstance(const std::string& name, const T& ptr) {}
213 
215  static StaticDeleterDeleter* GetInstance();
216 
219  const StaticDeleterBase* GetDeleterAt(size_t index) const {
220  return index < deleters_.size() ? deleters_[index] : NULL;
221  }
222 
224  size_t GetDeleterCount() const { return deleters_.size(); }
225 
233  static void DestroyInstance();
234 
235  private:
239  static void SetInstancePtr(const std::string&,
240  StaticDeleterDeleter* instance);
241 
242  std::vector<StaticDeleterBase*> deleters_;
243 
246 };
247 
248 } // namespace base
249 } // namespace ion
250 
251 #endif // ION_BASE_STATICSAFEDECLARE_H_
StaticDeleter(const std::string &name, T *pointer_to_delete)
const std::string & GetTypeName() const
Returns the name of the type this deleter deletes.
const StaticDeleterBase * GetDeleterAt(size_t index) const
Returns the deleter at the passed index.
size_t GetDeleterCount() const
Returns the number of deleters in this.
void IgnoreInstance(const std::string &name, const T &ptr)
Does nothing, but simplifies the above macros for static non-pointer instances.
StaticDeleterDeleter is an internal class that holds and deletes StaticDeleters; it should not be use...
Shareable is an abstract base class for any object that can be shared via the SharedPtr class...
Definition: shareable.h:31
void AddPointerToDelete(const std::string &name, T *ptr)
Adds a regular pointer to be deleted when this class is destroyed.
A LockGuard locks a mutex when created, and unlocks it when destroyed.
Definition: lockguards.h:90
std::string name
Definition: printer.cc:324
StaticDeleterBase(const std::string &name)
void AddArrayToDelete(const std::string &name, T *ptr)
Adds an array pointer to be deleted when this class is destroyed.
This class should not be used directly.
port::Mutex mutex_
Protects shared access to the Allocator and FT_Library.
A Mutex is used to ensure that only one thread or process can access a block of code at one time...
Definition: mutex.h:34
StaticDeleter(const std::string &name, T *pointer_to_delete)