// Matrix Construct // // Copyright (C) Matrix Construct Developers, Authors & Contributors // Copyright (C) 2016-2023 Jason Volk // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice is present in all copies. The // full license for this software is available in the LICENSE file. #pragma once #define HAVE_IRCD_ALLOCATOR_CALLBACK_H namespace ircd::allocator { template struct callback; } /// 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 struct ircd::allocator::callback { struct allocator; public: using allocate_callback = std::function; using deallocate_callback = std::function; 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 struct ircd::allocator::callback::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 struct rebind { typedef ircd::allocator::callback::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 allocator(const typename ircd::allocator::callback::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 inline typename ircd::allocator::callback::allocator ircd::allocator::callback::operator()() { return ircd::allocator::callback::allocator(*this); } template inline ircd::allocator::callback::operator allocator() { return ircd::allocator::callback::allocator(*this); }