mirror of
https://github.com/matrix-construct/construct
synced 2024-11-29 10:12:39 +01:00
ircd::allocator: Add simple callback allocator.
This commit is contained in:
parent
9dac813278
commit
08479976ad
1 changed files with 96 additions and 0 deletions
|
@ -22,6 +22,7 @@ namespace ircd::allocator
|
|||
struct state;
|
||||
struct scope;
|
||||
struct profile;
|
||||
template<class T = void> struct callback;
|
||||
template<class T = char> struct dynamic;
|
||||
template<class T = char, size_t = 512> struct fixed;
|
||||
template<class T = char, size_t L0_SIZE = 512> struct twolevel;
|
||||
|
@ -139,6 +140,101 @@ struct ircd::allocator::state
|
|||
{}
|
||||
};
|
||||
|
||||
/// The callback allocator is a shell around the pre-c++17/20 boilerplate
|
||||
/// jumble for allocator template creation. This is an alternative to virtual
|
||||
/// functions to accomplish the same thing here. Implement the principal
|
||||
/// allocate and deallocate functions and maintain an instance of
|
||||
/// allocator::callback with them somewhere.
|
||||
template<class T>
|
||||
struct ircd::allocator::callback
|
||||
{
|
||||
struct allocator;
|
||||
|
||||
public:
|
||||
using allocate_callback = std::function<T *(const size_t &, const T *const &)>;
|
||||
using deallocate_callback = std::function<void (T *const &, const size_t &)>;
|
||||
|
||||
allocate_callback ac;
|
||||
deallocate_callback dc;
|
||||
|
||||
allocator operator()();
|
||||
operator allocator();
|
||||
|
||||
callback(allocate_callback ac, deallocate_callback dc)
|
||||
:ac{std::move(ac)}
|
||||
,dc{std::move(dc)}
|
||||
{}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct ircd::allocator::callback<T>::allocator
|
||||
{
|
||||
using value_type = T;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
using is_always_equal = std::true_type;
|
||||
using propagate_on_container_move_assignment = std::true_type;
|
||||
|
||||
callback *s;
|
||||
|
||||
public:
|
||||
template<class U> struct rebind
|
||||
{
|
||||
typedef ircd::allocator::callback<T>::allocator other;
|
||||
};
|
||||
|
||||
T *
|
||||
__attribute__((malloc, returns_nonnull, warn_unused_result))
|
||||
allocate(const size_type n, const T *const hint = nullptr)
|
||||
{
|
||||
assert(s && s->ac);
|
||||
return s->ac(n, hint);
|
||||
}
|
||||
|
||||
void deallocate(T *const p, const size_type n = 1)
|
||||
{
|
||||
assert(s && s->dc);
|
||||
return s->dc(p, n);
|
||||
}
|
||||
|
||||
template<class U>
|
||||
allocator(const typename ircd::allocator::callback<U>::allocator &s) noexcept
|
||||
:s{s.s}
|
||||
{}
|
||||
|
||||
allocator(callback &s) noexcept
|
||||
:s{&s}
|
||||
{}
|
||||
|
||||
allocator(allocator &&) = default;
|
||||
allocator(const allocator &) = default;
|
||||
|
||||
friend bool operator==(const allocator &a, const allocator &b)
|
||||
{
|
||||
return &a == &b;
|
||||
}
|
||||
|
||||
friend bool operator!=(const allocator &a, const allocator &b)
|
||||
{
|
||||
return &a == &b;
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
typename ircd::allocator::callback<T>::allocator
|
||||
ircd::allocator::callback<T>::operator()()
|
||||
{
|
||||
return ircd::allocator::callback<T>::allocator(*this);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
ircd::allocator::callback<T>::operator
|
||||
allocator()
|
||||
{
|
||||
return ircd::allocator::callback<T>::allocator(*this);
|
||||
}
|
||||
|
||||
/// The fixed allocator creates a block of data with a size known at compile-
|
||||
/// time. This structure itself is the state object for the actual allocator
|
||||
/// instance used in the container. Create an instance of this structure,
|
||||
|
|
Loading…
Reference in a new issue