Panda3D
 All Classes Functions Variables Enumerations
deletedBufferChain.cxx
1 // Filename: deletedBufferChain.cxx
2 // Created by: drose (20Jul07)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "deletedBufferChain.h"
16 #include "memoryHook.h"
17 
18 ////////////////////////////////////////////////////////////////////
19 // Function: DeletedBufferChain::Constructor
20 // Access: Protected
21 // Description: Use the global MemoryHook to get a new
22 // DeletedBufferChain of the appropriate size.
23 ////////////////////////////////////////////////////////////////////
24 DeletedBufferChain::
25 DeletedBufferChain(size_t buffer_size) {
26  _deleted_chain = NULL;
27  _buffer_size = buffer_size;
28 
29  // We must allocate at least this much space for bookkeeping
30  // reasons.
31  _buffer_size = max(_buffer_size, sizeof(ObjectNode));
32 }
33 
34 ////////////////////////////////////////////////////////////////////
35 // Function: DeletedBufferChain::allocate
36 // Access: Public
37 // Description: Allocates the memory for a new buffer of the
38 // indicated size (which must be no greater than the
39 // fixed size associated with the DeletedBufferChain).
40 ////////////////////////////////////////////////////////////////////
42 allocate(size_t size, TypeHandle type_handle) {
43 #ifdef USE_DELETED_CHAIN
44  //TAU_PROFILE("void *DeletedBufferChain::allocate(size_t, TypeHandle)", " ", TAU_USER);
45  assert(size <= _buffer_size);
46 
47  // Determine how much space to allocate.
48  const size_t alloc_size = _buffer_size + flag_reserved_bytes;
49 
50  ObjectNode *obj;
51 
52  _lock.acquire();
53  if (_deleted_chain != (ObjectNode *)NULL) {
54  obj = _deleted_chain;
55  _deleted_chain = _deleted_chain->_next;
56  _lock.release();
57 
58 #ifdef USE_DELETEDCHAINFLAG
59  assert(obj->_flag == (AtomicAdjust::Integer)DCF_deleted);
60  obj->_flag = DCF_alive;
61 #endif // USE_DELETEDCHAINFLAG
62 
63  void *ptr = node_to_buffer(obj);
64 
65 #ifdef DO_MEMORY_USAGE
66  // type_handle.dec_memory_usage(TypeHandle::MC_deleted_chain_inactive, alloc_size);
67  type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, alloc_size);
68 #endif // DO_MEMORY_USAGE
69 
70  return ptr;
71  }
72  _lock.release();
73 
74  // If we get here, the deleted_chain is empty; we have to allocate a
75  // new object from the system pool.
76 
77  obj = (ObjectNode *)NeverFreeMemory::alloc(alloc_size);
78 
79 #ifdef USE_DELETEDCHAINFLAG
80  obj->_flag = DCF_alive;
81 #endif // USE_DELETEDCHAINFLAG
82 
83  void *ptr = node_to_buffer(obj);
84 
85 #ifdef DO_MEMORY_USAGE
86  type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, alloc_size);
87 #endif // DO_MEMORY_USAGE
88 
89  return ptr;
90 
91 #else // USE_DELETED_CHAIN
92  return PANDA_MALLOC_SINGLE(_buffer_size);
93 #endif // USE_DELETED_CHAIN
94 }
95 
96 ////////////////////////////////////////////////////////////////////
97 // Function: DeletedBufferChain::deallocate
98 // Access: Public
99 // Description: Frees the memory for a buffer previously allocated
100 // via allocate().
101 ////////////////////////////////////////////////////////////////////
103 deallocate(void *ptr, TypeHandle type_handle) {
104 #ifdef USE_DELETED_CHAIN
105  //TAU_PROFILE("void DeletedBufferChain::deallocate(void *, TypeHandle)", " ", TAU_USER);
106  assert(ptr != (void *)NULL);
107 
108 #ifdef DO_MEMORY_USAGE
109  type_handle.dec_memory_usage(TypeHandle::MC_deleted_chain_active,
110  _buffer_size + flag_reserved_bytes);
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
125  // that was never allocated, or you have heap corruption.
126  assert(orig_flag == (AtomicAdjust::Integer)DCF_alive);
127 #endif // USE_DELETEDCHAINFLAG
128 
129  _lock.acquire();
130 
131  obj->_next = _deleted_chain;
132  _deleted_chain = obj;
133 
134  _lock.release();
135 
136 #else // USE_DELETED_CHAIN
137  PANDA_FREE_SINGLE(ptr);
138 #endif // USE_DELETED_CHAIN
139 }
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 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:85
static Integer compare_and_exchange(Integer &mem, Integer old_value, Integer new_value)
Atomic compare and exchange.