12#include <l4/cxx/std_alloc>
13#include <l4/cxx/hlist>
30 int Max_free = 2,
template<
typename A>
class Alloc =
New_allocator >
50 Base_slab<Obj_size, Slab_size, Max_free, Alloc> *cache;
52 inline Slab_head() noexcept : num_free(0),
free(0), cache(0)
59 static_assert(Obj_size >=
sizeof(
void *),
60 "Object size must be at least the size of a pointer.");
61 static_assert(Obj_size <= Slab_size -
sizeof(Slab_head),
62 "Object_size exceeds slab capability.");
81 Free_o *object(
unsigned obj)
noexcept
82 {
return reinterpret_cast<Free_o*
>(_o +
object_size * obj); }
86 struct Slab_i :
public Slab_store,
public Slab_head
93 typedef void Obj_type;
110 void add_slab(
Slab_i *s)
noexcept
119 Free_o *f = s->free = s->object(0);
122 f->next = s->object(i);
128 _empty_slabs.push_front(s);
136 Slab_i *s = _alloc.alloc();
155 void shrink() noexcept
157 if (!_alloc.can_free)
162 Slab_i *s = _empty_slabs.
front();
172 : _alloc(
alloc), _num_free(0), _num_slabs(0), _full_slabs(),
173 _partial_slabs(), _empty_slabs()
176 ~Base_slab() noexcept
178 while (!_empty_slabs.empty())
180 Slab_i *o = _empty_slabs.front();
181 _empty_slabs.remove(o);
184 while (!_partial_slabs.empty())
186 Slab_i *o = _partial_slabs.front();
187 _partial_slabs.remove(o);
190 while (!_full_slabs.empty())
192 Slab_i *o = _full_slabs.front();
193 _full_slabs.remove(o);
211 free = &_empty_slabs;
213 if (
free->empty() && !grow())
216 Slab_i *s =
free->front();
220 if (
free == &_empty_slabs)
222 _empty_slabs.remove(s);
230 _partial_slabs.remove(s);
231 _full_slabs.push_front(s);
233 else if (
free == &_empty_slabs)
234 _partial_slabs.push_front(s);
251 unsigned long addr =
reinterpret_cast<unsigned long>(_o);
255 Slab_i *s =
reinterpret_cast<Slab_i*
>(addr);
257 if (s->cache !=
this)
260 Free_o *o =
reinterpret_cast<Free_o*
>(_o);
265 bool was_full =
false;
269 _full_slabs.remove(s);
278 _partial_slabs.remove(s);
280 _empty_slabs.push_front(s);
288 _partial_slabs.push_front(s);
313 for (
typename H_list<Slab_i>::Const_iterator s = _partial_slabs.begin();
314 s != _partial_slabs.end(); ++s)
315 count += s->num_free;
333template<
typename Type,
int Slab_size =
L4_PAGESIZE,
334 int Max_free = 2,
template<
typename A>
class Alloc = New_allocator >
335class Slab :
public Base_slab<sizeof(Type), Slab_size, Max_free, Alloc>
338 typedef Base_slab<
sizeof(Type), Slab_size, Max_free, Alloc> Base_type;
341 typedef Type Obj_type;
345 : Base_slab<sizeof(Type), Slab_size, Max_free, Alloc>(
alloc) {}
367 { Base_slab<
sizeof(Type), Slab_size, Max_free, Alloc>
::free(o); }
386template<
int Obj_size,
int Slab_size =
L4_PAGESIZE,
387 int Max_free = 2,
template<
typename A>
class Alloc = New_allocator >
394 typedef void Obj_type;
412 void *
alloc() noexcept {
return _a.alloc(); }
420 void free(
void *p)
noexcept { _a.free(p); }
444template<
int _O,
int _S,
int _M,
template<
typename A>
class Alloc >
445typename Base_slab_static<_O,_S,_M,Alloc>::_A
446 Base_slab_static<_O,_S,_M,Alloc>::_a;
463template<
typename Type,
int Slab_size =
L4_PAGESIZE,
464 int Max_free = 2,
template<
typename A>
class Alloc = New_allocator >
470 typedef Type Obj_type;
480 return reinterpret_cast<Type *
>(
Merged slab allocator (allocators for objects of the same size are merged together).
unsigned total_objects() const noexcept
Get the total number of objects managed by the slab allocator.
void * alloc() noexcept
Allocate an object.
void free(void *p) noexcept
Free the given object (p).
@ max_free_slabs
Maximum number of free slabs.
@ slab_size
Size of a slab.
@ objects_per_slab
Number of objects per slab.
@ object_size
Size of an object.
unsigned free_objects() const noexcept
Get the number of free objects in the slab allocator.
unsigned free_objects() const noexcept
Get the number of objects which can be allocated before a new empty slab needs to be added to the sla...
Alloc< Slab_i > Slab_alloc
Type of the backend allocator.
void * alloc() noexcept
Allocate a new object.
unsigned total_objects() const noexcept
Get the total number of objects managed by the slab allocator.
void free(void *_o) noexcept
Free the given object (_o).
bool empty() const
Check if the list is empty.
Value_type front() const
Return the first element in the list.
General double-linked list of unspecified cxx::H_list_item elements.
static void remove(T *e)
Remove the given element from its list.
Standard allocator based on operator new () .
Helper type to distinguish the operator new version that does not throw exceptions.
Merged slab allocator (allocators for objects of the same size are merged together).
Type * alloc() noexcept
Allocate an object of type Type.
Type * alloc() noexcept
Allocate an object of type Type.
void free(Type *o) noexcept
Free the object addressed by o.
#define L4_PAGESIZE
Minimal page size (in bytes).
H_list_item_t< void > H_list_item
Untyped list item.