diff --git a/alloc/arena.hpp b/alloc/arena.hpp index 28a812ac..c0a3a6f5 100644 --- a/alloc/arena.hpp +++ b/alloc/arena.hpp @@ -18,6 +18,8 @@ #define __UTIL_ALLOC_ARENA_HPP #include +#include "../memory/deleter.hpp" + namespace util { namespace alloc { template @@ -25,20 +27,44 @@ namespace util { namespace alloc { public: arena (T &store); + //--------------------------------------------------------------------- + template + U* + acquire (Args&&...); + + //--------------------------------------------------------------------- template - U* acquire (void); + void + release (U*); + + //--------------------------------------------------------------------- + template + using deleter_t = util::memory::owner_deleter< + U,arena,&arena::release + >; template - std::unique_ptr unique (void); + using unique_t = std::unique_ptr>; + + // the return type must be auto and the implementation must be inline + // otherwise we trigger an internal compiler error in gcc-5.2.0 + // "sorry, unimplemented: mangling offset_ref" + template + auto + unique (Args&& ...args) + { + return unique_t { + acquire (std::forward (args)...), + deleter_t (*this) + }; + } - template - void release (U*); private: T &m_store; }; } } -#include "./arena.hpp" +#include "./arena.ipp" #endif diff --git a/alloc/arena.ipp b/alloc/arena.ipp index 0fa7f2ec..dddfb3f2 100644 --- a/alloc/arena.ipp +++ b/alloc/arena.ipp @@ -34,24 +34,18 @@ template U* util::alloc::arena::acquire (Args&& ...args) { - U *data = m_store.allocate (sizeof (U), alignof (U)); + U *data = reinterpret_cast ( + m_store.allocate (sizeof (U), alignof (U)) + ); try { - new (data) U (std::forward (args)...); + new (data) U (std::forward (args)...); } catch (...) { m_store.deallocate (data, sizeof (U)); throw; } -} - -//----------------------------------------------------------------------------- -template -template -std::unique_ptr -util::alloc::arena::unique (Args&& ...args) -{ - return std::unique_ptr (acquire (std::forward (args)...)); + return data; } @@ -62,7 +56,7 @@ void util::alloc::arena::release (U *u) { u->~U (); - m_store.deallocate (u); + m_store.deallocate (reinterpret_cast (u), sizeof (U)); }