Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
allocatable.cc
Go to the documentation of this file.
1 
18 #include "ion/base/allocatable.h"
19 
20 #include <vector>
21 
22 #include "base/integral_types.h"
23 #include "ion/base/invalid.h"
24 #include "ion/base/lockguards.h"
27 
28 namespace ion {
29 namespace base {
30 
32 
83 
84 
85 class Allocatable::Helper {
86  public:
93  Helper()
94  : placement_allocator_(NULL) {}
95 
97  void AddAllocationData(const void* memory_ptr, size_t size,
98  Allocator* allocator) {
99  const void* end_ptr = reinterpret_cast<const uint8*>(memory_ptr) + size;
100  allocations_.push_back(AllocationData(MemoryRange(memory_ptr, end_ptr),
101  allocator, AllocationData::kNew));
102  }
103 
105  void AddPlacementAllocationData(const void* memory_ptr, size_t size,
106  Allocator* allocator) {
107  const void* end_ptr = reinterpret_cast<const uint8*>(memory_ptr) + size;
108  allocations_.push_back(AllocationData(MemoryRange(memory_ptr, end_ptr),
109  allocator,
110  AllocationData::kPlacement));
111  }
112 
114  void AddDeallocationData(const void *memory_ptr, Allocator* allocator) {
115  deallocations_.push_back(DeallocationData(memory_ptr, allocator));
116  }
117 
123  bool FindAllocationData(const void* instance_ptr, Allocator** allocator_out,
124  const void** memory_ptr_out);
125 
129  const AllocatorPtr FindDeallocationData(const void* memory_ptr);
130 
132  Allocator* GetPlacementAllocator() {
133  return placement_allocator_;
134  }
135 
137  void SetPlacementAllocator(Allocator* allocator) {
138  placement_allocator_ = allocator;
139  }
140 
141  private:
143  struct MemoryRange {
144  MemoryRange(const void* min_in, const void* max_in)
145  : min_address(min_in), max_address(max_in) {}
146  const void* min_address;
147  const void* max_address;
148  };
149 
152  struct AllocationData {
153  enum AllocationType {
154  kNew,
155  kPlacement
156  };
157  AllocationData(const MemoryRange& memory_range_in, Allocator* allocator_in,
158  AllocationType allocation_type_in)
159  : memory_range(memory_range_in),
160  allocator(allocator_in),
161  allocation_type(allocation_type_in) {}
163  MemoryRange memory_range;
165  Allocator* allocator;
169  AllocationType allocation_type;
170  };
171 
173  struct DeallocationData {
174  DeallocationData(const void* memory_ptr_in, Allocator* allocator_in)
175  : memory_ptr(memory_ptr_in), allocator(allocator_in) {}
177  const void* memory_ptr;
181  AllocatorPtr allocator;
182  };
183 
189  std::vector<AllocationData> allocations_;
190  std::vector<DeallocationData> deallocations_;
191  Allocator* placement_allocator_;
192 };
193 
194 bool Allocatable::Helper::FindAllocationData(const void* instance_ptr,
195  Allocator** allocator_out,
196  const void** memory_ptr_out) {
197  const size_t num_allocations = allocations_.size();
198  for (size_t i = 0; i < num_allocations; ++i) {
199  AllocationData& ad = allocations_[i];
200  const void* memory_start = ad.memory_range.min_address;
201  const void* memory_end = ad.memory_range.max_address;
202  if (memory_start <= instance_ptr && instance_ptr < memory_end) {
203  *allocator_out = ad.allocator;
207  *memory_ptr_out =
208  ad.allocation_type == AllocationData::kNew ? memory_start : NULL;
209  *memory_ptr_out = memory_start;
211  allocations_.erase(allocations_.begin() + i);
212  return true;
213  }
214  }
217  if (placement_allocator_) {
218  *allocator_out = placement_allocator_;
219  *memory_ptr_out = NULL;
220  return true;
221  }
223  return false;
224 }
225 
226 const AllocatorPtr Allocatable::Helper::FindDeallocationData(
227  const void* memory_ptr) {
228  DCHECK(memory_ptr);
229  const size_t num_deallocations = deallocations_.size();
230  AllocatorPtr allocator;
231  for (size_t i = 0; i < num_deallocations; ++i) {
232  DeallocationData& dd = deallocations_[i];
233  if (dd.memory_ptr == memory_ptr) {
234  allocator = dd.allocator;
235  deallocations_.erase(deallocations_.begin() + i);
236  break;
237  }
238  }
241  DCHECK(allocator.Get());
242  return allocator;
243 }
244 
246 
251 
252 
254  Construct();
255 }
256 
258  Construct();
259 }
260 
261 void Allocatable::Construct() {
264  Allocator* allocator;
265  const void* memory_ptr;
266  if (GetHelper()->FindAllocationData(this, &allocator, &memory_ptr)) {
267  allocator_.Reset(allocator);
268  memory_ptr_ = memory_ptr;
269  } else {
270  memory_ptr_ = NULL;
271  }
272 }
273 
275  : allocator_(allocator_in), memory_ptr_(NULL) {
276  Allocator* allocator;
277  const void* memory_ptr;
279  (void)allocator;
280  (void)memory_ptr;
282  DCHECK(!GetHelper()->FindAllocationData(this, &allocator, &memory_ptr))
283  << "Allocatable can take an AllocatorPtr in its constructor only when "
284  "created on the stack";
285 }
286 
290  if (memory_ptr_)
291  GetHelper()->AddDeallocationData(memory_ptr_, allocator_.Get());
292 }
293 
294 void* Allocatable::New(size_t size, const AllocatorPtr& allocator) {
296  DCHECK(a.Get());
297  void* memory_ptr = a->AllocateMemory(size);
300  if (memory_ptr)
301  GetHelper()->AddAllocationData(memory_ptr, size, a.Get());
302 
303  return memory_ptr;
304 }
305 
306 void Allocatable::Delete(void* memory_ptr) {
308  if (memory_ptr) {
310  AllocatorPtr allocator = GetHelper()->FindDeallocationData(memory_ptr);
311  DCHECK(allocator.Get());
312  allocator->DeallocateMemory(memory_ptr);
313  }
314 }
315 
316 void* Allocatable::PlacementNew(size_t size, const AllocatorPtr& allocator,
317  void* memory_ptr) {
318  if (memory_ptr)
319  GetHelper()->AddPlacementAllocationData(memory_ptr, size, allocator.Get());
320  return memory_ptr;
321 }
322 
323 Allocator* Allocatable::GetPlacementAllocator() {
324  return GetHelper()->GetPlacementAllocator();
325 }
326 
327 void Allocatable::SetPlacementAllocator(Allocator* allocator) {
328  GetHelper()->SetPlacementAllocator(allocator);
329 }
330 
331 Allocatable::Helper* Allocatable::GetHelper() {
334  ION_DECLARE_SAFE_STATIC_POINTER(ThreadLocalObject<Helper>, s_helper);
335  return s_helper->Get();
336 }
337 
338 } // namespace base
339 } // namespace ion
#define ION_DECLARE_SAFE_STATIC_POINTER(type, variable)
Declare a static non-array pointer and calls a default constructor.
base::AllocatorPtr allocator_
The Allocator for the FreeTypeManager and all its Fonts.
#define DCHECK(expr)
Definition: logging.h:331
virtual ~Allocatable()
The destructor clears the reference to the allocator.
Definition: allocatable.cc:287
SharedPtr< Allocator > AllocatorPtr
Definition: allocator.h:51
T * Get() const
Returns a raw pointer to the instance, which may be NULL.
Definition: sharedptr.h:89
static const AllocatorPtr & GetNonNullAllocator(const AllocatorPtr &allocator)
This convenience function can be used where a non-NULL Allocator pointer is needed.
Allocatable is an abstract base class for classes whose memory is managed by an Allocator.
Definition: allocatable.h:60
Allocatable()
This constructor sets up the Allocator pointer.
Definition: allocatable.cc:253
Allocator is an abstract base class for a memory allocator used for Ion objects derived from Allocata...
Definition: allocator.h:61
void Reset(T *new_shared)
Changes the pointer to point to the given shared, which may be NULL.
Definition: sharedptr.h:92
A SharedPtr is a smart shared pointer to an instance of some class that implements reference counting...
Definition: sharedptr.h:60