InDesign SDK  20.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
BypassAllocator.h
1 //========================================================================================
2 //
3 // $File$
4 //
5 // Owner: Robin_Briggs
6 //
7 // $Author$
8 //
9 // $DateTime$
10 //
11 // $Revision$
12 //
13 // $Change$
14 //
15 // ADOBE CONFIDENTIAL
16 //
17 // Copyright 1997-2010 Adobe Systems Incorporated. All rights reserved.
18 //
19 // NOTICE: All information contained herein is, and remains
20 // the property of Adobe Systems Incorporated and its suppliers,
21 // if any. The intellectual and technical concepts contained
22 // herein are proprietary to Adobe Systems Incorporated and its
23 // suppliers and may be covered by U.S. and Foreign Patents,
24 // patents in process, and are protected by trade secret or copyright law.
25 // Dissemination of this information or reproduction of this material
26 // is strictly forbidden unless prior written permission is obtained
27 // from Adobe Systems Incorporated.
28 //
29 //========================================================================================
30 
31 #ifndef __BypassAllocator__
32 #define __BypassAllocator__
33 
34 #include <stdlib.h> // for malloc, free
35 
36 #ifdef MACINTOSH
37 #include <new>
38 #endif
39 
40 #include "MemoryUtils.h"
41 
42 //========================================================================================
43 
44 // The point of this allocator is to be able to use an STL object while completely
45 // bypassing our allocation mechanisms and going directly to the runtime library.
46 // This is done by using malloc/free in the underlying RTL.
47 
48 template <class T>
50 public:
51  // type definitions
52  typedef T value_type;
53  typedef T* pointer;
54  typedef const T* const_pointer;
55  typedef T& reference;
56  typedef const T& const_reference;
57  typedef size_t size_type;
58  typedef ptrdiff_t difference_type;
59 
60  // rebind allocator to type U
61  template <class U >
62  struct rebind {
64  };
65 
66  // return address of values
67  pointer address (reference value) const {
68  return &value;
69  }
70  const_pointer address (const_reference value) const {
71  return &value;
72  }
73 
74  /* constructors and destructor
75  * - nothing to do because the allocator has no state
76  */
77  BypassAllocator() noexcept {
78  }
79  BypassAllocator(const BypassAllocator& src) noexcept {
80  }
81  template <class U >
82  BypassAllocator (const BypassAllocator< U > &src) noexcept {
83  }
84  ~BypassAllocator() noexcept {
85  }
86 
87  // return maximum number of elements that can be allocated
88  size_type max_size () const noexcept {
89  return (size_type) (int64) -1 / sizeof(T);
90  }
91 
92  // allocate but don't initialize num elements of type T
93  pointer allocate (size_type num, const void* = 0) {
94 #ifdef WASM
95  pointer ret = (pointer) new char[num * sizeof(T)];
96 #else
97 #if defined(MACINTOSH) && defined(DEBUG)
98  pointer ret = (pointer) K2Memory::RTLCompatibleBypassMalloc (num * sizeof(T));
99 #else
100  pointer ret = (pointer) malloc (num * sizeof(T));
101 #endif
102  if (!ret) throw std::bad_alloc();
103 #endif // WASM
104  return ret;
105  }
106 
107  // initialize elements of allocated storage p with value value
108  void construct (pointer p, const T& value) {
109  // initialize memory with placement new
110  new((void*)p)T(value);
111  }
112 
113  // destroy elements of initialized storage p
114  void destroy (pointer p) {
115  // destroy objects by calling their destructor
116  p->~T();
117  }
118 
119  // deallocate storage p of deleted elements
120  void deallocate (pointer p, size_type num) {
121 #ifdef WASM
122  delete [] (char*) p;
123 #elif defined(MACINTOSH) && defined(DEBUG)
124  K2Memory::RTLCompatibleBypassFree (p);
125 #else
126  free (p);
127 #endif
128  }
129 
130 };
131 
132 // return that all specializations of this allocator are interchangeable
133 template <class T1, class T2>
134 bool operator== (const BypassAllocator<T1>&, const BypassAllocator<T2>&) noexcept {
135  return true;
136 }
137 template <class T1, class T2>
138 bool operator!= (const BypassAllocator<T1>&, const BypassAllocator<T2>&) noexcept {
139  return false;
140 }
141 
142 //========================================================================================
143 
144 // This is similar, but keeps a pool of recently used objects to recycle.
145 
146 // This is cheesy and NOT a good example of how to do this in a general case for
147 // a number of reasons, but this is sufficient for our memory tracking debug code.
148 
149 template <class T>
151 public:
152  // type definitions
153  typedef T value_type;
154  typedef T* pointer;
155  typedef const T* const_pointer;
156  typedef T& reference;
157  typedef const T& const_reference;
158  typedef size_t size_type;
159  typedef ptrdiff_t difference_type;
160 
161  // rebind allocator to type U
162  template <class U >
163  struct rebind {
165  };
166 
167  // return address of values
168  pointer address (reference value) const {
169  return &value;
170  }
171  const_pointer address (const_reference value) const {
172  return &value;
173  }
174 
175  /* constructors and destructor
176  */
177  BypassRecycleAllocator() noexcept : fSP (0) {
178  }
179  BypassRecycleAllocator(const BypassRecycleAllocator& src) noexcept : fSP (0) {
180  }
181  template <class U >
182  BypassRecycleAllocator (const BypassRecycleAllocator< U > &src) noexcept : fSP (0) {
183  }
184  ~BypassRecycleAllocator() noexcept {
185  while (fSP)
186 #if defined(MACINTOSH) && defined(DEBUG)
187  K2Memory::RTLCompatibleBypassFree (fStack [--fSP]);
188 #else
189  free (fStack [--fSP]);
190 #endif
191  }
192 
193  // return maximum number of elements that can be allocated
194  size_type max_size () const noexcept {
195  return (size_type) (int64) -1 / sizeof(T);
196  }
197 
198  // allocate but don't initialize num elements of type T
199  pointer allocate (size_type num, const void* = 0) {
200  if (num == 1 && fSP) return fStack [--fSP];
201 #if defined(MACINTOSH) && defined(DEBUG)
202  pointer ret = (pointer) K2Memory::RTLCompatibleBypassMalloc (num * sizeof(T));
203 #else
204  pointer ret = (pointer) malloc (num * sizeof(T));
205 #endif
206  if (!ret) throw std::bad_alloc();
207  return ret;
208  }
209 
210  // initialize elements of allocated storage p with value value
211  void construct (pointer p, const T& value) {
212  // initialize memory with placement new
213  new((void*)p)T(value);
214  }
215 
216  // destroy elements of initialized storage p
217  void destroy (pointer p) {
218  // destroy objects by calling their destructor
219  p->~T();
220  }
221 
222  // deallocate storage p of deleted elements
223  void deallocate (pointer p, size_type num) {
224  if (num == 1 && fSP < kMaxSize)
225  fStack [fSP++] = p;
226  else
227 #if defined(MACINTOSH) && defined(DEBUG)
228  K2Memory::RTLCompatibleBypassFree (p);
229 #else
230  free (p);
231 #endif
232  }
233 
234 private:
235 
236  enum { kMaxSize = 1000 }; // tested: 90% recycle rate for build acceptance, only 10% of requests actually hit malloc/free
237  pointer fStack [kMaxSize];
238  int32 fSP;
239 };
240 
241 template <class T1, class T2>
242 bool operator== (const BypassRecycleAllocator<T1>&lhs, const BypassRecycleAllocator<T2>&rhs) noexcept {
243  return &lhs==&rhs;
244 }
245 template <class T1, class T2>
246 bool operator!= (const BypassRecycleAllocator<T1>&lhs, const BypassRecycleAllocator<T2>&rhs) noexcept {
247  return &lhs!=&rhs;
248 }
249 
250 //========================================================================================
251 
258 template <class T>
260 public:
261  // type definitions
262  typedef T value_type;
263  typedef T* pointer;
264  typedef const T* const_pointer;
265  typedef T& reference;
266  typedef const T& const_reference;
267  typedef size_t size_type;
268  typedef ptrdiff_t difference_type;
269 
270  // rebind allocator to type U
271  template <class U >
272  struct rebind {
274  };
275 
276  // return address of values
277  pointer address (reference value) const {
278  return &value;
279  }
280  const_pointer address (const_reference value) const {
281  return &value;
282  }
283 
284  /* constructors and destructor
285  * - nothing to do because the allocator has no state
286  */
287  BypassPurgingAllocator() noexcept {}
288  ~BypassPurgingAllocator() noexcept {}
289  BypassPurgingAllocator(const BypassPurgingAllocator& src) noexcept {}
290  template <class U >
291  BypassPurgingAllocator (const BypassPurgingAllocator< U > &src) noexcept {}
292 
293  // return maximum number of elements that can be allocated
294  size_type max_size () const noexcept {
295  return (size_type) (int64) -1 / sizeof(T);
296  }
297 
298  // allocate but don't initialize num elements of type T
299  pointer allocate (size_type num, const void* = 0) {
300  pointer ret = (pointer) K2Memory::RTLCompatibleMallocNoPurging (num * sizeof(value_type));
301  if (!ret) throw std::bad_alloc();
302  return ret;
303  }
304 
305  // initialize elements of allocated storage p with value value
306  void construct (pointer p, const T& value) {
307  // initialize memory with placement new
308  new((void*)p)value_type(value);
309  }
310 
311  // destroy elements of initialized storage p
312  void destroy (pointer p) {
313  // destroy objects by calling their destructor
314  p->~value_type();
315  }
316 
317  // deallocate storage p of deleted elements
318  void deallocate (pointer p, size_type num) {
319  K2Memory::RTLCompatibleFree(p);
320  }
321 
322 };
323 
324 // return that all specializations of this allocator are interchangeable
325 template <class T1, class T2>
326 bool operator== (const BypassPurgingAllocator<T1>&, const BypassPurgingAllocator<T2>&) noexcept {
327  return true;
328 }
329 template <class T1, class T2>
330 bool operator!= (const BypassPurgingAllocator<T1>&, const BypassPurgingAllocator<T2>&) noexcept {
331  return false;
332 }
333 
334 
335 #endif // __BypassAllocator__