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
use crate::allocators::allocator::Allocator;
use crate::allocators::global::current_allocator_in_use::CurrentAllocatorInUse;
use crate::allocators::global::local_allocator::LocalAllocator;
use std::alloc::{Alloc, GlobalAlloc};
pub trait GlobalSwitchableAllocator: Sync + GlobalAlloc + Alloc + Allocator {
type CoroutineLocalAllocator: LocalAllocator;
type ThreadLocalAllocator: LocalAllocator;
type GlobalAllocator: Allocator;
fn replace_coroutine_local_allocator(
&self,
replacement: Option<Self::CoroutineLocalAllocator>,
) -> Option<Self::CoroutineLocalAllocator>;
fn initialize_thread_local_allocator(&self, thread_local_allocator: Self::ThreadLocalAllocator);
fn drop_thread_local_allocator(&self);
fn save_current_allocator_in_use(&self) -> CurrentAllocatorInUse;
fn restore_current_allocator_in_use(&self, restore_to: CurrentAllocatorInUse);
#[inline(always)]
fn replace_current_allocator_in_use(
&self,
replacement: CurrentAllocatorInUse,
) -> CurrentAllocatorInUse {
let was = self.save_current_allocator_in_use();
self.restore_current_allocator_in_use(replacement);
was
}
#[inline(always)]
fn callback_with_coroutine_local_allocator<R>(&self, callback: impl FnOnce() -> R) -> R {
self.callback_with_different_current_allocator(
CurrentAllocatorInUse::CoroutineLocal,
callback,
)
}
#[inline(always)]
fn callback_with_thread_local_allocator<R>(&self, callback: impl FnOnce() -> R) -> R {
self.callback_with_different_current_allocator(CurrentAllocatorInUse::ThreadLocal, callback)
}
#[inline(always)]
fn callback_with_global_allocator<R>(&self, callback: impl FnOnce() -> R) -> R {
self.callback_with_different_current_allocator(CurrentAllocatorInUse::Global, callback)
}
#[inline(always)]
fn callback_with_different_current_allocator<R>(
&self,
different: CurrentAllocatorInUse,
callback: impl FnOnce() -> R,
) -> R {
let restore_to = self.save_current_allocator_in_use();
self.restore_current_allocator_in_use(different);
let result = callback();
self.restore_current_allocator_in_use(restore_to);
result
}
fn coroutine_local_allocator(&self) -> Option<&Self::CoroutineLocalAllocator>;
#[inline(always)]
fn coroutine_local_allocator_unchecked(&self) -> &Self::CoroutineLocalAllocator {
self.coroutine_local_allocator().expect("Assign the coroutine local allocator first using `replace_coroutine_local_allocator()`")
}
fn thread_local_allocator(&self) -> Option<&Self::ThreadLocalAllocator>;
#[inline(always)]
fn thread_local_allocator_unchecked(&self) -> &Self::ThreadLocalAllocator {
self.thread_local_allocator().expect("Initialize the thread local allocator first using `initialize_thread_local_allocator()`")
}
fn global_allocator(&self) -> &Self::GlobalAllocator;
}