/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright 2015-2018 Danny Robson */ #ifndef CRUFT_UTIL_ALLOC_ARENA_HPP #define CRUFT_UTIL_ALLOC_ARENA_HPP #include "../memory/deleter.hpp" #include "../cast.hpp" #include "../view.hpp" #include #include namespace cruft::alloc { /// wraps a block allocator with an interface suitable for allocating /// individual objects. template class arena { public: explicit arena (T &store): m_store (store) { ; } //--------------------------------------------------------------------- template U* acquire (Args&&... args) { U *data = m_store.template allocate (1).data (); try { new (data) U (std::forward (args)...); } catch (...) { m_store.template deallocate ({data,1}); throw; } return data; } //--------------------------------------------------------------------- template void release (U *u) { u->~U (); m_store.template deallocate (cruft::view {u,1u}); } //--------------------------------------------------------------------- template using deleter_t = cruft::memory::owner_deleter< U,arena,&arena::release >; template 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) }; } private: T &m_store; }; } #endif