CookMem 1.4.0
A C++ memory context / allocator
Loading...
Searching...
No Matches
allocator.h
1/*
2 * Copyright (c) 2025-2026 Heng Yuan
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#ifndef COOK_MEM_ALLOCATOR_H
17#define COOK_MEM_ALLOCATOR_H
18
19#include <cstddef>
20#include <functional>
21#include <limits>
22#include <new>
23#include <type_traits>
24#include <utility>
25
26#include "context.h"
27
28namespace cookmem
29{
30
37template<class Context>
39{
40public:
42 typedef Context context_type;
48 typedef std::false_type propagate_on_container_swap;
50 typedef std::false_type is_always_equal;
51
59 explicit MemContextProvider (Context& context)
60 : m_context (context)
61 {
62 }
63
69 Context&
70 get () const
71 {
72 return m_context.get ();
73 }
74
82 bool
83 operator== (const MemContextProvider& other) const
84 {
85 return &m_context.get () == &other.m_context.get ();
86 }
87
95 bool
96 operator!= (const MemContextProvider& other) const
97 {
98 return !(*this == other);
99 }
100
101private:
102 std::reference_wrapper<Context> m_context;
103};
104
111template<class Context, class Tag>
113{
114public:
116 typedef Context context_type;
122 typedef std::true_type propagate_on_container_swap;
124 typedef std::false_type is_always_equal;
125
132 : m_context (getContextForAllocator ())
133 {
134 }
135
140 static Context&
142 {
143 return activeContext ();
144 }
145
149 static Context&
151 {
152 return getPersistentThreadContext ();
153 }
154
161 Context&
162 get () const
163 {
164 return m_context.get ();
165 }
166
174 bool
175 operator== (const TLSContextProvider& other) const
176 {
177 return &m_context.get () == &other.m_context.get ();
178 }
179
187 bool
188 operator!= (const TLSContextProvider& other) const
189 {
190 return !(*this == other);
191 }
192
193private:
194 template<class, class>
195 friend class TLSContextScope;
196
197 static Context&
198 activeContext ()
199 {
200 Context* context = activeContextStorage ();
201 return context != nullptr ? *context : getPersistentThreadContext ();
202 }
203
204 static Context*&
205 activeContextStorage ()
206 {
207 static thread_local Context* context = nullptr;
208 return context;
209 }
210
211 static Context&
212 getContextForAllocator ()
213 {
214 return activeContext ();
215 }
216
217 static Context&
218 getPersistentThreadContext ()
219 {
220 static thread_local Context context;
221 return context;
222 }
223
224 std::reference_wrapper<Context> m_context;
225};
226
234template<class Context, class Tag>
236{
237public:
243 : m_context (),
244 m_previousContext (TLSContextProvider<Context, Tag>::activeContextStorage ())
245 {
247 }
248
260 explicit TLSContextScope (bool shareArena)
261 : m_context (TLSContextProvider<Context, Tag>::getPersistentThreadContext (), shareArena),
262 m_previousContext (TLSContextProvider<Context, Tag>::activeContextStorage ())
263 {
265 }
266
268 {
270 }
271
272 TLSContextScope (const TLSContextScope&) = delete;
273 TLSContextScope& operator= (const TLSContextScope&) = delete;
274
280 Context&
282 {
283 return m_context;
284 }
285
286private:
287 Context m_context;
288 Context* m_previousContext;
289};
290
300template<class T,
301 class ContextProvider = MemContextProvider<CachedMemContext<> > >
303{
304public:
306 typedef typename ContextProvider::context_type context_type;
307 typedef T value_type;
308 typedef T* pointer;
309 typedef const T* const_pointer;
310 typedef T& reference;
311 typedef const T& const_reference;
312 typedef std::size_t size_type;
313 typedef std::ptrdiff_t difference_type;
315 typedef typename ContextProvider::propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
317 typedef typename ContextProvider::propagate_on_container_move_assignment propagate_on_container_move_assignment;
319 typedef typename ContextProvider::propagate_on_container_swap propagate_on_container_swap;
321 typedef typename ContextProvider::is_always_equal is_always_equal;
322
330 template<class U>
331 struct rebind
332 {
335 };
336
341 template<class Provider = ContextProvider>
343 typename std::enable_if<
344 std::is_default_constructible<Provider>::value,
345 int>::type* = nullptr)
346 : m_provider ()
347 {
348 }
349
358 : m_provider (context)
359 {
360 }
361
369 : m_provider (provider)
370 {
371 }
372
379 Allocator (const Allocator& other)
380 : m_provider (other.m_provider)
381 {
382 }
383
391 template<class U>
393 : m_provider (other.m_provider)
394 {
395 }
396
407 pointer
408 allocate (size_type size, const void* = nullptr)
409 {
410 if (size > (std::numeric_limits<size_type>::max) () / sizeof (T))
411 {
412 throw std::bad_alloc ();
413 }
414 if (size == 0)
415 {
416 return nullptr;
417 }
418
419 // Decided here rather than in the class body, so that the allocator
420 // can still be named for an incomplete type T.
421 typedef std::integral_constant<bool, (alignof (T) > ALLOCATION_ALIGNMENT)> OverAligned;
422 void* ptr = allocateBytes (size * sizeof (T), OverAligned ());
423 if (ptr == nullptr)
424 {
425 throw std::bad_alloc ();
426 }
427 return static_cast<pointer> (ptr);
428 }
429
437 void
439 {
440 m_provider.get ().deallocate (ptr);
441 }
442
449 max_size () const
450 {
451 return (std::numeric_limits<size_type>::max) () / sizeof (T);
452 }
453
462 template<class U, class... Args>
463 void
465 {
466 ::new (static_cast<void*> (ptr)) U (std::forward<Args> (args)...);
467 }
468
475 template<class U>
476 void
478 {
479 ptr->~U ();
480 }
481
488 getContext () const
489 {
490 return m_provider.get ();
491 }
492
501 template<class U>
502 bool
504 {
505 return m_provider == other.m_provider;
506 }
507
515 template<class U>
516 bool
518 {
519 return !(*this == other);
520 }
521
522private:
523 template<class, class>
524 friend class Allocator;
525
529 void*
530 allocateBytes (size_type bytes, std::false_type)
531 {
532 return m_provider.get ().allocate (bytes);
533 }
534
538 void*
539 allocateBytes (size_type bytes, std::true_type)
540 {
541 return m_provider.get ().allocateAligned (bytes, alignof (T));
542 }
543
544 ContextProvider m_provider;
545};
546
547} // namespace cookmem
548
549#endif // COOK_MEM_ALLOCATOR_H
Definition allocator.h:303
ContextProvider::propagate_on_container_copy_assignment propagate_on_container_copy_assignment
Definition allocator.h:315
Allocator(const Allocator< U, ContextProvider > &other)
Definition allocator.h:392
Allocator(const ContextProvider &provider)
Definition allocator.h:368
void deallocate(pointer ptr, size_type)
Definition allocator.h:438
pointer allocate(size_type size, const void *=nullptr)
Definition allocator.h:408
T & reference
Reference to an allocated object.
Definition allocator.h:310
T value_type
The type of the allocated objects.
Definition allocator.h:307
ContextProvider context_provider_type
The type of the context provider.
Definition allocator.h:305
T * pointer
Pointer to an allocated object.
Definition allocator.h:308
void destroy(U *ptr)
Definition allocator.h:477
std::size_t size_type
The type of object counts.
Definition allocator.h:312
Allocator(const Allocator &other)
Definition allocator.h:379
size_type max_size() const
Definition allocator.h:449
bool operator!=(const Allocator< U, ContextProvider > &other) const
Definition allocator.h:517
ContextProvider::is_always_equal is_always_equal
Definition allocator.h:321
bool operator==(const Allocator< U, ContextProvider > &other) const
Definition allocator.h:503
void construct(U *ptr, Args &&... args)
Definition allocator.h:464
Allocator(context_type &context)
Definition allocator.h:357
std::ptrdiff_t difference_type
The type of pointer differences.
Definition allocator.h:313
const T * const_pointer
Const pointer to an allocated object.
Definition allocator.h:309
ContextProvider::propagate_on_container_move_assignment propagate_on_container_move_assignment
Definition allocator.h:317
const T & const_reference
Const reference to an allocated object.
Definition allocator.h:311
context_type & getContext() const
Definition allocator.h:488
ContextProvider::propagate_on_container_swap propagate_on_container_swap
Definition allocator.h:319
Allocator(typename std::enable_if< std::is_default_constructible< Provider >::value, int >::type *=nullptr)
Definition allocator.h:342
ContextProvider::context_type context_type
The type of the memory context.
Definition allocator.h:306
Definition allocator.h:39
MemContextProvider(Context &context)
Definition allocator.h:59
bool operator==(const MemContextProvider &other) const
Definition allocator.h:83
std::false_type propagate_on_container_move_assignment
Definition allocator.h:46
Context context_type
Definition allocator.h:42
std::false_type is_always_equal
Definition allocator.h:50
Context & get() const
Definition allocator.h:70
bool operator!=(const MemContextProvider &other) const
Definition allocator.h:96
std::false_type propagate_on_container_copy_assignment
Definition allocator.h:44
std::false_type propagate_on_container_swap
Definition allocator.h:48
Definition allocator.h:113
Context & get() const
Definition allocator.h:162
std::true_type propagate_on_container_move_assignment
Definition allocator.h:120
std::true_type propagate_on_container_swap
Definition allocator.h:122
Context context_type
Definition allocator.h:116
std::true_type propagate_on_container_copy_assignment
Definition allocator.h:118
TLSContextProvider()
Definition allocator.h:131
static Context & getThreadContext()
Definition allocator.h:150
bool operator!=(const TLSContextProvider &other) const
Definition allocator.h:188
bool operator==(const TLSContextProvider &other) const
Definition allocator.h:175
std::false_type is_always_equal
Definition allocator.h:124
static Context & getActiveContext()
Definition allocator.h:141
Definition allocator.h:236
TLSContextScope()
Definition allocator.h:242
Context & getContext()
Definition allocator.h:281
TLSContextScope(bool shareArena)
Definition allocator.h:260
Definition allocator.h:29
const std::size_t ALLOCATION_ALIGNMENT
Definition config.h:36
Definition allocator.h:332
Allocator< U, ContextProvider > other
Definition allocator.h:334