/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright 2015 Danny Robson */ #ifndef __UTIL_ALLOC_ARENA_HPP #define __UTIL_ALLOC_ARENA_HPP #include "../memory/deleter.hpp" #include #include namespace util::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 = reinterpret_cast ( m_store.allocate (sizeof (U), alignof (U)) ); try { new (data) U (std::forward (args)...); } catch (...) { m_store.deallocate (data, sizeof (U)); throw; } return data; } //--------------------------------------------------------------------- template void release (U *u) { u->~U (); m_store.deallocate (reinterpret_cast (u), sizeof (U)); } //--------------------------------------------------------------------- template using deleter_t = util::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