aboutsummaryrefslogtreecommitdiff
path: root/src/DI/alloc_functor.tpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/DI/alloc_functor.tpp')
-rw-r--r--src/DI/alloc_functor.tpp165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/DI/alloc_functor.tpp b/src/DI/alloc_functor.tpp
new file mode 100644
index 0000000..d3f6946
--- /dev/null
+++ b/src/DI/alloc_functor.tpp
@@ -0,0 +1,165 @@
+#pragma once
+
+#include "alloc_functor.hpp"
+
+template <class Return>
+template <class... Args>
+auto InvokeReturnWrapper<Return>::call(Args &&...args) -> Return
+{
+ return std::invoke(std::forward<Args>(args)...);
+}
+
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
+#define ALLOC_FUNCTOR_TEMPLATE \
+ template <class Function, class Allocator, class Return, class... Args>
+
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
+#define ALLOC_FUNCTOR AllocFunctor<Function, Allocator, Return(Args...)>
+
+ALLOC_FUNCTOR_TEMPLATE
+ALLOC_FUNCTOR::AllocFunctor(Target &&function)
+ : _function(std::piecewise_construct, std::forward_as_tuple(std::move(function)),
+ std::forward_as_tuple())
+{
+}
+
+ALLOC_FUNCTOR_TEMPLATE
+ALLOC_FUNCTOR::AllocFunctor(const Target &function, const Alloc &allocator)
+ : _function(std::piecewise_construct, std::forward_as_tuple(function),
+ std::forward_as_tuple(allocator))
+{
+}
+
+ALLOC_FUNCTOR_TEMPLATE
+ALLOC_FUNCTOR::AllocFunctor(const Target &function, Alloc &&allocator)
+ : _function(std::piecewise_construct, std::forward_as_tuple(function),
+ std::forward_as_tuple(std::move(allocator)))
+{
+}
+
+ALLOC_FUNCTOR_TEMPLATE
+ALLOC_FUNCTOR::AllocFunctor(Target &&function, Alloc &&allocator)
+ : _function(std::piecewise_construct, std::forward_as_tuple(std::move(function)),
+ std::forward_as_tuple(std::move(allocator)))
+{
+}
+
+ALLOC_FUNCTOR_TEMPLATE
+auto ALLOC_FUNCTOR::operator()(Args &&...args) -> Return
+{
+ using Invoker = InvokeReturnWrapper<Return>;
+
+ return Invoker::call(_function.first(), std::forward<Args>(args)...);
+}
+
+ALLOC_FUNCTOR_TEMPLATE
+auto ALLOC_FUNCTOR::target() const -> const Target &
+{
+ return _function.first();
+}
+
+ALLOC_FUNCTOR_TEMPLATE
+auto ALLOC_FUNCTOR::get_allocator() const -> const Alloc &
+{
+ return _function.second();
+}
+
+ALLOC_FUNCTOR_TEMPLATE
+auto ALLOC_FUNCTOR::clone() const -> AllocFunctor *
+{
+ using AllocTraits = std::allocator_traits<Alloc>;
+
+ using AllocHelper = typename RebindAllocHelper<AllocTraits, AllocFunctor>::type;
+
+ auto alloc_helper = AllocHelper(_function.second());
+
+ using Destructor = AllocDestructor<AllocHelper>;
+
+ auto hold = std::unique_ptr<AllocFunctor, Destructor>(alloc_helper.allocate(1),
+ _Dp(alloc_helper, 1));
+
+ ::new (static_cast<void *>(hold.get()))
+ AllocFunctor(_function.first(), _Alloc(alloc_helper));
+
+ return hold.release();
+}
+
+ALLOC_FUNCTOR_TEMPLATE
+void ALLOC_FUNCTOR::destroy() noexcept
+{
+ _function.~CompressedPair<Target, Alloc>();
+}
+
+ALLOC_FUNCTOR_TEMPLATE
+void ALLOC_FUNCTOR::destroy_and_delete(AllocFunctor *functor)
+{
+ using AllocTraits = std::allocator_traits<Alloc>;
+
+ using FunctorAlloc = typename RebindAllocHelper<AllocTraits, AllocFunctor>::type;
+
+ auto functor_alloc = FunctorAlloc(functor->get_allocator());
+
+ functor->destroy();
+ functor_alloc.deallocate(functor, 1);
+}
+
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
+#define DEFAULT_ALLOC_FUNCTOR_TEMPLATE \
+ template <class Function, class Return, class... Args>
+
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
+#define DEFAULT_ALLOC_FUNCTOR DefaultAllocFunctor<Function, Return(Args...)>
+
+DEFAULT_ALLOC_FUNCTOR_TEMPLATE
+DEFAULT_ALLOC_FUNCTOR::DefaultAllocFunctor(Target &&function)
+ : _function(std::move(function))
+{
+}
+
+DEFAULT_ALLOC_FUNCTOR_TEMPLATE
+DEFAULT_ALLOC_FUNCTOR::DefaultAllocFunctor(const Target &function) : _function(function)
+{
+}
+
+DEFAULT_ALLOC_FUNCTOR_TEMPLATE
+auto DEFAULT_ALLOC_FUNCTOR::operator()(Args &&...args) -> Return
+{
+ using Invoker = InvokeReturnWrapper<Return>;
+
+ return Invoker::call(_function, std::forward<Args>(args)...);
+}
+
+DEFAULT_ALLOC_FUNCTOR_TEMPLATE
+auto DEFAULT_ALLOC_FUNCTOR::target() const -> const Target &
+{
+ return _function;
+}
+
+DEFAULT_ALLOC_FUNCTOR_TEMPLATE
+auto DEFAULT_ALLOC_FUNCTOR::clone() const -> DefaultAllocFunctor *
+{
+ std::allocator<DefaultAllocFunctor> allocator;
+
+ DefaultAllocFunctor *functor_ptr = allocator.allocate(1);
+
+ // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
+ auto *res = ::new (static_cast<void *>(functor_ptr)) DefaultAllocFunctor(_function);
+
+ return res;
+}
+
+DEFAULT_ALLOC_FUNCTOR_TEMPLATE
+void DEFAULT_ALLOC_FUNCTOR::destroy() noexcept
+{
+ _function.~_Target();
+}
+
+DEFAULT_ALLOC_FUNCTOR_TEMPLATE
+void DEFAULT_ALLOC_FUNCTOR::destroy_and_delete(DefaultAllocFunctor *function)
+{
+ function->destroy();
+
+ std::allocator<DefaultAllocFunctor> allocator;
+
+ allocator.deallocate(function, 1);
+}