Panda3D
deletedBufferChain.h
1 // Filename: deletedBufferChain.h
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 #ifndef DELETEDBUFFERCHAIN_H
16 #define DELETEDBUFFERCHAIN_H
17 
18 #include "dtoolbase.h"
19 #include "neverFreeMemory.h"
20 #include "mutexImpl.h"
21 #include "atomicAdjust.h"
22 #include "numeric_types.h"
23 #include "typeHandle.h"
24 #include <assert.h>
25 
26 // Though it's tempting, it doesn't seem to be possible to implement
27 // DeletedBufferChain via the atomic exchange operation.
28 // Specifically, a pointer may be removed from the head of the chain,
29 // then the same pointer reinserted in the chain, while another thread
30 // is waiting; and that thread will not detect the change. So
31 // instead, we always use a mutex.
32 
33 #ifndef NDEBUG
34 // In development mode, we define USE_DELETEDCHAINFLAG, which
35 // triggers the piggyback of an additional word of data on every
36 // allocated block, so we can ensure that an object is not
37 // double-deleted and that the deleted chain remains intact.
38 #define USE_DELETEDCHAINFLAG 1
39 #endif // NDEBUG
40 
41 #ifdef USE_DELETEDCHAINFLAG
42 enum DeletedChainFlag {
43  DCF_deleted = 0xfeedba0f,
44  DCF_alive = 0x12487654,
45 };
46 #endif
47 
48 ////////////////////////////////////////////////////////////////////
49 // Class : DeletedBufferChain
50 // Description : This template class can be used to provide faster
51 // allocation/deallocation for many Panda objects. It
52 // works by maintaining a linked list of deleted buffers
53 // that are all of the same size; when a new object is
54 // allocated that matches that size, the same space is
55 // just reused.
56 //
57 // This class manages untyped buffers of a fixed size.
58 // It can be used directly; or it also serves as a
59 // backbone for DeletedChain, which is a template class
60 // that manages object allocations.
61 //
62 // Use MemoryHook to get a new DeletedBufferChain of a
63 // particular size.
64 ////////////////////////////////////////////////////////////////////
65 class EXPCL_DTOOL DeletedBufferChain {
66 protected:
67  DeletedBufferChain(size_t buffer_size);
68 
69 public:
70  void *allocate(size_t size, TypeHandle type_handle);
71  void deallocate(void *ptr, TypeHandle type_handle);
72 
73  INLINE bool validate(void *ptr);
74  INLINE size_t get_buffer_size() const;
75 
76 private:
77  class ObjectNode {
78  public:
79 #ifdef USE_DELETEDCHAINFLAG
80  // In development mode, we piggyback this extra data. This is
81  // maintained out-of-band from the actual pointer returned, so we
82  // can safely use this flag to indicate the difference between
83  // allocated and freed pointers.
84  TVOLATILE AtomicAdjust::Integer _flag;
85 #endif
86 
87  // This pointer sits within the buffer, in the same space
88  // referenced by the actual pointer returned (unlike _flag,
89  // above). It's only used when the buffer is deleted, so there's
90  // no harm in sharing space with the undeleted buffer.
91  ObjectNode *_next;
92  };
93 
94  static INLINE void *node_to_buffer(ObjectNode *node);
95  static INLINE ObjectNode *buffer_to_node(void *buffer);
96 
97  ObjectNode *_deleted_chain;
98 
99  MutexImpl _lock;
100  size_t _buffer_size;
101 
102 #ifndef USE_DELETEDCHAINFLAG
103  // Without DELETEDCHAINFLAG, we don't even store the _flag member at all.
104  static const size_t flag_reserved_bytes = 0;
105 
106 #elif defined(LINMATH_ALIGN)
107  // With SSE2 alignment, we need all 16 bytes to preserve alignment.
108 #ifdef __AVX__
109  static const size_t flag_reserved_bytes = 32;
110 #else
111  static const size_t flag_reserved_bytes = 16;
112 #endif
113 
114 #else
115  // Otherwise, we only need enough space for the Integer itself.
116  static const size_t flag_reserved_bytes = sizeof(AtomicAdjust::Integer);
117 #endif // USE_DELETEDCHAINFLAG
118 
119  friend class MemoryHook;
120 };
121 
122 #include "deletedBufferChain.I"
123 
124 #endif
125 
This class provides a wrapper around the various possible malloc schemes Panda might employ...
Definition: memoryHook.h:43
A fake mutex implementation for single-threaded applications that don&#39;t need any synchronization cont...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
This template class can be used to provide faster allocation/deallocation for many Panda objects...