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
//! The Ferroc Memory Allocator
//!
//! # Usage
//!
//! Ferroc can be used in many ways by various features. Pick one you prefer:
//!
//! ## The default allocator
//!
//! The simplest use of this crate is to configure it as the default global
//! allocator. Simply add the dependency of this crate, mark an instance of
//! [`Ferroc`] using the `#[global_allocator]` attribute, and done!
//!
//! ```
//! use ferroc::Ferroc;
//!
//! #[global_allocator]
//! static FERROC: Ferroc = Ferroc;
//!
//! let _vec = vec![10; 100];
//! ```
//!
//! Or, if you don't want to use it as the global allocator, [`Ferroc`] provides
//! methods of all the functions you need, as well as the implementation of
//! [`core::alloc::Allocator`]:
//!
//! ```
//! #![feature(allocator_api)]
//! use ferroc::Ferroc;
//!
//! let mut vec = Vec::with_capacity_in(10, Ferroc);
//! vec.extend([1, 2, 3, 4, 5]);
//!
//! let layout = std::alloc::Layout::new::<[u32; 10]>();
//! let memory = Ferroc.allocate(layout).unwrap();
//! unsafe { Ferroc.deallocate(memory.cast(), layout) };
//! ```
//!
//! ## The default allocator (custom configuration)
//!
//! An instance of Ferroc type consists of thread-local contexts and heaps and a
//! global arena collection based on a specified base allocator, which can be
//! configured as you like.
//!
//! To do so, disable the default feature and enable the `global` feature as
//! well as other necessary features to [configure](config) it! Take the
//! embedded use case for example:
//!
//! ```toml
//! [dependencies.ferroc]
//! version = "*"
//! default-features = false
//! features = ["global", "base-static"]
//! ```
//!
//! ```rust,ignore
//! // This is the capacity of the necessary additional static
//! // memory space used by ferroc as the metadata storage.
//! const HEADER_CAP: usize = 4096;
//! ferroc::config!(pub Custom => ferroc::base::Static::<HEADER_CAP>);
//!
//! #[global_allocator]
//! static CUSTOM: Custom = Custom;
//!
//! // Multiple manageable static memory chunks can be loaded at runtime.
//! let chunk = unsafe { Chunk::from_static(/* ... */) };
//! CUSTOM.manage(chunk);
//!
//! // ...And you can start allocation.
//! let _vec = vec![10; 100];
//! ```
//!
//! ## MORE customizations
//!
//! If the configurations of the default allocator can't satisfy your need, you
//! can use the intermediate structures manually while disabling unnecessary
//! features:
//!
//! ```rust,ignore
//! #![feature(allocator_api)]
//! use ferroc::{
//! arena::Arenas,
//! heap::{Heap, Context},
//! base::Mmap,
//! };
//!
//! let arenas = Arenas::new(Mmap); // `Arenas` are `Send` & `Sync`...
//! let cx = Context::new(&arenas);
//! let heap = Heap::new(&cx); // ...while `Context`s and `Heap`s are not.
//!
//! // Using the allocator API.
//! let mut vec = Vec::new_in(&heap);
//! vec.extend([1, 2, 3, 4]);
//! assert_eq!(vec.iter().sum::<i32>(), 10);
//!
//! // Manually allocate memory.
//! let layout = std::alloc::Layout::new::<u8>();
//! let ptr = heap.allocate(layout).unwrap();
//! unsafe { heap.deallocate(ptr, layout) };
//!
//! // Immediately run some delayed clean-up operations.
//! heap.collect(/* force */false);
//! ```
//!
//! ## Using as a dynamic library for `malloc` function series
//!
//! Simply enable the `c` feature and compile it, and you can retrieve the
//! library binary alongside with a `ferroc.h` C/C++ compatible header.
//!
//! If you want to replace the default `malloc` implementation, add a `rustc`
//! flag `--cfg sys_alloc` when compiling.
//!
//! ## Statistics
//!
//! You can get statistics by enabling the `stat` feature and call the `stat`
//! method on the default allocator or other instances like
//! [`Heap`](crate::heap::Heap).
extern crate std;
type Stat = ;
config_mod!;
pub use *;
pub use Stat;