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 */
34 void *DeletedBufferChain::
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 // 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 */
102 void DeletedBufferChain::
103 deallocate(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}
AtomicAdjustDummyImpl::compare_and_exchange
static Integer compare_and_exchange(Integer &mem, Integer old_value, Integer new_value)
Atomic compare and exchange.
Definition atomicAdjustDummyImpl.I:93
DeletedBufferChain::deallocate
void deallocate(void *ptr, TypeHandle type_handle)
Frees the memory for a buffer previously allocated via allocate().
Definition deletedBufferChain.cxx:103
DeletedBufferChain::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 ...
Definition deletedBufferChain.cxx:35
NeverFreeMemory::alloc
static void * alloc(size_t size)
Returns a pointer to a newly-allocated block of memory of the indicated size.
Definition neverFreeMemory.I:21
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
TypeHandle::dec_memory_usage
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
TypeHandle::inc_memory_usage
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
deletedBufferChain.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
memoryHook.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.