forked from questor/eastl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
core_allocator_adapter.h
364 lines (287 loc) · 12.5 KB
/
core_allocator_adapter.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
/////////////////////////////////////////////////////////////////////////////
// Copyright (c) Electronic Arts Inc. All rights reserved.
/////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Implements an EASTL allocator that uses an ICoreAllocator.
// However, this header file is not dependent on ICoreAllocator or its package.
///////////////////////////////////////////////////////////////////////////////
#ifndef EASTL_CORE_ALLOCATOR_ADAPTER_H
#define EASTL_CORE_ALLOCATOR_ADAPTER_H
#if EASTL_CORE_ALLOCATOR_ENABLED
#include <eastl/internal/config.h>
#if defined(EASTL_PRAGMA_ONCE_SUPPORTED)
#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.
#endif
/// EASTL_CORE_ALLOCATOR_ADAPTER_GET_DEFAULT_CORE_ALLOCATOR
///
/// This allows the application to override the default name for the default global core allocator.
/// However, you must be careful in your usage of this, as if this file is shared between uses then
/// you will need to be careful that your override of this doesn't conflict with others.
///
#ifndef EASTL_CORE_ALLOCATOR_ADAPTER_GET_DEFAULT_CORE_ALLOCATOR
#define EASTL_CORE_ALLOCATOR_ADAPTER_GET_DEFAULT_CORE_ALLOCATOR AllocatorType::GetDefaultAllocator
#endif
namespace EA
{
namespace Allocator
{
/// CoreAllocatorAdapter
///
/// Implements the EASTL allocator interface.
/// Allocates memory from an instance of ICoreAllocator or another class with an equivalent interface.
/// ICoreAllocator is a pure-virtual memory allocation interface used by a number of EA games and
/// shared libraries. It's completely unrelated to EASTL, but it's prevalent enough that it's useful
/// for EASTL to have a built-in adapter for this interface. ICoreAllocator is declared in the
/// CoreAllocator package icoreallocator_interface.h header, but CoreAllocatorAdapter can work with
/// any equivalent interface, as defined below.
///
/// Expected interface:
/// enum AllocFlags {
/// kFlagTempMemory = 0,
/// kFlagPermMemory = 1
/// };
///
/// struct CoreAllocator {
/// void* Alloc(size_t size, const char* name, unsigned int allocFlags);
/// void* Alloc(size_t size, const char* name, unsigned int allocFlags, // Not required unless you are working with types that require custom alignment.
/// unsigned int align, unsigned int alignOffset = 0);
/// void Free(void* block, size_t size = 0);
/// static CoreAllocator* GetDefaultAllocator();
/// };
///
/// Example usage:
/// #include <coreallocator/icoreallocator_interface.h>
/// typedef EA::Allocator::CoreAllocatorAdapter<EASTLTestCoreAllocator> Adapter;
/// eastl::list<Widget, Adapter> widgetList(Adapter("UI/WidgetList", pSomeCoreAllocator));
/// widgetList.pushBack(Widget());
///
/// Example usage:
/// #include <MyEquivalentCoreAllocatorInterface.h>
/// eastl::list<Widget, CoreAllocatorAdapter<MyCoreAllocatorInterface> > widgetList;
/// widgetList.pushBack(Widget());
///
/// Example usage:
/// #include <coreallocator/icoreallocator_interface.h>
/// typedef EA::Allocator::CoreAllocatorAdapter<EASTLTestCoreAllocator> Adapter;
/// typedef eastl::list<Widget, Adapter> WidgetList;
/// CoreAllocatorFixed<WidgetList::node_type> widgetCoreAllocator(pFixedAllocatorForWidgetListValueType); // CoreAllocatorFixed is a hypothetical implementation of the ICoreAllocator interface.
/// WidgetList widgetList(Adapter("UI/WidgetList", &widgetCoreAllocator)); // Note that the widgetCoreAllocator is declared before and thus destroyed after the widget list.
///
template<class AllocatorType>
class CoreAllocatorAdapter
{
public:
typedef CoreAllocatorAdapter<AllocatorType> this_type;
public:
// To do: Make this constructor explicit, when there is no known code dependent on it being otherwise.
CoreAllocatorAdapter(const char* pName = EASTL_NAME_VAL(EASTL_ALLOCATOR_DEFAULT_NAME), AllocatorType* pAllocator = EASTL_CORE_ALLOCATOR_ADAPTER_GET_DEFAULT_CORE_ALLOCATOR());
CoreAllocatorAdapter(const char* pName, AllocatorType* pAllocator, int flags);
CoreAllocatorAdapter(const CoreAllocatorAdapter& x);
CoreAllocatorAdapter(const CoreAllocatorAdapter& x, const char* pName);
CoreAllocatorAdapter& operator=(const CoreAllocatorAdapter& x);
void* allocate(size_t n, int flags = 0);
void* allocate(size_t n, size_t alignment, size_t offset, int flags = 0);
void deallocate(void* p, size_t n);
AllocatorType* getAllocator() const;
void setAllocator(AllocatorType* pAllocator);
int getFlags() const;
void setFlags(int flags);
const char* getName() const;
void setName(const char* pName);
public: // Public because otherwise VC++ generates (possibly invalid) warnings about inline friend template specializations.
AllocatorType* mpCoreAllocator;
int mnFlags; // Allocation flags. See ICoreAllocator/AllocFlags.
#if EASTL_NAME_ENABLED
const char* mpName; // Debug name, used to track memory.
#endif
};
template<class AllocatorType>
bool operator==(const CoreAllocatorAdapter<AllocatorType>& a, const CoreAllocatorAdapter<AllocatorType>& b);
template<class AllocatorType>
bool operator!=(const CoreAllocatorAdapter<AllocatorType>& a, const CoreAllocatorAdapter<AllocatorType>& b);
/// EASTLICoreAllocator
///
/// Provides a standardized typedef for ICoreAllocator;
///
/// Example usage:
/// eastl::list<Widget, EASTLICoreAllocator> widgetList("UI/WidgetList", pSomeCoreAllocator);
/// widgetList.pushBack(Widget());
///
class ICoreAllocator;
class EASTLCoreAllocatorImpl;
typedef CoreAllocatorAdapter<ICoreAllocator> EASTLICoreAllocatorAdapter;
typedef CoreAllocatorAdapter<EASTLCoreAllocatorImpl> EASTLCoreAllocatorAdapter;
typedef EASTLICoreAllocatorAdapter EASTLICoreAllocator; // for backwards compatibility
/// EASTLICoreDeleter
///
/// Implements a functor which can free memory from the specified
/// ICoreAllocator interface. This is a convenience object provided for
/// users who wish to have EASTL containers deallocate memory obtained from
/// ICoreAllocator interfaces.
///
template <class AllocatorType>
class CoreDeleterAdapter
{
public:
typedef CoreDeleterAdapter<AllocatorType> this_type;
AllocatorType* mpCoreAllocator;
public:
CoreDeleterAdapter(AllocatorType* pAllocator = EASTL_CORE_ALLOCATOR_ADAPTER_GET_DEFAULT_CORE_ALLOCATOR()) EASTL_NOEXCEPT
: mpCoreAllocator(pAllocator) {}
~CoreDeleterAdapter() EASTL_NOEXCEPT {}
template <typename T>
void operator()(T* p) { mpCoreAllocator->Free(p); }
CoreDeleterAdapter(const CoreDeleterAdapter& in) { mpCoreAllocator = in.mpCoreAllocator; }
#if EASTL_MOVE_SEMANTICS_ENABLED
CoreDeleterAdapter(CoreDeleterAdapter&& in)
{
mpCoreAllocator = in.mpCoreAllocator;
in.mpCoreAllocator = nullptr;
}
CoreDeleterAdapter& operator=(const CoreDeleterAdapter& in)
{
mpCoreAllocator = in.mpCoreAllocator;
return *this;
}
CoreDeleterAdapter& operator=(CoreDeleterAdapter&& in)
{
mpCoreAllocator = in.mpCoreAllocator;
in.mpCoreAllocator = nullptr;
return *this;
}
#endif
};
/// EASTLICoreDeleter
///
/// Provides a standardized typedef for ICoreAllocator implementations.
///
/// Example usage:
/// eastl::shared_ptr<A> foo(pA, EASTLCoreDeleter());
///
typedef CoreDeleterAdapter<ICoreAllocator> EASTLICoreDeleterAdapter;
typedef CoreDeleterAdapter<EASTLCoreAllocatorImpl> EASTLCoreDeleterAdapter;
} // namespace Allocator
} // namespace EA
///////////////////////////////////////////////////////////////////////////////
// Inlines
///////////////////////////////////////////////////////////////////////////////
namespace EA
{
namespace Allocator
{
template<class AllocatorType>
inline CoreAllocatorAdapter<AllocatorType>::CoreAllocatorAdapter(const char* EASTL_NAME(pName), AllocatorType* pCoreAllocator)
: mpCoreAllocator(pCoreAllocator), mnFlags(0)
{
#if EASTL_NAME_ENABLED
mpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;
#endif
}
template<class AllocatorType>
inline CoreAllocatorAdapter<AllocatorType>::CoreAllocatorAdapter(const char* EASTL_NAME(pName), AllocatorType* pCoreAllocator, int flags)
: mpCoreAllocator(pCoreAllocator), mnFlags(flags)
{
#if EASTL_NAME_ENABLED
mpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;
#endif
}
template<class AllocatorType>
inline CoreAllocatorAdapter<AllocatorType>::CoreAllocatorAdapter(const CoreAllocatorAdapter& x)
: mpCoreAllocator(x.mpCoreAllocator), mnFlags(x.mnFlags)
{
#if EASTL_NAME_ENABLED
mpName = x.mpName;
#endif
}
template<class AllocatorType>
inline CoreAllocatorAdapter<AllocatorType>::CoreAllocatorAdapter(const CoreAllocatorAdapter& x, const char* EASTL_NAME(pName))
: mpCoreAllocator(x.mpCoreAllocator), mnFlags(x.mnFlags)
{
#if EASTL_NAME_ENABLED
mpName = pName ? pName : EASTL_ALLOCATOR_DEFAULT_NAME;
#endif
}
template<class AllocatorType>
inline CoreAllocatorAdapter<AllocatorType>& CoreAllocatorAdapter<AllocatorType>::operator=(const CoreAllocatorAdapter& x)
{
// In order to be consistent with EASTL's allocator implementation,
// we don't copy the name from the source object.
mpCoreAllocator = x.mpCoreAllocator;
mnFlags = x.mnFlags;
return *this;
}
template<class AllocatorType>
inline void* CoreAllocatorAdapter<AllocatorType>::allocate(size_t n, int /*flags*/)
{
// It turns out that EASTL itself doesn't use the flags parameter,
// whereas the user here might well want to specify a flags
// parameter. So we use ours instead of the one passed in.
return mpCoreAllocator->Alloc(n, EASTL_NAME_VAL(mpName), (unsigned)mnFlags);
}
template<class AllocatorType>
inline void* CoreAllocatorAdapter<AllocatorType>::allocate(size_t n, size_t alignment, size_t offset, int /*flags*/)
{
// It turns out that EASTL itself doesn't use the flags parameter,
// whereas the user here might well want to specify a flags
// parameter. So we use ours instead of the one passed in.
return mpCoreAllocator->Alloc(n, EASTL_NAME_VAL(mpName), (unsigned)mnFlags, (unsigned)alignment, (unsigned)offset);
}
template<class AllocatorType>
inline void CoreAllocatorAdapter<AllocatorType>::deallocate(void* p, size_t n)
{
return mpCoreAllocator->Free(p, n);
}
template<class AllocatorType>
inline AllocatorType* CoreAllocatorAdapter<AllocatorType>::getAllocator() const
{
return mpCoreAllocator;
}
template<class AllocatorType>
inline void CoreAllocatorAdapter<AllocatorType>::setAllocator(AllocatorType* pAllocator)
{
mpCoreAllocator = pAllocator;
}
template<class AllocatorType>
inline int CoreAllocatorAdapter<AllocatorType>::getFlags() const
{
return mnFlags;
}
template<class AllocatorType>
inline void CoreAllocatorAdapter<AllocatorType>::setFlags(int flags)
{
mnFlags = flags;
}
template<class AllocatorType>
inline const char* CoreAllocatorAdapter<AllocatorType>::getName() const
{
#if EASTL_NAME_ENABLED
return mpName;
#else
return EASTL_ALLOCATOR_DEFAULT_NAME;
#endif
}
template<class AllocatorType>
inline void CoreAllocatorAdapter<AllocatorType>::setName(const char* pName)
{
#if EASTL_NAME_ENABLED
mpName = pName;
#else
(void)pName;
#endif
}
template<class AllocatorType>
inline bool operator==(const CoreAllocatorAdapter<AllocatorType>& a, const CoreAllocatorAdapter<AllocatorType>& b)
{
return (a.mpCoreAllocator == b.mpCoreAllocator) &&
(a.mnFlags == b.mnFlags);
}
template<class AllocatorType>
inline bool operator!=(const CoreAllocatorAdapter<AllocatorType>& a, const CoreAllocatorAdapter<AllocatorType>& b)
{
return (a.mpCoreAllocator != b.mpCoreAllocator) ||
(a.mnFlags != b.mnFlags);
}
} // namespace Allocator
} // namespace EA
#endif // EASTL_CORE_ALLOCATOR_ENABLED
#endif // Header include guard