Panda3D
deletedBufferChain.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file deletedBufferChain.cxx
10  * @author drose
11  * @date 2007-07-20
12  */
13 
14 #include "deletedBufferChain.h"
15 #include "memoryHook.h"
16 
17 /**
18  * Use the global MemoryHook to get a new DeletedBufferChain of the
19  * appropriate size.
20  */
21 DeletedBufferChain::
22 DeletedBufferChain(size_t buffer_size) {
23  _deleted_chain = nullptr;
24  _buffer_size = buffer_size;
25 
26  // We must allocate at least this much space for bookkeeping reasons.
27  _buffer_size = std::max(_buffer_size, sizeof(ObjectNode));
28 }
29 
30 /**
31  * Allocates the memory for a new buffer of the indicated size (which must be
32  * no greater than the fixed size associated with the DeletedBufferChain).
33  */
35 allocate(size_t size, TypeHandle type_handle) {
36 #ifdef USE_DELETED_CHAIN
37  // TAU_PROFILE("void *DeletedBufferChain::allocate(size_t, TypeHandle)", "
38  // ", TAU_USER);
39  assert(size <= _buffer_size);
40 
41  // Determine how much space to allocate.
42  const size_t alloc_size = _buffer_size + flag_reserved_bytes + MEMORY_HOOK_ALIGNMENT - 1;
43 
44  ObjectNode *obj;
45 
46  _lock.lock();
47  if (_deleted_chain != nullptr) {
48  obj = _deleted_chain;
49  _deleted_chain = _deleted_chain->_next;
50  _lock.unlock();
51 
52 #ifdef USE_DELETEDCHAINFLAG
53  assert(obj->_flag == (AtomicAdjust::Integer)DCF_deleted);
54  obj->_flag = DCF_alive;
55 #endif // USE_DELETEDCHAINFLAG
56 
57  void *ptr = node_to_buffer(obj);
58 
59 #ifdef DO_MEMORY_USAGE
60  // type_handle.dec_memory_usage(TypeHandle::MC_deleted_chain_inactive,
61  // alloc_size);
62  type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, alloc_size);
63 #endif // DO_MEMORY_USAGE
64 
65  return ptr;
66  }
67  _lock.unlock();
68 
69  // If we get here, the deleted_chain is empty; we have to allocate a new
70  // object from the system pool.
71 
72  // Allocate memory, and make sure the object starts at the proper alignment.
73  void *mem = NeverFreeMemory::alloc(alloc_size);
74  uintptr_t aligned = ((uintptr_t)mem + flag_reserved_bytes + MEMORY_HOOK_ALIGNMENT - 1) & ~(MEMORY_HOOK_ALIGNMENT - 1);
75  obj = (ObjectNode *)(aligned - flag_reserved_bytes);
76 
77 #ifdef USE_DELETEDCHAINFLAG
78  obj->_flag = DCF_alive;
79 #endif // USE_DELETEDCHAINFLAG
80 
81  void *ptr = node_to_buffer(obj);
82 
83 #ifndef NDEBUG
84  assert(((uintptr_t)ptr % MEMORY_HOOK_ALIGNMENT) == 0);
85 #endif
86 
87 #ifdef DO_MEMORY_USAGE
88  type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, alloc_size);
89 #endif // DO_MEMORY_USAGE
90 
91  return ptr;
92 
93 #else // USE_DELETED_CHAIN
94  return PANDA_MALLOC_SINGLE(_buffer_size);
95 #endif // USE_DELETED_CHAIN
96 }
97 
98 /**
99  * Frees the memory for a buffer previously allocated via allocate().
100  */
102 deallocate(void *ptr, TypeHandle type_handle) {
103 #ifdef USE_DELETED_CHAIN
104  // TAU_PROFILE("void DeletedBufferChain::deallocate(void *, TypeHandle)", "
105  // ", TAU_USER);
106  assert(ptr != nullptr);
107 
108 #ifdef DO_MEMORY_USAGE
109  const size_t alloc_size = _buffer_size + flag_reserved_bytes + MEMORY_HOOK_ALIGNMENT - 1;
110  type_handle.dec_memory_usage(TypeHandle::MC_deleted_chain_active, alloc_size);
111  // type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_inactive,
112  // _buffer_size + flag_reserved_bytes);
113 
114 #endif // DO_MEMORY_USAGE
115 
116  ObjectNode *obj = buffer_to_node(ptr);
117 
118 #ifdef USE_DELETEDCHAINFLAG
119  AtomicAdjust::Integer orig_flag = AtomicAdjust::compare_and_exchange(obj->_flag, DCF_alive, DCF_deleted);
120 
121  // If this assertion is triggered, you double-deleted an object.
122  assert(orig_flag != (AtomicAdjust::Integer)DCF_deleted);
123 
124  // If this assertion is triggered, you tried to delete an object that was
125  // never allocated, or you have heap corruption.
126  assert(orig_flag == (AtomicAdjust::Integer)DCF_alive);
127 #endif // USE_DELETEDCHAINFLAG
128 
129  _lock.lock();
130 
131  obj->_next = _deleted_chain;
132  _deleted_chain = obj;
133 
134  _lock.unlock();
135 
136 #else // USE_DELETED_CHAIN
137  PANDA_FREE_SINGLE(ptr);
138 #endif // USE_DELETED_CHAIN
139 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void * allocate(size_t size, TypeHandle type_handle)
Allocates the memory for a new buffer of the indicated size (which must be no greater than the fixed ...
void inc_memory_usage(MemoryClass memory_class, size_t size)
Adds the indicated amount to the record for the total allocated memory for objects of this type.
Definition: typeHandle.cxx:43
void deallocate(void *ptr, TypeHandle type_handle)
Frees the memory for a buffer previously allocated via allocate().
static void * alloc(size_t size)
Returns a pointer to a newly-allocated block of memory of the indicated size.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
void dec_memory_usage(MemoryClass memory_class, size_t size)
Subtracts the indicated amount from the record for the total allocated memory for objects of this typ...
Definition: typeHandle.cxx:67
static Integer compare_and_exchange(Integer &mem, Integer old_value, Integer new_value)
Atomic compare and exchange.