// // libsemigroups - C++ library for semigroups and monoids // Copyright (C) 2020 James D. Mitchell // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>.
// This file contains an implementation of a pool, which provide an easy // way to manage temporary elements while avoiding unnecessary memory // allocation.
#include <list> // for list #include <stack> // for stack #include <type_traits> // for is_pointer #include <unordered_map> // for unordered_map
#include"libsemigroups/exception.hpp"// for LIBSEMIGROUPS_EXCEPTION
namespace libsemigroups { namespace detail {
// Declarations template <typename T, typename = void> class Pool;
template <typename T, typename = void> class PoolGuard;
// Helpers template <typename T> using is_pointer_t = std::enable_if_t<std::is_pointer<T>::value>;
template <typename T> using is_non_pointer_t = std::enable_if_t<!std::is_pointer<T>::value>;
// Pool for non-pointer types, these are intended to be used with the // T = BruidhinnTraits::internal_value_type, and so the non-pointer objects // should be small and easy to copy. There are only versions for pointer // and non-pointer types as BruidhinnTraits::internal_value_type is always // one of these two. It's your responsibility to ensure that the // non-pointer type is actually small and easy to copy. template <typename T> class Pool<T, is_non_pointer_t<T>> final {
static_assert(std::is_default_constructible<T>::value, "Pool requires T to be default-constructible");
// Not noexcept because it can throw
T acquire() { if (_acquirable.empty()) { if (_acquired.empty()) {
LIBSEMIGROUPS_EXCEPTION( "the pool has not been initialised, cannot acquire!");
} // double size
push(_acquired.back(), _acquired.size());
}
T ptr = _acquirable.top();
_acquirable.pop();
_acquired.push_back(ptr);
_map.emplace(ptr, --_acquired.end()); return ptr;
}
// Not noexcept because it can throw void release(T ptr) { auto it = _map.find(ptr); if (it == _map.end()) {
LIBSEMIGROUPS_EXCEPTION("attempted to release an object which is " "not owned by this pool");
}
_acquired.erase(it->second);
_map.erase(it);
_acquirable.push(ptr);
}
// A pool guard acquires an element from the pool on construction and // releases it on destruction. This version doesn't do anything, it's based // on the assumption that the type T is small and easy to copy. template <typename T> class PoolGuard<T, is_non_pointer_t<T>> final {
static_assert(std::is_default_constructible<T>::value, "PoolGuard requires T to be default-constructible");
// Get the element acquired from the pool
T get() const noexcept { return T();
} void swap(T) noexcept {} void shrink_to_fit() {}
};
// A pool guard acquires an element from the pool on construction and // releases it on destruction. template <typename T> class PoolGuard<T, is_pointer_t<T>> final { public: explicit PoolGuard(Pool<T>& pool) : _pool(pool), _tmp(pool.acquire()) {}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.