Panda3D
Loading...
Searching...
No Matches
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 */
21DeletedBufferChain::
22DeletedBufferChain(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 */
35allocate(size_t size, TypeHandle type_handle) {
36#ifdef USE_DELETED_CHAIN
37 // TAU_PROFILE("void *DeletedBufferChain::allocate(size_t, TypeHandle)", "
38 // ", TAU_USER);
39 // If this triggers, maybe you forgot ALLOC_DELETED_CHAIN in a subclass?
40 assert(size <= _buffer_size);
41
42 // Determine how much space to allocate.
43 const size_t alloc_size = _buffer_size + flag_reserved_bytes + MEMORY_HOOK_ALIGNMENT - 1;
44
45 ObjectNode *obj;
46
47 _lock.lock();
48 if (_deleted_chain != nullptr) {
49 obj = _deleted_chain;
50 _deleted_chain = _deleted_chain->_next;
51 _lock.unlock();
52
53#ifdef USE_DELETEDCHAINFLAG
54 assert(obj->_flag == (AtomicAdjust::Integer)DCF_deleted);
55 obj->_flag = DCF_alive;
56#endif // USE_DELETEDCHAINFLAG
57
58 void *ptr = node_to_buffer(obj);
59
60#ifdef DO_MEMORY_USAGE
61 // type_handle.dec_memory_usage(TypeHandle::MC_deleted_chain_inactive,
62 // alloc_size);
63 type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, alloc_size);
64#endif // DO_MEMORY_USAGE
65
66 return ptr;
67 }
68 _lock.unlock();
69
70 // If we get here, the deleted_chain is empty; we have to allocate a new
71 // object from the system pool.
72
73 // Allocate memory, and make sure the object starts at the proper alignment.
74 void *mem = NeverFreeMemory::alloc(alloc_size);
75 uintptr_t aligned = ((uintptr_t)mem + flag_reserved_bytes + MEMORY_HOOK_ALIGNMENT - 1) & ~(MEMORY_HOOK_ALIGNMENT - 1);
76 obj = (ObjectNode *)(aligned - flag_reserved_bytes);
77
78#ifdef USE_DELETEDCHAINFLAG
79 obj->_flag = DCF_alive;
80#endif // USE_DELETEDCHAINFLAG
81
82 void *ptr = node_to_buffer(obj);
83
84#ifndef NDEBUG
85 assert(((uintptr_t)ptr % MEMORY_HOOK_ALIGNMENT) == 0);
86#endif
87
88#ifdef DO_MEMORY_USAGE
89 type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, alloc_size);
90#endif // DO_MEMORY_USAGE
91
92 return ptr;
93
94#else // USE_DELETED_CHAIN
95 return PANDA_MALLOC_SINGLE(_buffer_size);
96#endif // USE_DELETED_CHAIN
97}
98
99/**
100 * Frees the memory for a buffer previously allocated via allocate().
101 */
103deallocate(void *ptr, TypeHandle type_handle) {
104#ifdef USE_DELETED_CHAIN
105 // TAU_PROFILE("void DeletedBufferChain::deallocate(void *, TypeHandle)", "
106 // ", TAU_USER);
107 assert(ptr != nullptr);
108
109#ifdef DO_MEMORY_USAGE
110 const size_t alloc_size = _buffer_size + flag_reserved_bytes + MEMORY_HOOK_ALIGNMENT - 1;
111 type_handle.dec_memory_usage(TypeHandle::MC_deleted_chain_active, alloc_size);
112 // type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_inactive,
113 // _buffer_size + flag_reserved_bytes);
114
115#endif // DO_MEMORY_USAGE
116
117 ObjectNode *obj = buffer_to_node(ptr);
118
119#ifdef USE_DELETEDCHAINFLAG
120 AtomicAdjust::Integer orig_flag = AtomicAdjust::compare_and_exchange(obj->_flag, DCF_alive, DCF_deleted);
121
122 // If this assertion is triggered, you double-deleted an object.
123 assert(orig_flag != (AtomicAdjust::Integer)DCF_deleted);
124
125 // If this assertion is triggered, you tried to delete an object that was
126 // never allocated, or you have heap corruption.
127 assert(orig_flag == (AtomicAdjust::Integer)DCF_alive);
128#endif // USE_DELETEDCHAINFLAG
129
130 _lock.lock();
131
132 obj->_next = _deleted_chain;
133 _deleted_chain = obj;
134
135 _lock.unlock();
136
137#else // USE_DELETED_CHAIN
138 PANDA_FREE_SINGLE(ptr);
139#endif // USE_DELETED_CHAIN
140}
static Integer compare_and_exchange(Integer &mem, Integer old_value, Integer new_value)
Atomic compare and exchange.
void deallocate(void *ptr, TypeHandle type_handle)
Frees the memory for a buffer previously allocated via allocate().
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 ...
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...
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.