47 #ifndef LIB_ALLOCATOR_HANDLE_H 48 #define LIB_ALLOCATOR_HANDLE_H 91 using AlloT = std::allocator_traits<Allo>;
92 using BaseType =
typename Allo::value_type;
94 Allo& baseAllocator() {
return *
this; }
100 using XAllo =
typename AlloT::template rebind_alloc<X>;
101 if constexpr (std::is_constructible_v<XAllo, Allo>)
102 return XAllo{baseAllocator()};
107 template<
class ALOT,
typename...ARGS>
108 typename ALOT::pointer
109 construct (
typename ALOT::allocator_type& allo, ARGS&& ...args)
111 auto loc = ALOT::allocate (allo, 1);
112 try { ALOT::construct (allo, loc, std::forward<ARGS>(args)...); }
115 ALOT::deallocate (allo, loc, 1);
123 destroy (
typename ALOT::allocator_type& allo,
typename ALOT::pointer elm)
125 ALOT::destroy (allo, elm);
126 ALOT::deallocate (allo, elm, 1);
143 : Allo{std::move (allo)}
149 return baseAllocator() == o.baseAllocator();
154 return not (*
this == o);
160 template<
class TY,
typename...ARGS>
164 if constexpr (std::is_same_v<TY, BaseType>)
166 return construct<AlloT> (baseAllocator(), std::forward<ARGS>(args)...);
170 using XAlloT =
typename AlloT::template rebind_traits<TY>;
171 auto xAllo = adaptAllocator<TY>();
172 return construct<XAlloT> (xAllo, std::forward<ARGS>(args)...);
181 if constexpr (std::is_same_v<TY, BaseType>)
183 destroy<AlloT> (baseAllocator(), elm);
187 using XAlloT =
typename AlloT::template rebind_traits<TY>;
188 auto xAllo = adaptAllocator<TY>();
189 destroy<XAlloT> (xAllo, elm);
200 : std::__and_< std::is_empty<FAC>
201 , std::is_default_constructible<FAC>
226 template<
typename TY>
231 factory.dispose (elm);
234 template<
typename TY>
259 template<
class TY,
typename...ARGS>
263 if constexpr (is_Stateless_v<FAC>)
265 using Handle = std::unique_ptr<TY, void(TY*)>;
266 return Handle{FAC::template create<TY> (std::forward<ARGS> (args)...)
272 using Handle = std::unique_ptr<TY, StatefulDeleter<TY>>;
273 return Handle{FAC::template create<TY> (std::forward<ARGS> (args)...)
295 template<
typename TY>
301 std::byte buf_[
sizeof(TY)];
303 template<
typename...ARGS>
307 return *
new(&buf_) TY {std::forward<ARGS> (args)...};
313 return * std::launder (reinterpret_cast<TY*> (&buf_));
322 std::list<Allocation> storage_;
325 template<
typename...ARGS>
327 operator() (ARGS&& ...args)
329 auto pos = storage_.emplace (storage_.end());
331 return pos->create (std::forward<ARGS> (args)...);
335 storage_.erase (pos);
338 ERROR (memory,
"Allocation failed with unknown exception. " 339 "Lumiera errorID=%s", errID?errID:
"??");
349 for (
auto& alloc : storage_)
Adapter to use a generic factory FAC for creating managed object instances with unique ownership...
Generic opaque reference counting handle, for accessing a service and managing its lifecycle...
< Concepts and Adaptors for custom memory management
void dispose(TY *elm)
destroy the given element and discard the associated memory
TY * create(ARGS &&...args)
create new element using the embedded allocator
#define ERROR_LOG_AND_IGNORE(_FLAG_, _OP_DESCR_)
convenience shortcut for a sequence of catch blocks just logging and consuming an error...
Metafunction: probe if the given base factory is possibly monostate.
StdFactory(Allo allo=Allo{})
Create an instance of the adapter factory, forwarding to the embedded standard conforming allocator f...
Implementation namespace for support and library code.
Placeholder implementation for a custom allocator.
lumiera_err lumiera_error(void)
Get and clear current error state.
Lumiera error handling (C++ interface).
static void dispose(TY *elm)
auto make_unique(ARGS &&...args)
Factory function: generate object with scoped ownership and automated clean-up.