From 07b8d1707bac471a1b72cb42dbaec3b4077587c5 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Wed, 17 Jul 2019 03:31:56 +0700 Subject: [PATCH] link blackmatov libraries without copy headers to 3rdparty --- CMakeLists.txt | 13 +- headers/3rdparty/ecs.hpp/ecs.hpp | 2521 ----------------- .../3rdparty/flat.hpp/detail/eq_compare.hpp | 25 - .../3rdparty/flat.hpp/detail/is_sorted.hpp | 38 - .../flat.hpp/detail/is_transparent.hpp | 23 - .../3rdparty/flat.hpp/detail/pair_compare.hpp | 62 - headers/3rdparty/flat.hpp/flat_fwd.hpp | 51 - headers/3rdparty/flat.hpp/flat_map.hpp | 792 ------ headers/3rdparty/flat.hpp/flat_multimap.hpp | 677 ----- headers/3rdparty/flat.hpp/flat_multiset.hpp | 586 ---- headers/3rdparty/flat.hpp/flat_set.hpp | 659 ----- headers/3rdparty/promise.hpp/invoke.hpp | 248 -- headers/3rdparty/promise.hpp/jobber.hpp | 427 --- headers/3rdparty/promise.hpp/promise.hpp | 1306 --------- headers/3rdparty/promise.hpp/scheduler.hpp | 335 --- headers/enduro2d/base/types.hpp | 9 +- headers/enduro2d/core/_core.hpp | 8 +- headers/enduro2d/high/_high.hpp | 2 +- scripts/cloc_all.sh | 3 - scripts/cloc_engine.sh | 3 - scripts/cloc_headers.sh | 6 +- scripts/update_modules.sh | 9 - 22 files changed, 21 insertions(+), 7782 deletions(-) delete mode 100644 headers/3rdparty/ecs.hpp/ecs.hpp delete mode 100644 headers/3rdparty/flat.hpp/detail/eq_compare.hpp delete mode 100644 headers/3rdparty/flat.hpp/detail/is_sorted.hpp delete mode 100644 headers/3rdparty/flat.hpp/detail/is_transparent.hpp delete mode 100644 headers/3rdparty/flat.hpp/detail/pair_compare.hpp delete mode 100644 headers/3rdparty/flat.hpp/flat_fwd.hpp delete mode 100644 headers/3rdparty/flat.hpp/flat_map.hpp delete mode 100644 headers/3rdparty/flat.hpp/flat_multimap.hpp delete mode 100644 headers/3rdparty/flat.hpp/flat_multiset.hpp delete mode 100644 headers/3rdparty/flat.hpp/flat_set.hpp delete mode 100644 headers/3rdparty/promise.hpp/invoke.hpp delete mode 100644 headers/3rdparty/promise.hpp/jobber.hpp delete mode 100644 headers/3rdparty/promise.hpp/promise.hpp delete mode 100644 headers/3rdparty/promise.hpp/scheduler.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 25fd3b04..5754e92d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.11 FATAL_ERROR) if(NOT DEFINED PROJECT_NAME) - set(BUILD_AS_STANDALONE ON) + set(E2D_BUILD_AS_STANDALONE ON) endif() project(enduro2d) @@ -9,7 +9,7 @@ project(enduro2d) set(E2D_SYSTEM_NAME ${CMAKE_SYSTEM_NAME}) set(E2D_ROOT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) -if(NOT BUILD_AS_STANDALONE) +if(NOT E2D_BUILD_AS_STANDALONE) set(E2D_SYSTEM_NAME ${E2D_SYSTEM_NAME} PARENT_SCOPE) set(E2D_ROOT_DIRECTORY ${E2D_ROOT_DIRECTORY} PARENT_SCOPE) endif() @@ -153,6 +153,10 @@ set(USE_EMBEDDED_CURL ON CACHE INTERNAL "" FORCE) add_subdirectory(modules/curly.hpp) set_target_properties(curly.hpp libcurl PROPERTIES FOLDER modules) +add_subdirectory(modules/ecs.hpp) +add_subdirectory(modules/flat.hpp) +add_subdirectory(modules/promise.hpp) + set(GLFW_INSTALL OFF CACHE INTERNAL "" FORCE) set(GLFW_BUILD_DOCS OFF CACHE INTERNAL "" FORCE) set(GLFW_BUILD_TESTS OFF CACHE INTERNAL "" FORCE) @@ -249,7 +253,10 @@ source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${E2D_3RDPARTY}) target_link_libraries(${PROJECT_NAME} - PUBLIC curly.hpp) + PUBLIC curly.hpp + PUBLIC ecs.hpp + PUBLIC flat.hpp + PUBLIC promise.hpp) target_link_libraries(${PROJECT_NAME} PRIVATE bass diff --git a/headers/3rdparty/ecs.hpp/ecs.hpp b/headers/3rdparty/ecs.hpp/ecs.hpp deleted file mode 100644 index 48835fb9..00000000 --- a/headers/3rdparty/ecs.hpp/ecs.hpp +++ /dev/null @@ -1,2521 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/ecs.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// ----------------------------------------------------------------------------- -// -// config -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - class entity; - class const_entity; - - template < typename T > - class component; - template < typename T > - class const_component; - - class prototype; - - class system; - class registry; - - class entity_filler; - class registry_filler; - - using family_id = std::uint16_t; - using entity_id = std::uint32_t; - using priority_t = std::int32_t; - - constexpr std::size_t entity_id_index_bits = 22u; - constexpr std::size_t entity_id_version_bits = 10u; - - static_assert( - std::is_unsigned::value, - "ecs_hpp (family_id must be an unsigned integer)"); - - static_assert( - std::is_unsigned::value, - "ecs_hpp (entity_id must be an unsigned integer)"); - - static_assert( - entity_id_index_bits > 0u && - entity_id_version_bits > 0u && - sizeof(entity_id) == (entity_id_index_bits + entity_id_version_bits) / 8u, - "ecs_hpp (invalid entity id index and version bits)"); -} - -// ----------------------------------------------------------------------------- -// -// utilities -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - namespace detail - { - // - // as_const - // - - template < typename T > - constexpr std::add_const_t& as_const(T& t) noexcept { - return t; - } - - // - // hash_combine - // - - constexpr std::size_t hash_combine(std::size_t l, std::size_t r) noexcept { - return l ^ (r + 0x9e3779b9 + (l << 6) + (l >> 2)); - } - - // - // tuple_tail - // - - namespace impl - { - template < typename T, typename... Ts, std::size_t... Is > - std::tuple tuple_tail_impl( - std::tuple&& t, - std::index_sequence iseq) - { - (void)iseq; - return std::make_tuple(std::move(std::get(t))...); - } - - template < typename T, typename... Ts, std::size_t... Is > - std::tuple tuple_tail_impl( - const std::tuple& t, - std::index_sequence iseq) - { - (void)iseq; - return std::make_tuple(std::get(t)...); - } - } - - template < typename T, typename... Ts > - std::tuple tuple_tail(std::tuple&& t) { - return impl::tuple_tail_impl( - std::move(t), - std::make_index_sequence()); - } - - template < typename T, typename... Ts > - std::tuple tuple_tail(const std::tuple& t) { - return impl::tuple_tail_impl( - t, - std::make_index_sequence()); - } - - // - // tuple_contains - // - - namespace impl - { - template < size_t I, typename V, typename... Ts > - std::enable_if_t - tuple_contains_impl(const std::tuple& t, const V& v) { - (void)t; - (void)v; - return false; - } - - template < size_t I, typename V, typename... Ts > - std::enable_if_t - tuple_contains_impl(const std::tuple& t, const V& v) { - if ( std::get(t) == v ) { - return true; - } - return tuple_contains_impl(t, v); - } - } - - template < typename V, typename... Ts > - bool tuple_contains(const std::tuple& t, const V& v) { - return impl::tuple_contains_impl<0>(t, v); - } - - // - // tiny_tuple_apply - // - - namespace impl - { - template < typename F, typename Tuple, std::size_t... I > - void tiny_tuple_apply_impl(F&& f, Tuple&& args, std::index_sequence) { - std::forward(f)(std::get(std::forward(args))...); - } - } - - template < typename F, typename Tuple > - void tiny_tuple_apply(F&& f, Tuple&& args) { - impl::tiny_tuple_apply_impl( - std::forward(f), - std::forward(args), - std::make_index_sequence>::value>()); - } - - // - // next_capacity_size - // - - inline std::size_t next_capacity_size( - std::size_t cur_size, - std::size_t min_size, - std::size_t max_size) - { - if ( min_size > max_size ) { - throw std::length_error("ecs_hpp::next_capacity_size"); - } - if ( cur_size >= max_size / 2u ) { - return max_size; - } - return std::max(cur_size * 2u, min_size); - } - - // - // entity_id index/version - // - - constexpr std::size_t entity_id_index_mask = (1u << entity_id_index_bits) - 1u; - constexpr std::size_t entity_id_version_mask = (1u << entity_id_version_bits) - 1u; - - constexpr inline entity_id entity_id_index(entity_id id) noexcept { - return id & entity_id_index_mask; - } - - constexpr inline entity_id entity_id_version(entity_id id) noexcept { - return (id >> entity_id_index_bits) & entity_id_version_mask; - } - - constexpr inline entity_id entity_id_join(entity_id index, entity_id version) noexcept { - return index | (version << entity_id_index_bits); - } - - constexpr inline entity_id upgrade_entity_id(entity_id id) noexcept { - return entity_id_join( - entity_id_index(id), - entity_id_version(id) + 1u); - } - } -} - -// ----------------------------------------------------------------------------- -// -// detail::type_family -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - namespace detail - { - template < typename Void = void > - class type_family_base { - static_assert( - std::is_void::value, - "unexpected internal error"); - protected: - static family_id last_id_; - }; - - template < typename T > - class type_family final : public type_family_base<> { - public: - static family_id id() noexcept { - static family_id self_id = ++last_id_; - assert(self_id > 0u && "ecs_hpp::family_id overflow"); - return self_id; - } - }; - - template < typename Void > - family_id type_family_base::last_id_ = 0u; - } -} - -// ----------------------------------------------------------------------------- -// -// detail::sparse_indexer -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - namespace detail - { - template < typename T - , bool = std::is_unsigned::value - && sizeof(T) <= sizeof(std::size_t) > - struct sparse_unsigned_indexer { - std::size_t operator()(const T v) const noexcept { - return static_cast(v); - } - }; - - template < typename T > - struct sparse_unsigned_indexer {}; - - template < typename T > - struct sparse_indexer final - : public sparse_unsigned_indexer {}; - } -} - -// ----------------------------------------------------------------------------- -// -// detail::sparse_set -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - namespace detail - { - template < typename T - , typename Indexer = sparse_indexer > - class sparse_set final { - public: - using iterator = typename std::vector::iterator; - using const_iterator = typename std::vector::const_iterator; - public: - static_assert( - noexcept(std::declval()(std::declval())), - "unsupported sparse_set indexer"); - static_assert( - std::is_nothrow_destructible::value && - std::is_nothrow_move_assignable::value && - noexcept(std::declval() == std::declval()), - "unsupported sparse_set value type"); - public: - iterator begin() noexcept { - return dense_.begin(); - } - - iterator end() noexcept { - return dense_.end(); - } - - const_iterator begin() const noexcept { - return dense_.begin(); - } - - const_iterator end() const noexcept { - return dense_.end(); - } - - const_iterator cbegin() const noexcept { - return dense_.cbegin(); - } - - const_iterator cend() const noexcept { - return dense_.cend(); - } - public: - sparse_set(const Indexer& indexer = Indexer()) - : indexer_(indexer) {} - - sparse_set(const sparse_set& other) = default; - sparse_set& operator=(const sparse_set& other) = default; - - sparse_set(sparse_set&& other) noexcept = default; - sparse_set& operator=(sparse_set&& other) noexcept = default; - - void swap(sparse_set& other) noexcept { - using std::swap; - swap(dense_, other.dense_); - swap(sparse_, other.sparse_); - } - - template < typename UT > - bool insert(UT&& v) { - if ( has(v) ) { - return false; - } - const std::size_t vi = indexer_(v); - if ( vi >= sparse_.size() ) { - sparse_.resize(next_capacity_size( - sparse_.size(), vi + 1u, sparse_.max_size())); - } - dense_.push_back(std::forward(v)); - sparse_[vi] = dense_.size() - 1u; - return true; - } - - template < typename... Args > - bool emplace(Args&&... args) { - return insert(T(std::forward(args)...)); - } - - bool unordered_erase(const T& v) noexcept { - if ( !has(v) ) { - return false; - } - const std::size_t vi = indexer_(v); - const std::size_t dense_index = sparse_[vi]; - if ( dense_index != dense_.size() - 1 ) { - dense_[dense_index] = std::move(dense_.back()); - sparse_[indexer_(dense_[dense_index])] = dense_index; - } - dense_.pop_back(); - return true; - } - - void clear() noexcept { - dense_.clear(); - } - - bool has(const T& v) const noexcept { - const std::size_t vi = indexer_(v); - return vi < sparse_.size() - && sparse_[vi] < dense_.size() - && dense_[sparse_[vi]] == v; - } - - const_iterator find(const T& v) const noexcept { - return has(v) - ? begin() + sparse_[indexer_(v)] - : end(); - } - - std::size_t get_dense_index(const T& v) const { - const auto p = find_dense_index(v); - if ( p.second ) { - return p.first; - } - throw std::logic_error("ecs_hpp::sparse_set (value not found)"); - } - - std::pair find_dense_index(const T& v) const noexcept { - return has(v) - ? std::make_pair(sparse_[indexer_(v)], true) - : std::make_pair(std::size_t(-1), false); - } - - bool empty() const noexcept { - return dense_.empty(); - } - - std::size_t size() const noexcept { - return dense_.size(); - } - - std::size_t memory_usage() const noexcept { - return dense_.capacity() * sizeof(dense_[0]) - + sparse_.capacity() * sizeof(sparse_[0]); - } - private: - Indexer indexer_; - std::vector dense_; - std::vector sparse_; - }; - - template < typename T - , typename Indexer > - void swap( - sparse_set& l, - sparse_set& r) noexcept - { - l.swap(r); - } - } -} - -// ----------------------------------------------------------------------------- -// -// detail::sparse_map -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - namespace detail - { - template < typename K - , typename T - , typename Indexer = sparse_indexer > - class sparse_map final { - public: - using iterator = typename std::vector::iterator; - using const_iterator = typename std::vector::const_iterator; - public: - static_assert( - std::is_nothrow_destructible::value && - std::is_nothrow_move_assignable::value, - "unsupported sparse_map value type"); - public: - iterator begin() noexcept { - return keys_.begin(); - } - - iterator end() noexcept { - return keys_.end(); - } - - const_iterator begin() const noexcept { - return keys_.begin(); - } - - const_iterator end() const noexcept { - return keys_.end(); - } - - const_iterator cbegin() const noexcept { - return keys_.cbegin(); - } - - const_iterator cend() const noexcept { - return keys_.cend(); - } - public: - sparse_map(const Indexer& indexer = Indexer()) - : keys_(indexer) {} - - sparse_map(const sparse_map& other) = default; - sparse_map& operator=(const sparse_map& other) = default; - - sparse_map(sparse_map&& other) noexcept = default; - sparse_map& operator=(sparse_map&& other) noexcept = default; - - void swap(sparse_map& other) noexcept { - using std::swap; - swap(keys_, other.keys_); - swap(values_, other.values_); - } - - template < typename UK, typename UT > - bool insert(UK&& k, UT&& v) { - if ( keys_.has(k) ) { - return false; - } - values_.push_back(std::forward(v)); - try { - return keys_.insert(std::forward(k)); - } catch (...) { - values_.pop_back(); - throw; - } - } - - template < typename UK, typename... Args > - bool emplace(UK&& k, Args&&... args) { - if ( keys_.has(k) ) { - return false; - } - values_.emplace_back(std::forward(args)...); - try { - return keys_.insert(std::forward(k)); - } catch (...) { - values_.pop_back(); - throw; - } - } - - template < typename UK, typename UT > - bool insert_or_assign(UK&& k, UT&& v) { - if ( keys_.has(k) ) { - get(k) = std::forward(v); - return false; - } else { - insert(std::forward(k), std::forward(v)); - return true; - } - } - - bool unordered_erase(const K& k) noexcept { - const auto value_index_p = keys_.find_dense_index(k); - if ( !value_index_p.second ) { - return false; - } - if ( value_index_p.first != values_.size() - 1 ) { - values_[value_index_p.first] = std::move(values_.back()); - } - values_.pop_back(); - keys_.unordered_erase(k); - return true; - } - - void clear() noexcept { - keys_.clear(); - values_.clear(); - } - - bool has(const K& k) const noexcept { - return keys_.has(k); - } - - T& get(const K& k) { - return values_[keys_.get_dense_index(k)]; - } - - const T& get(const K& k) const { - return values_[keys_.get_dense_index(k)]; - } - - T* find(const K& k) noexcept { - const auto value_index_p = keys_.find_dense_index(k); - return value_index_p.second - ? &values_[value_index_p.first] - : nullptr; - } - - const T* find(const K& k) const noexcept { - const auto value_index_p = keys_.find_dense_index(k); - return value_index_p.second - ? &values_[value_index_p.first] - : nullptr; - } - - bool empty() const noexcept { - return values_.empty(); - } - - std::size_t size() const noexcept { - return values_.size(); - } - - std::size_t memory_usage() const noexcept { - return keys_.memory_usage() - + values_.capacity() * sizeof(values_[0]); - } - private: - sparse_set keys_; - std::vector values_; - }; - - template < typename K - , typename T - , typename Indexer > - void swap( - sparse_map& l, - sparse_map& r) noexcept - { - l.swap(r); - } - } -} - -// ----------------------------------------------------------------------------- -// -// detail::entity_id_indexer -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - namespace detail - { - struct entity_id_indexer final { - std::size_t operator()(entity_id id) const noexcept { - return entity_id_index(id); - } - }; - } -} - -// ----------------------------------------------------------------------------- -// -// detail::component_storage -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - namespace detail - { - class component_storage_base { - public: - virtual ~component_storage_base() = default; - virtual bool remove(entity_id id) noexcept = 0; - virtual bool has(entity_id id) const noexcept = 0; - virtual void clone(entity_id from, entity_id to) = 0; - virtual std::size_t memory_usage() const noexcept = 0; - }; - - template < typename T, bool E = std::is_empty::value > - class component_storage final : public component_storage_base { - public: - component_storage(registry& owner) - : owner_(owner) {} - - template < typename... Args > - T& assign(entity_id id, Args&&... args) { - components_.insert_or_assign(id, T(std::forward(args)...)); - return components_.get(id); - } - - bool exists(entity_id id) const noexcept { - return components_.has(id); - } - - bool remove(entity_id id) noexcept override { - return components_.unordered_erase(id); - } - - T* find(entity_id id) noexcept { - return components_.find(id); - } - - const T* find(entity_id id) const noexcept { - return components_.find(id); - } - - std::size_t count() const noexcept { - return components_.size(); - } - - bool has(entity_id id) const noexcept override { - return components_.has(id); - } - - void clone(entity_id from, entity_id to) override { - const T* c = components_.find(from); - if ( c ) { - components_.insert_or_assign(to, *c); - } - } - - template < typename F > - void for_each_component(F&& f) { - for ( const entity_id id : components_ ) { - f(id, components_.get(id)); - } - } - - template < typename F > - void for_each_component(F&& f) const { - for ( const entity_id id : components_ ) { - f(id, components_.get(id)); - } - } - - std::size_t memory_usage() const noexcept override { - return components_.memory_usage(); - } - private: - registry& owner_; - detail::sparse_map components_; - }; - - template < typename T > - class component_storage final : public component_storage_base { - public: - component_storage(registry& owner) - : owner_(owner) {} - - template < typename... Args > - T& assign(entity_id id, Args&&...) { - components_.insert(id); - return empty_value_; - } - - bool exists(entity_id id) const noexcept { - return components_.has(id); - } - - bool remove(entity_id id) noexcept override { - return components_.unordered_erase(id); - } - - T* find(entity_id id) noexcept { - return components_.has(id) - ? &empty_value_ - : nullptr; - } - - const T* find(entity_id id) const noexcept { - return components_.has(id) - ? &empty_value_ - : nullptr; - } - - std::size_t count() const noexcept { - return components_.size(); - } - - bool has(entity_id id) const noexcept override { - return components_.has(id); - } - - void clone(entity_id from, entity_id to) override { - if ( components_.has(from) ) { - components_.insert(to); - } - } - - template < typename F > - void for_each_component(F&& f) { - for ( const entity_id id : components_ ) { - f(id, empty_value_); - } - } - - template < typename F > - void for_each_component(F&& f) const { - for ( const entity_id id : components_ ) { - f(id, empty_value_); - } - } - - std::size_t memory_usage() const noexcept override { - return components_.memory_usage(); - } - private: - registry& owner_; - static T empty_value_; - detail::sparse_set components_; - }; - - template < typename T > - T component_storage::empty_value_; - } -} - -// ----------------------------------------------------------------------------- -// -// entity -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - class entity final { - public: - entity(registry& owner) noexcept; - entity(registry& owner, entity_id id) noexcept; - - entity(const entity&) = default; - entity& operator=(const entity&) = default; - - entity(entity&&) noexcept = default; - entity& operator=(entity&&) noexcept = default; - - registry& owner() noexcept; - const registry& owner() const noexcept; - - entity_id id() const noexcept; - - entity clone() const; - void destroy() noexcept; - bool valid() const noexcept; - - template < typename T, typename... Args > - T& assign_component(Args&&... args); - - template < typename T > - bool remove_component(); - - template < typename T > - bool exists_component() const noexcept; - - std::size_t remove_all_components() noexcept; - - template < typename T > - T& get_component(); - - template < typename T > - const T& get_component() const; - - template < typename T > - T* find_component() noexcept; - - template < typename T > - const T* find_component() const noexcept; - - template < typename... Ts > - std::tuple get_components(); - template < typename... Ts > - std::tuple get_components() const; - - template < typename... Ts > - std::tuple find_components() noexcept; - template < typename... Ts > - std::tuple find_components() const noexcept; - - std::size_t component_count() const noexcept; - private: - registry* owner_{nullptr}; - entity_id id_{0u}; - }; - - bool operator<(const entity& l, const entity& r) noexcept; - - bool operator==(const entity& l, const entity& r) noexcept; - bool operator==(const entity& l, const const_entity& r) noexcept; - - bool operator!=(const entity& l, const entity& r) noexcept; - bool operator!=(const entity& l, const const_entity& r) noexcept; -} - -namespace std -{ - template <> - struct hash final { - std::size_t operator()(const ecs_hpp::entity& ent) const noexcept { - return ecs_hpp::detail::hash_combine( - std::hash()(&ent.owner()), - std::hash()(ent.id())); - } - }; -} - -// ----------------------------------------------------------------------------- -// -// const_entity -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - class const_entity final { - public: - const_entity(const entity& ent) noexcept; - - const_entity(const registry& owner) noexcept; - const_entity(const registry& owner, entity_id id) noexcept; - - const_entity(const const_entity&) = default; - const_entity& operator=(const const_entity&) = default; - - const_entity(const_entity&&) noexcept = default; - const_entity& operator=(const_entity&&) noexcept = default; - - const registry& owner() const noexcept; - entity_id id() const noexcept; - - bool valid() const noexcept; - - template < typename T > - bool exists_component() const noexcept; - - template < typename T > - const T& get_component() const; - - template < typename T > - const T* find_component() const noexcept; - - template < typename... Ts > - std::tuple get_components() const; - - template < typename... Ts > - std::tuple find_components() const noexcept; - - std::size_t component_count() const noexcept; - private: - const registry* owner_{nullptr}; - entity_id id_{0u}; - }; - - bool operator<(const const_entity& l, const const_entity& r) noexcept; - - bool operator==(const const_entity& l, const entity& r) noexcept; - bool operator==(const const_entity& l, const const_entity& r) noexcept; - - bool operator!=(const const_entity& l, const entity& r) noexcept; - bool operator!=(const const_entity& l, const const_entity& r) noexcept; -} - -namespace std -{ - template <> - struct hash final { - std::size_t operator()(const ecs_hpp::const_entity& ent) const noexcept { - return ecs_hpp::detail::hash_combine( - std::hash()(&ent.owner()), - std::hash()(ent.id())); - } - }; -} - -// ----------------------------------------------------------------------------- -// -// component -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - template < typename T > - class component final { - public: - component(const entity& owner) noexcept; - - component(const component&) = default; - component& operator=(const component&) = default; - - component(component&&) noexcept = default; - component& operator=(component&&) noexcept = default; - - entity& owner() noexcept; - const entity& owner() const noexcept; - - bool remove(); - bool exists() const noexcept; - - template < typename... Args > - T& assign(Args&&... args); - - T& get(); - const T& get() const; - - T* find() noexcept; - const T* find() const noexcept; - - T& operator*(); - const T& operator*() const; - - T* operator->() noexcept; - const T* operator->() const noexcept; - - explicit operator bool() const noexcept; - private: - entity owner_; - }; - - template < typename T > - bool operator<(const component& l, const component& r) noexcept; - - template < typename T > - bool operator==(const component& l, const component& r) noexcept; - template < typename T > - bool operator==(const component& l, const const_component& r) noexcept; - - template < typename T > - bool operator!=(const component& l, const component& r) noexcept; - template < typename T > - bool operator!=(const component& l, const const_component& r) noexcept; -} - -namespace std -{ - template < typename T > - struct hash> { - std::size_t operator()(const ecs_hpp::component& comp) const noexcept { - return std::hash()(comp.owner()); - } - }; -} - -// ----------------------------------------------------------------------------- -// -// const_component -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - template < typename T > - class const_component final { - public: - const_component(const component& comp) noexcept; - const_component(const const_entity& owner) noexcept; - - const_component(const const_component&) = default; - const_component& operator=(const const_component&) = default; - - const_component(const_component&&) noexcept = default; - const_component& operator=(const_component&&) noexcept = default; - - const const_entity& owner() const noexcept; - - bool exists() const noexcept; - - const T& get() const; - const T* find() const noexcept; - - const T& operator*() const; - const T* operator->() const noexcept; - explicit operator bool() const noexcept; - private: - const_entity owner_; - }; - - template < typename T > - bool operator<(const const_component& l, const const_component& r) noexcept; - - template < typename T > - bool operator==(const const_component& l, const component& r) noexcept; - template < typename T > - bool operator==(const const_component& l, const const_component& r) noexcept; - - template < typename T > - bool operator!=(const const_component& l, const component& r) noexcept; - template < typename T > - bool operator!=(const const_component& l, const const_component& r) noexcept; -} - -namespace std -{ - template < typename T > - struct hash> { - std::size_t operator()(const ecs_hpp::const_component& comp) const noexcept { - return std::hash()(comp.owner()); - } - }; -} - -// ----------------------------------------------------------------------------- -// -// prototype -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - namespace detail - { - class applier_base; - using applier_uptr = std::unique_ptr; - - class applier_base { - public: - virtual ~applier_base() = default; - virtual applier_uptr clone() const = 0; - virtual void apply_to_entity(entity& ent, bool override) const = 0; - }; - - template < typename T > - class typed_applier : public applier_base { - public: - virtual void apply_to_component(T& component) const = 0; - }; - - template < typename T, typename... Args > - class typed_applier_with_args final : public typed_applier { - public: - typed_applier_with_args(std::tuple&& args); - typed_applier_with_args(const std::tuple& args); - applier_uptr clone() const override; - void apply_to_entity(entity& ent, bool override) const override; - void apply_to_component(T& component) const override; - private: - std::tuple args_; - }; - } - - class prototype final { - public: - prototype() = default; - ~prototype() noexcept = default; - - prototype(const prototype& other); - prototype& operator=(const prototype& other); - - prototype(prototype&& other) noexcept; - prototype& operator=(prototype&& other) noexcept; - - void clear() noexcept; - bool empty() const noexcept; - void swap(prototype& other) noexcept; - - template < typename T > - bool has_component() const noexcept; - - template < typename T, typename... Args > - prototype& component(Args&&... args) &; - template < typename T, typename... Args > - prototype&& component(Args&&... args) &&; - - prototype& merge_with(const prototype& other, bool override) &; - prototype&& merge_with(const prototype& other, bool override) &&; - - template < typename T > - bool apply_to_component(T& component) const; - void apply_to_entity(entity& ent, bool override) const; - private: - detail::sparse_map< - family_id, - detail::applier_uptr> appliers_; - }; - - void swap(prototype& l, prototype& r) noexcept; -} - -// ----------------------------------------------------------------------------- -// -// system -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - class system { - public: - virtual ~system() = default; - virtual void process(registry& owner) = 0; - }; -} - -// ----------------------------------------------------------------------------- -// -// registry -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - class registry final { - private: - class uentity { - public: - uentity(registry& owner, entity_id id) noexcept; - - uentity(entity_id ent) noexcept; - uentity(entity ent) noexcept; - - operator entity_id() const noexcept; - operator entity() const noexcept; - operator const_entity() const noexcept; - - entity_id id() const noexcept; - registry* owner() noexcept; - const registry* owner() const noexcept; - - bool check_owner(const registry* owner) const noexcept; - private: - entity_id id_{0u}; - registry* owner_{nullptr}; - }; - - class const_uentity { - public: - const_uentity(const registry& owner, entity_id id) noexcept; - - const_uentity(entity_id ent) noexcept; - const_uentity(entity ent) noexcept; - const_uentity(const_entity ent) noexcept; - const_uentity(const uentity& ent) noexcept; - - operator entity_id() const noexcept; - operator const_entity() const noexcept; - - entity_id id() const noexcept; - const registry* owner() const noexcept; - - bool check_owner(const registry* owner) const noexcept; - private: - entity_id id_{0u}; - const registry* owner_{nullptr}; - }; - public: - registry() = default; - ~registry() noexcept = default; - - registry(const registry& other) = delete; - registry& operator=(const registry& other) = delete; - - registry(registry&& other) noexcept = default; - registry& operator=(registry&& other) noexcept = default; - - entity wrap_entity(const const_uentity& ent) noexcept; - const_entity wrap_entity(const const_uentity& ent) const noexcept; - - template < typename T > - component wrap_component(const const_uentity& ent) noexcept; - template < typename T > - const_component wrap_component(const const_uentity& ent) const noexcept; - - entity create_entity(); - entity create_entity(const prototype& proto); - entity create_entity(const const_uentity& proto); - - void destroy_entity(const uentity& ent) noexcept; - bool valid_entity(const const_uentity& ent) const noexcept; - - template < typename T, typename... Args > - T& assign_component(const uentity& ent, Args&&... args); - - template < typename T > - bool remove_component(const uentity& ent); - - template < typename T > - bool exists_component(const const_uentity& ent) const noexcept; - - std::size_t remove_all_components(const uentity& ent) noexcept; - - template < typename T > - T& get_component(const uentity& ent); - template < typename T > - const T& get_component(const const_uentity& ent) const; - - template < typename T > - T* find_component(const uentity& ent) noexcept; - template < typename T > - const T* find_component(const const_uentity& ent) const noexcept; - - template < typename... Ts > - std::tuple get_components(const uentity& ent); - template < typename... Ts > - std::tuple get_components(const const_uentity& ent) const; - - template < typename... Ts > - std::tuple find_components(const uentity& ent) noexcept; - template < typename... Ts > - std::tuple find_components(const const_uentity& ent) const noexcept; - - template < typename T > - std::size_t component_count() const noexcept; - std::size_t entity_count() const noexcept; - std::size_t entity_component_count(const const_uentity& ent) const noexcept; - - template < typename F > - void for_each_entity(F&& f); - template < typename F > - void for_each_entity(F&& f) const; - - template < typename T, typename F > - void for_each_component(F&& f); - template < typename T, typename F > - void for_each_component(F&& f) const; - - template < typename... Ts, typename F > - void for_joined_components(F&& f); - template < typename... Ts, typename F > - void for_joined_components(F&& f) const; - - template < typename T, typename... Args > - void add_system(priority_t priority, Args&&... args); - - void process_all_systems(); - void process_systems_above(priority_t min); - void process_systems_below(priority_t max); - void process_systems_in_range(priority_t min, priority_t max); - - struct memory_usage_info { - std::size_t entities{0u}; - std::size_t components{0u}; - }; - memory_usage_info memory_usage() const noexcept; - - template < typename T > - std::size_t component_memory_usage() const noexcept; - private: - template < typename T > - detail::component_storage* find_storage_() noexcept; - - template < typename T > - const detail::component_storage* find_storage_() const noexcept; - - template < typename T > - detail::component_storage& get_or_create_storage_(); - - template < typename T - , typename... Ts - , typename F - , std::size_t I - , std::size_t... Is > - void for_joined_components_impl_( - F&& f, - std::index_sequence iseq); - - template < typename T - , typename... Ts - , typename F - , std::size_t I - , std::size_t... Is > - void for_joined_components_impl_( - F&& f, - std::index_sequence iseq) const; - - template < typename T - , typename... Ts - , typename F - , typename Ss - , typename... Cs > - void for_joined_components_impl_( - const uentity& e, - const F& f, - const Ss& ss, - Cs&... cs); - - template < typename T - , typename... Ts - , typename F - , typename Ss - , typename... Cs > - void for_joined_components_impl_( - const const_uentity& e, - const F& f, - const Ss& ss, - const Cs&... cs) const; - - template < typename F, typename... Cs > - void for_joined_components_impl_( - const uentity& e, - const F& f, - const std::tuple<>& ss, - Cs&... cs); - - template < typename F, typename... Cs > - void for_joined_components_impl_( - const const_uentity& e, - const F& f, - const std::tuple<>& ss, - const Cs&... cs) const; - private: - entity_id last_entity_id_{0u}; - std::vector free_entity_ids_; - detail::sparse_set entity_ids_; - - using storage_uptr = std::unique_ptr; - detail::sparse_map storages_; - - using system_uptr = std::unique_ptr; - std::vector> systems_; - }; -} - -// ----------------------------------------------------------------------------- -// -// fillers -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - class entity_filler final { - public: - entity_filler(entity& entity) noexcept - : entity_(entity) {} - - template < typename T, typename... Args > - entity_filler& component(Args&&... args) { - entity_.assign_component(std::forward(args)...); - return *this; - } - private: - entity& entity_; - }; - - class registry_filler final { - public: - registry_filler(registry& registry) noexcept - : registry_(registry) {} - - template < typename T, typename... Args > - registry_filler& system(priority_t priority, Args&&... args) { - registry_.add_system( - priority, - std::forward(args)...); - return *this; - } - private: - registry& registry_; - }; -} - -// ----------------------------------------------------------------------------- -// -// entity impl -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - inline entity::entity(registry& owner) noexcept - : owner_(&owner) {} - - inline entity::entity(registry& owner, entity_id id) noexcept - : owner_(&owner) - , id_(id) {} - - inline registry& entity::owner() noexcept { - return *owner_; - } - - inline const registry& entity::owner() const noexcept { - return *owner_; - } - - inline entity_id entity::id() const noexcept { - return id_; - } - - inline entity entity::clone() const { - return (*owner_).create_entity(id_); - } - - inline void entity::destroy() noexcept { - (*owner_).destroy_entity(id_); - } - - inline bool entity::valid() const noexcept { - return detail::as_const(*owner_).valid_entity(id_); - } - - template < typename T, typename... Args > - T& entity::assign_component(Args&&... args) { - return (*owner_).assign_component( - id_, - std::forward(args)...); - } - - template < typename T > - bool entity::remove_component() { - return (*owner_).remove_component(id_); - } - - template < typename T > - bool entity::exists_component() const noexcept { - return detail::as_const(*owner_).exists_component(id_); - } - - inline std::size_t entity::remove_all_components() noexcept { - return (*owner_).remove_all_components(id_); - } - - template < typename T > - T& entity::get_component() { - return (*owner_).get_component(id_); - } - - template < typename T > - const T& entity::get_component() const { - return detail::as_const(*owner_).get_component(id_); - } - - template < typename T > - T* entity::find_component() noexcept { - return (*owner_).find_component(id_); - } - - template < typename T > - const T* entity::find_component() const noexcept { - return detail::as_const(*owner_).find_component(id_); - } - - template < typename... Ts > - std::tuple entity::get_components() { - return (*owner_).get_components(id_); - } - - template < typename... Ts > - std::tuple entity::get_components() const { - return detail::as_const(*owner_).get_components(id_); - } - - template < typename... Ts > - std::tuple entity::find_components() noexcept { - return (*owner_).find_components(id_); - } - - template < typename... Ts > - std::tuple entity::find_components() const noexcept { - return detail::as_const(*owner_).find_components(id_); - } - - inline std::size_t entity::component_count() const noexcept { - return detail::as_const(*owner_).entity_component_count(id_); - } - - inline bool operator<(const entity& l, const entity& r) noexcept { - return (&l.owner() < &r.owner()) - || (&l.owner() == &r.owner() && l.id() < r.id()); - } - - inline bool operator==(const entity& l, const entity& r) noexcept { - return &l.owner() == &r.owner() - && l.id() == r.id(); - } - - inline bool operator==(const entity& l, const const_entity& r) noexcept { - return &l.owner() == &r.owner() - && l.id() == r.id(); - } - - inline bool operator!=(const entity& l, const entity& r) noexcept { - return !(l == r); - } - - inline bool operator!=(const entity& l, const const_entity& r) noexcept { - return !(l == r); - } -} - -// ----------------------------------------------------------------------------- -// -// const_entity impl -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - inline const_entity::const_entity(const entity& ent) noexcept - : owner_(&ent.owner()) - , id_(ent.id()) {} - - inline const_entity::const_entity(const registry& owner) noexcept - : owner_(&owner) {} - - inline const_entity::const_entity(const registry& owner, entity_id id) noexcept - : owner_(&owner) - , id_(id) {} - - inline const registry& const_entity::owner() const noexcept { - return *owner_; - } - - inline entity_id const_entity::id() const noexcept { - return id_; - } - - inline bool const_entity::valid() const noexcept { - return (*owner_).valid_entity(id_); - } - - template < typename T > - bool const_entity::exists_component() const noexcept { - return (*owner_).exists_component(id_); - } - - template < typename T > - const T& const_entity::get_component() const { - return (*owner_).get_component(id_); - } - - template < typename T > - const T* const_entity::find_component() const noexcept { - return (*owner_).find_component(id_); - } - - template < typename... Ts > - std::tuple const_entity::get_components() const { - return (*owner_).get_components(id_); - } - - template < typename... Ts > - std::tuple const_entity::find_components() const noexcept { - return (*owner_).find_components(id_); - } - - inline std::size_t const_entity::component_count() const noexcept { - return (*owner_).entity_component_count(id_); - } - - inline bool operator<(const const_entity& l, const const_entity& r) noexcept { - return (&l.owner() < &r.owner()) - || (&l.owner() == &r.owner() && l.id() < r.id()); - } - - inline bool operator==(const const_entity& l, const entity& r) noexcept { - return &l.owner() == &r.owner() - && l.id() == r.id(); - } - - inline bool operator==(const const_entity& l, const const_entity& r) noexcept { - return &l.owner() == &r.owner() - && l.id() == r.id(); - } - - inline bool operator!=(const const_entity& l, const entity& r) noexcept { - return !(l == r); - } - - inline bool operator!=(const const_entity& l, const const_entity& r) noexcept { - return !(l == r); - } -} - -// ----------------------------------------------------------------------------- -// -// component impl -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - template < typename T > - component::component(const entity& owner) noexcept - : owner_(owner) {} - - template < typename T > - entity& component::owner() noexcept { - return owner_; - } - - template < typename T > - const entity& component::owner() const noexcept { - return owner_; - } - - template < typename T > - bool component::remove() { - return owner_.remove_component(); - } - - template < typename T > - bool component::exists() const noexcept { - return owner_.exists_component(); - } - - template < typename T > - template < typename... Args > - T& component::assign(Args&&... args) { - return owner_.assign_component( - std::forward(args)...); - } - - template < typename T > - T& component::get() { - return owner_.get_component(); - } - - template < typename T > - const T& component::get() const { - return detail::as_const(owner_).template get_component(); - } - - template < typename T > - T* component::find() noexcept { - return owner_.find_component(); - } - - template < typename T > - const T* component::find() const noexcept { - return detail::as_const(owner_).template find_component(); - } - - template < typename T > - T& component::operator*() { - return get(); - } - - template < typename T > - const T& component::operator*() const { - return get(); - } - - template < typename T > - T* component::operator->() noexcept { - return find(); - } - - template < typename T > - const T* component::operator->() const noexcept { - return find(); - } - - template < typename T > - component::operator bool() const noexcept { - return exists(); - } - - template < typename T > - bool operator<(const component& l, const component& r) noexcept { - return l.owner() < r.owner(); - } - - template < typename T > - bool operator==(const component& l, const component& r) noexcept { - return l.owner() == r.owner(); - } - - template < typename T > - bool operator==(const component& l, const const_component& r) noexcept { - return l.owner() == r.owner(); - } - - template < typename T > - bool operator!=(const component& l, const component& r) noexcept { - return !(l == r); - } - - template < typename T > - bool operator!=(const component& l, const const_component& r) noexcept { - return !(l == r); - } -} - -// ----------------------------------------------------------------------------- -// -// const_component impl -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - template < typename T > - const_component::const_component(const component& comp) noexcept - : owner_(comp.owner()) {} - - template < typename T > - const_component::const_component(const const_entity& owner) noexcept - : owner_(owner) {} - - template < typename T > - const const_entity& const_component::owner() const noexcept { - return owner_; - } - - template < typename T > - bool const_component::exists() const noexcept { - return detail::as_const(owner_).template exists_component(); - } - - template < typename T > - const T& const_component::get() const { - return detail::as_const(owner_).template get_component(); - } - - template < typename T > - const T* const_component::find() const noexcept { - return detail::as_const(owner_).template find_component(); - } - - template < typename T > - const T& const_component::operator*() const { - return get(); - } - - template < typename T > - const T* const_component::operator->() const noexcept { - return find(); - } - - template < typename T > - const_component::operator bool() const noexcept { - return exists(); - } - - template < typename T > - bool operator<(const const_component& l, const const_component& r) noexcept { - return l.owner() < r.owner(); - } - - template < typename T > - bool operator==(const const_component& l, const component& r) noexcept { - return l.owner() == r.owner(); - } - - template < typename T > - bool operator==(const const_component& l, const const_component& r) noexcept { - return l.owner() == r.owner(); - } - - template < typename T > - bool operator!=(const const_component& l, const component& r) noexcept { - return !(l == r); - } - - template < typename T > - bool operator!=(const const_component& l, const const_component& r) noexcept { - return !(l == r); - } -} - -// ----------------------------------------------------------------------------- -// -// prototype impl -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - namespace detail - { - template < typename T, typename... Args > - typed_applier_with_args::typed_applier_with_args(std::tuple&& args) - : args_(std::move(args)) {} - - template < typename T, typename... Args > - typed_applier_with_args::typed_applier_with_args(const std::tuple& args) - : args_(args) {} - - template < typename T, typename... Args > - applier_uptr typed_applier_with_args::clone() const { - return std::make_unique(args_); - } - - template < typename T, typename... Args > - void typed_applier_with_args::apply_to_entity(entity& ent, bool override) const { - detail::tiny_tuple_apply([&ent, override](const Args&... args){ - if ( override || !ent.exists_component() ) { - ent.assign_component(args...); - } - }, args_); - } - - template < typename T, typename... Args > - void typed_applier_with_args::apply_to_component(T& component) const { - detail::tiny_tuple_apply([&component](const Args&... args){ - component = T(args...); - }, args_); - } - } - - inline prototype::prototype(const prototype& other) { - for ( const family_id family : other.appliers_ ) { - appliers_.insert(family, other.appliers_.get(family)->clone()); - } - } - - inline prototype& prototype::operator=(const prototype& other) { - if ( this != &other ) { - prototype p(other); - swap(p); - } - return *this; - } - - inline prototype::prototype(prototype&& other) noexcept - : appliers_(std::move(other.appliers_)) {} - - inline prototype& prototype::operator=(prototype&& other) noexcept { - if ( this != &other ) { - swap(other); - other.clear(); - } - return *this; - } - - inline void prototype::clear() noexcept { - appliers_.clear(); - } - - inline bool prototype::empty() const noexcept { - return appliers_.empty(); - } - - inline void prototype::swap(prototype& other) noexcept { - using std::swap; - swap(appliers_, other.appliers_); - } - - template < typename T > - bool prototype::has_component() const noexcept { - const auto family = detail::type_family::id(); - return appliers_.has(family); - } - - template < typename T, typename... Args > - prototype& prototype::component(Args&&... args) & { - using applier_t = detail::typed_applier_with_args< - T, - std::decay_t...>; - auto applier = std::make_unique( - std::make_tuple(std::forward(args)...)); - const auto family = detail::type_family::id(); - appliers_.insert_or_assign(family, std::move(applier)); - return *this; - } - - template < typename T, typename... Args > - prototype&& prototype::component(Args&&... args) && { - component(std::forward(args)...); - return std::move(*this); - } - - inline prototype& prototype::merge_with(const prototype& other, bool override) & { - for ( const auto family : other.appliers_ ) { - if ( override || !appliers_.has(family) ) { - appliers_.insert_or_assign( - family, - other.appliers_.get(family)->clone()); - } - } - return *this; - } - - inline prototype&& prototype::merge_with(const prototype& other, bool override) && { - merge_with(other, override); - return std::move(*this); - } - - template < typename T > - bool prototype::apply_to_component(T& component) const { - const auto family = detail::type_family::id(); - const auto applier_base_ptr = appliers_.find(family); - if ( !applier_base_ptr ) { - return false; - } - using applier_t = detail::typed_applier; - const auto applier = static_cast(applier_base_ptr->get()); - applier->apply_to_component(component); - return true; - } - - inline void prototype::apply_to_entity(entity& ent, bool override) const { - for ( const auto family : appliers_ ) { - appliers_.get(family)->apply_to_entity(ent, override); - } - } - - inline void swap(prototype& l, prototype& r) noexcept { - l.swap(r); - } -} - -// ----------------------------------------------------------------------------- -// -// registry impl -// -// ----------------------------------------------------------------------------- - -namespace ecs_hpp -{ - // - // registry::uentity - // - - inline registry::uentity::uentity(registry& owner, entity_id id) noexcept - : id_(id) - , owner_(&owner) {} - - inline registry::uentity::uentity(entity_id ent) noexcept - : id_(ent) {} - - inline registry::uentity::uentity(entity ent) noexcept - : id_(ent.id()) - , owner_(&ent.owner()) {} - - inline registry::uentity::operator entity_id() const noexcept { - return id_; - } - - inline registry::uentity::operator entity() const noexcept { - assert(owner_); - return {*owner_, id_}; - } - - inline registry::uentity::operator const_entity() const noexcept { - assert(owner_); - return {*owner_, id_}; - } - - inline entity_id registry::uentity::id() const noexcept { - return id_; - } - - inline registry* registry::uentity::owner() noexcept { - return owner_; - } - - inline const registry* registry::uentity::owner() const noexcept { - return owner_; - } - - inline bool registry::uentity::check_owner(const registry* owner) const noexcept { - return !owner_ || owner_ == owner; - } - - // - // registry::const_uentity - // - - inline registry::const_uentity::const_uentity(const registry& owner, entity_id id) noexcept - : id_(id) - , owner_(&owner) {} - - inline registry::const_uentity::const_uentity(entity_id ent) noexcept - : id_(ent) {} - - inline registry::const_uentity::const_uentity(entity ent) noexcept - : id_(ent.id()) - , owner_(&ent.owner()) {} - - inline registry::const_uentity::const_uentity(const_entity ent) noexcept - : id_(ent.id()) - , owner_(&ent.owner()) {} - - inline registry::const_uentity::const_uentity(const uentity& ent) noexcept - : id_(ent.id()) - , owner_(ent.owner()) {} - - inline registry::const_uentity::operator entity_id() const noexcept { - return id_; - } - - inline registry::const_uentity::operator const_entity() const noexcept { - assert(owner_); - return {*owner_, id_}; - } - - inline entity_id registry::const_uentity::id() const noexcept { - return id_; - } - - inline const registry* registry::const_uentity::owner() const noexcept { - return owner_; - } - - inline bool registry::const_uentity::check_owner(const registry* owner) const noexcept { - return !owner_ || owner_ == owner; - } - - // - // registry - // - - inline entity registry::wrap_entity(const const_uentity& ent) noexcept { - return {*this, ent.id()}; - } - - inline const_entity registry::wrap_entity(const const_uentity& ent) const noexcept { - return {*this, ent.id()}; - } - - template < typename T > - component registry::wrap_component(const const_uentity& ent) noexcept { - return {wrap_entity(ent)}; - } - - template < typename T > - const_component registry::wrap_component(const const_uentity& ent) const noexcept { - return {wrap_entity(ent)}; - } - - inline entity registry::create_entity() { - if ( !free_entity_ids_.empty() ) { - const auto free_ent_id = free_entity_ids_.back(); - const auto new_ent_id = detail::upgrade_entity_id(free_ent_id); - entity_ids_.insert(new_ent_id); - free_entity_ids_.pop_back(); - return wrap_entity(new_ent_id); - - } - if ( last_entity_id_ >= detail::entity_id_index_mask ) { - throw std::logic_error("ecs_hpp::registry (entity index overlow)"); - } - if ( free_entity_ids_.capacity() <= entity_ids_.size() ) { - // ensure free entity ids capacity for safe (noexcept) entity destroying - free_entity_ids_.reserve(detail::next_capacity_size( - free_entity_ids_.capacity(), - entity_ids_.size() + 1, - free_entity_ids_.max_size())); - } - entity_ids_.insert(last_entity_id_ + 1); - return wrap_entity(++last_entity_id_); - } - - inline entity registry::create_entity(const prototype& proto) { - auto ent = create_entity(); - try { - proto.apply_to_entity(ent, true); - } catch (...) { - destroy_entity(ent); - throw; - } - return ent; - } - - inline entity registry::create_entity(const const_uentity& proto) { - assert(valid_entity(proto)); - entity ent = create_entity(); - try { - for ( const auto family : storages_ ) { - storages_.get(family)->clone(proto, ent.id()); - } - } catch (...) { - destroy_entity(ent); - throw; - } - return ent; - } - - inline void registry::destroy_entity(const uentity& ent) noexcept { - assert(valid_entity(ent)); - remove_all_components(ent); - if ( entity_ids_.unordered_erase(ent) ) { - assert(free_entity_ids_.size() < free_entity_ids_.capacity()); - free_entity_ids_.push_back(ent); - } - } - - inline bool registry::valid_entity(const const_uentity& ent) const noexcept { - assert(ent.check_owner(this)); - return entity_ids_.has(ent); - } - - template < typename T, typename... Args > - T& registry::assign_component(const uentity& ent, Args&&... args) { - assert(valid_entity(ent)); - return get_or_create_storage_().assign( - ent, - std::forward(args)...); - } - - template < typename T > - bool registry::remove_component(const uentity& ent) { - assert(valid_entity(ent)); - detail::component_storage* storage = find_storage_(); - return storage - ? storage->remove(ent) - : false; - } - - template < typename T > - bool registry::exists_component(const const_uentity& ent) const noexcept { - assert(valid_entity(ent)); - const detail::component_storage* storage = find_storage_(); - return storage - ? storage->exists(ent) - : false; - } - - inline std::size_t registry::remove_all_components(const uentity& ent) noexcept { - assert(valid_entity(ent)); - std::size_t removed_count = 0u; - for ( const auto family : storages_ ) { - if ( storages_.get(family)->remove(ent) ) { - ++removed_count; - } - } - return removed_count; - } - - template < typename T > - T& registry::get_component(const uentity& ent) { - assert(valid_entity(ent)); - T* component = find_component(ent); - if ( component ) { - return *component; - } - throw std::logic_error("ecs_hpp::registry (component not found)"); - } - - template < typename T > - const T& registry::get_component(const const_uentity& ent) const { - assert(valid_entity(ent)); - const T* component = find_component(ent); - if ( component ) { - return *component; - } - throw std::logic_error("ecs_hpp::registry (component not found)"); - } - - template < typename T > - T* registry::find_component(const uentity& ent) noexcept { - assert(valid_entity(ent)); - detail::component_storage* storage = find_storage_(); - return storage - ? storage->find(ent) - : nullptr; - } - - template < typename T > - const T* registry::find_component(const const_uentity& ent) const noexcept { - assert(valid_entity(ent)); - const detail::component_storage* storage = find_storage_(); - return storage - ? storage->find(ent) - : nullptr; - } - - template < typename... Ts > - std::tuple registry::get_components(const uentity& ent) { - assert(valid_entity(ent)); - return std::make_tuple(std::ref(get_component(ent))...); - } - - template < typename... Ts > - std::tuple registry::get_components(const const_uentity& ent) const { - assert(valid_entity(ent)); - return std::make_tuple(std::cref(get_component(ent))...); - } - - template < typename... Ts > - std::tuple registry::find_components(const uentity& ent) noexcept { - assert(valid_entity(ent)); - return std::make_tuple(find_component(ent)...); - } - - template < typename... Ts > - std::tuple registry::find_components(const const_uentity& ent) const noexcept { - assert(valid_entity(ent)); - return std::make_tuple(find_component(ent)...); - } - - template < typename T > - std::size_t registry::component_count() const noexcept { - const detail::component_storage* storage = find_storage_(); - return storage - ? storage->count() - : 0u; - } - - inline std::size_t registry::entity_count() const noexcept { - return entity_ids_.size(); - } - - inline std::size_t registry::entity_component_count(const const_uentity& ent) const noexcept { - assert(valid_entity(ent)); - std::size_t component_count = 0u; - for ( const auto family : storages_ ) { - if ( storages_.get(family)->has(ent) ) { - ++component_count; - } - } - return component_count; - } - - template < typename F > - void registry::for_each_entity(F&& f) { - for ( const auto id : entity_ids_ ) { - f({*this, id}); - } - } - - template < typename F > - void registry::for_each_entity(F&& f) const { - for ( const auto id : entity_ids_ ) { - f({*this, id}); - } - } - - template < typename T, typename F > - void registry::for_each_component(F&& f) { - detail::component_storage* storage = find_storage_(); - if ( storage ) { - storage->for_each_component([this, &f](const entity_id e, T& t){ - f(uentity{*this, e}, t); - }); - } - } - - template < typename T, typename F > - void registry::for_each_component(F&& f) const { - const detail::component_storage* storage = find_storage_(); - if ( storage ) { - storage->for_each_component([this, &f](const entity_id e, const T& t){ - f(const_uentity{*this, e}, t); - }); - } - } - - template < typename... Ts, typename F > - void registry::for_joined_components(F&& f) { - for_joined_components_impl_( - std::forward(f), - std::make_index_sequence()); - } - - template < typename... Ts, typename F > - void registry::for_joined_components(F&& f) const { - for_joined_components_impl_( - std::forward(f), - std::make_index_sequence()); - } - - template < typename T, typename... Args > - void registry::add_system(priority_t priority, Args&&... args) { - auto iter = std::upper_bound( - systems_.begin(), systems_.end(), priority, - [](priority_t pr, const auto& r){ - return pr < r.first; - }); - systems_.emplace( - iter, - priority, - std::make_unique(std::forward(args)...)); - } - - inline void registry::process_all_systems() { - process_systems_in_range( - std::numeric_limits::min(), - std::numeric_limits::max()); - } - - inline void registry::process_systems_above(priority_t min) { - process_systems_in_range( - min, - std::numeric_limits::max()); - } - - inline void registry::process_systems_below(priority_t max) { - process_systems_in_range( - std::numeric_limits::min(), - max); - } - - inline void registry::process_systems_in_range(priority_t min, priority_t max) { - const auto first = std::lower_bound( - systems_.begin(), systems_.end(), min, - [](const auto& p, priority_t pr) noexcept { - return p.first < pr; - }); - for ( auto iter = first; iter != systems_.end() && iter->first <= max; ++iter ) { - iter->second->process(*this); - } - } - - inline registry::memory_usage_info registry::memory_usage() const noexcept { - memory_usage_info info; - info.entities += free_entity_ids_.capacity() * sizeof(free_entity_ids_[0]); - info.entities += entity_ids_.memory_usage(); - for ( const auto family : storages_ ) { - info.components += storages_.get(family)->memory_usage(); - } - return info; - } - - template < typename T > - std::size_t registry::component_memory_usage() const noexcept { - const detail::component_storage* storage = find_storage_(); - return storage - ? storage->memory_usage() - : 0u; - } - - template < typename T > - detail::component_storage* registry::find_storage_() noexcept { - const auto family = detail::type_family::id(); - using raw_storage_ptr = detail::component_storage*; - const storage_uptr* storage_uptr_ptr = storages_.find(family); - return storage_uptr_ptr && *storage_uptr_ptr - ? static_cast(storage_uptr_ptr->get()) - : nullptr; - } - - template < typename T > - const detail::component_storage* registry::find_storage_() const noexcept { - const auto family = detail::type_family::id(); - using raw_storage_ptr = const detail::component_storage*; - const storage_uptr* storage_uptr_ptr = storages_.find(family); - return storage_uptr_ptr && *storage_uptr_ptr - ? static_cast(storage_uptr_ptr->get()) - : nullptr; - } - - template < typename T > - detail::component_storage& registry::get_or_create_storage_() { - detail::component_storage* storage = find_storage_(); - if ( storage ) { - return *storage; - } - const auto family = detail::type_family::id(); - storages_.emplace( - family, - std::make_unique>(*this)); - return *static_cast*>( - storages_.get(family).get()); - } - - template < typename T - , typename... Ts - , typename F - , std::size_t I - , std::size_t... Is > - void registry::for_joined_components_impl_( - F&& f, - std::index_sequence iseq) - { - (void)iseq; - const auto ss = std::make_tuple(find_storage_()...); - if ( !detail::tuple_contains(ss, nullptr) ) { - for_each_component([this, &f, &ss](const uentity& e, T& t) { - for_joined_components_impl_(e, f, ss, t); - }); - } - } - - template < typename T - , typename... Ts - , typename F - , std::size_t I - , std::size_t... Is > - void registry::for_joined_components_impl_( - F&& f, - std::index_sequence iseq) const - { - (void)iseq; - const auto ss = std::make_tuple(find_storage_()...); - if ( !detail::tuple_contains(ss, nullptr) ) { - for_each_component([this, &f, &ss](const const_uentity& e, const T& t) { - detail::as_const(*this).for_joined_components_impl_(e, f, ss, t); - }); - } - } - - template < typename T - , typename... Ts - , typename F - , typename Ss - , typename... Cs > - void registry::for_joined_components_impl_( - const uentity& e, - const F& f, - const Ss& ss, - Cs&... cs) - { - T* c = std::get<0>(ss)->find(e); - if ( c ) { - for_joined_components_impl_( - e, - f, - detail::tuple_tail(ss), - cs..., - *c); - } - } - - template < typename T - , typename... Ts - , typename F - , typename Ss - , typename... Cs > - void registry::for_joined_components_impl_( - const const_uentity& e, - const F& f, - const Ss& ss, - const Cs&... cs) const - { - const T* c = std::get<0>(ss)->find(e); - if ( c ) { - for_joined_components_impl_( - e, - f, - detail::tuple_tail(ss), - cs..., - *c); - } - } - - template < typename F, typename... Cs > - void registry::for_joined_components_impl_( - const uentity& e, - const F& f, - const std::tuple<>& ss, - Cs&... cs) - { - (void)ss; - f(e, cs...); - } - - template < typename F, typename... Cs > - void registry::for_joined_components_impl_( - const const_uentity& e, - const F& f, - const std::tuple<>& ss, - const Cs&... cs) const - { - (void)ss; - f(e, cs...); - } -} diff --git a/headers/3rdparty/flat.hpp/detail/eq_compare.hpp b/headers/3rdparty/flat.hpp/detail/eq_compare.hpp deleted file mode 100644 index 7498a417..00000000 --- a/headers/3rdparty/flat.hpp/detail/eq_compare.hpp +++ /dev/null @@ -1,25 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/flat.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2019, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -namespace flat_hpp::detail -{ - template < typename Compare > - class eq_compare : public Compare { - public: - eq_compare() = default; - - eq_compare(const Compare& compare) - : Compare(compare) {} - - template < typename L, typename R > - bool operator()(const L& l, const R& r) const { - return !Compare::operator()(l, r) - && !Compare::operator()(r, l); - } - }; -} diff --git a/headers/3rdparty/flat.hpp/detail/is_sorted.hpp b/headers/3rdparty/flat.hpp/detail/is_sorted.hpp deleted file mode 100644 index 7372c0c7..00000000 --- a/headers/3rdparty/flat.hpp/detail/is_sorted.hpp +++ /dev/null @@ -1,38 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/flat.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2019, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -namespace flat_hpp::detail -{ - template < typename Iter, typename Compare > - bool is_sorted(Iter first, Iter last, Compare comp) { - if ( first != last ) { - Iter next = first; - while ( ++next != last ) { - if ( comp(*next, *first) ) { - return false; - } - ++first; - } - } - return true; - } - - template < typename Iter, typename Compare > - bool is_sorted_unique(Iter first, Iter last, Compare comp) { - if ( first != last ){ - Iter next = first; - while ( ++next != last ) { - if ( !comp(*first, *next) ) { - return false; - } - ++first; - } - } - return true; - } -} diff --git a/headers/3rdparty/flat.hpp/detail/is_transparent.hpp b/headers/3rdparty/flat.hpp/detail/is_transparent.hpp deleted file mode 100644 index 2f6ec110..00000000 --- a/headers/3rdparty/flat.hpp/detail/is_transparent.hpp +++ /dev/null @@ -1,23 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/flat.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2019, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include - -namespace flat_hpp::detail -{ - template < typename T, typename U, typename = void > - struct is_transparent - : std::false_type {}; - - template < typename T, typename U > - struct is_transparent> - : std::true_type {}; - - template < typename T, typename U > - inline constexpr bool is_transparent_v = is_transparent::value; -} diff --git a/headers/3rdparty/flat.hpp/detail/pair_compare.hpp b/headers/3rdparty/flat.hpp/detail/pair_compare.hpp deleted file mode 100644 index 3d90c44c..00000000 --- a/headers/3rdparty/flat.hpp/detail/pair_compare.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/flat.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2019, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include "is_transparent.hpp" - -namespace flat_hpp::detail -{ - template < typename Pair, typename Compare > - class pair_compare : public Compare { - public: - pair_compare() = default; - - pair_compare(const Compare& compare) - : Compare(compare) {} - - bool operator()( - const typename Pair::first_type& l, - const typename Pair::first_type& r) const - { - return Compare::operator()(l, r); - } - - bool operator()(const Pair& l, const Pair& r) const { - return Compare::operator()(l.first, r.first); - } - - bool operator()( - const typename Pair::first_type& l, - const Pair& r) const - { - return Compare::operator()(l, r.first); - } - - bool operator()( - const Pair& l, - const typename Pair::first_type& r) const - { - return Compare::operator()(l.first, r); - } - - template < typename K > - std::enable_if_t< - is_transparent_v, - bool> - operator()(const K& l, const Pair& r) const { - return Compare::operator()(l, r.first); - } - - template < typename K > - std::enable_if_t< - is_transparent_v, - bool> - operator()(const Pair& l, const K& r) const { - return Compare::operator()(l.first, r); - } - }; -} diff --git a/headers/3rdparty/flat.hpp/flat_fwd.hpp b/headers/3rdparty/flat.hpp/flat_fwd.hpp deleted file mode 100644 index da10e37d..00000000 --- a/headers/3rdparty/flat.hpp/flat_fwd.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/flat.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2019, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include "detail/is_sorted.hpp" -#include "detail/eq_compare.hpp" -#include "detail/pair_compare.hpp" -#include "detail/is_transparent.hpp" - -namespace flat_hpp -{ - struct sorted_range_t {}; - inline constexpr sorted_range_t sorted_range = sorted_range_t(); - - struct sorted_unique_range_t : public sorted_range_t {}; - inline constexpr sorted_unique_range_t sorted_unique_range = sorted_unique_range_t(); - - template < typename Key - , typename Compare = std::less - , typename Container = std::vector > - class flat_set; - - template < typename Key - , typename Compare = std::less - , typename Container = std::vector > - class flat_multiset; - - template < typename Key - , typename Value - , typename Compare = std::less - , typename Container = std::vector> > - class flat_map; - - template < typename Key - , typename Value - , typename Compare = std::less - , typename Container = std::vector> > - class flat_multimap; -} diff --git a/headers/3rdparty/flat.hpp/flat_map.hpp b/headers/3rdparty/flat.hpp/flat_map.hpp deleted file mode 100644 index e32ae44e..00000000 --- a/headers/3rdparty/flat.hpp/flat_map.hpp +++ /dev/null @@ -1,792 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/flat.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2019, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include "flat_fwd.hpp" - -namespace flat_hpp -{ - template < typename Key - , typename Value - , typename Compare - , typename Container > - class flat_map - : private detail::pair_compare< - typename Container::value_type, - Compare> - { - using base_type = detail::pair_compare< - typename Container::value_type, - Compare>; - public: - using key_type = Key; - using mapped_type = Value; - using value_type = typename Container::value_type; - - using size_type = typename Container::size_type; - using difference_type = typename Container::difference_type; - - using key_compare = Compare; - using container_type = Container; - - using reference = typename Container::reference; - using const_reference = typename Container::const_reference; - using pointer = typename Container::pointer; - using const_pointer = typename Container::const_pointer; - - using iterator = typename Container::iterator; - using const_iterator = typename Container::const_iterator; - using reverse_iterator = typename Container::reverse_iterator; - using const_reverse_iterator = typename Container::const_reverse_iterator; - - class value_compare : private key_compare { - public: - bool operator()(const value_type& l, const value_type& r) const { - return key_compare::operator()(l.first, r.first); - } - protected: - friend class flat_map; - explicit value_compare(key_compare compare) - : key_compare(std::move(compare)) {} - }; - public: - flat_map() - noexcept(std::is_nothrow_default_constructible_v - && std::is_nothrow_default_constructible_v) {} - - explicit flat_map(const Compare& c) - : base_type(c) {} - - template < typename Allocator > - explicit flat_map(const Allocator& a) - : data_(a) {} - - template < typename Allocator > - flat_map(const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) {} - - template < typename InputIter > - flat_map(InputIter first, InputIter last) { - from_range_(first, last); - } - - template < typename InputIter > - flat_map(sorted_range_t, InputIter first, InputIter last) { - from_range_(sorted_range, first, last); - } - - template < typename InputIter > - flat_map(sorted_unique_range_t, InputIter first, InputIter last) { - from_range_(sorted_unique_range, first, last); - } - - template < typename InputIter > - flat_map(InputIter first, InputIter last, const Compare& c) - : base_type(c) { - from_range_(first, last); - } - - template < typename InputIter > - flat_map(sorted_range_t, InputIter first, InputIter last, const Compare& c) - : base_type(c) { - from_range_(sorted_range, first, last); - } - - template < typename InputIter > - flat_map(sorted_unique_range_t, InputIter first, InputIter last, const Compare& c) - : base_type(c) { - from_range_(sorted_unique_range, first, last); - } - - template < typename InputIter, typename Allocator > - flat_map(InputIter first, InputIter last, const Allocator& a) - : data_(a) { - from_range_(first, last); - } - - template < typename InputIter, typename Allocator > - flat_map(sorted_range_t, InputIter first, InputIter last, const Allocator& a) - : data_(a) { - from_range_(sorted_range, first, last); - } - - template < typename InputIter, typename Allocator > - flat_map(sorted_unique_range_t, InputIter first, InputIter last, const Allocator& a) - : data_(a) { - from_range_(sorted_unique_range, first, last); - } - - template < typename InputIter, typename Allocator > - flat_map(InputIter first, InputIter last, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(first, last); - } - - template < typename InputIter, typename Allocator > - flat_map(sorted_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(sorted_range, first, last); - } - - template < typename InputIter, typename Allocator > - flat_map(sorted_unique_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(sorted_unique_range, first, last); - } - - flat_map(std::initializer_list ilist) { - from_range_(ilist.begin(), ilist.end()); - } - - flat_map(sorted_range_t, std::initializer_list ilist) { - from_range_(sorted_range, ilist.begin(), ilist.end()); - } - - flat_map(sorted_unique_range_t, std::initializer_list ilist) { - from_range_(sorted_unique_range, ilist.begin(), ilist.end()); - } - - flat_map(std::initializer_list ilist, const Compare& c) - : base_type(c) { - from_range_(ilist.begin(), ilist.end()); - } - - flat_map(sorted_range_t, std::initializer_list ilist, const Compare& c) - : base_type(c) { - from_range_(sorted_range, ilist.begin(), ilist.end()); - } - - flat_map(sorted_unique_range_t, std::initializer_list ilist, const Compare& c) - : base_type(c) { - from_range_(sorted_unique_range, ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_map(std::initializer_list ilist, const Allocator& a) - : data_(a) { - from_range_(ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_map(sorted_range_t, std::initializer_list ilist, const Allocator& a) - : data_(a) { - from_range_(sorted_range, ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_map(sorted_unique_range_t, std::initializer_list ilist, const Allocator& a) - : data_(a) { - from_range_(sorted_unique_range, ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_map(std::initializer_list ilist, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_map(sorted_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(sorted_range, ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_map(sorted_unique_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(sorted_unique_range, ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_map(flat_map&& other, const Allocator& a) - : base_type(static_cast(other)) - , data_(std::move(other.data_), a) {} - - template < typename Allocator > - flat_map(const flat_map& other, const Allocator& a) - : base_type(static_cast(other)) - , data_(other.data_, a) {} - - flat_map(flat_map&& other) = default; - flat_map(const flat_map& other) = default; - - flat_map& operator=(flat_map&& other) = default; - flat_map& operator=(const flat_map& other) = default; - - flat_map& operator=(std::initializer_list ilist) { - flat_map(ilist).swap(*this); - return *this; - } - - iterator begin() - noexcept(noexcept(std::declval().begin())) { - return data_.begin(); - } - - const_iterator begin() const - noexcept(noexcept(std::declval().begin())) { - return data_.begin(); - } - - const_iterator cbegin() const - noexcept(noexcept(std::declval().cbegin())) { - return data_.cbegin(); - } - - iterator end() - noexcept(noexcept(std::declval().end())) { - return data_.end(); - } - - const_iterator end() const - noexcept(noexcept(std::declval().end())) { - return data_.end(); - } - - const_iterator cend() const - noexcept(noexcept(std::declval().cend())) { - return data_.cend(); - } - - reverse_iterator rbegin() - noexcept(noexcept(std::declval().rbegin())) { - return data_.rbegin(); - } - - const_reverse_iterator rbegin() const - noexcept(noexcept(std::declval().rbegin())) { - return data_.rbegin(); - } - - const_reverse_iterator crbegin() const - noexcept(noexcept(std::declval().crbegin())) { - return data_.crbegin(); - } - - reverse_iterator rend() - noexcept(noexcept(std::declval().rend())) { - return data_.rend(); - } - - const_reverse_iterator rend() const - noexcept(noexcept(std::declval().rend())) { - return data_.rend(); - } - - const_reverse_iterator crend() const - noexcept(noexcept(std::declval().crend())) { - return data_.crend(); - } - - bool empty() const - noexcept(noexcept(std::declval().empty())) { - return data_.empty(); - } - - size_type size() const - noexcept(noexcept(std::declval().size())) { - return data_.size(); - } - - size_type max_size() const - noexcept(noexcept(std::declval().max_size())) { - return data_.max_size(); - } - - size_type capacity() const - noexcept(noexcept(std::declval().capacity())) { - return data_.capacity(); - } - - void reserve(size_type ncapacity) { - data_.reserve(ncapacity); - } - - void shrink_to_fit() { - data_.shrink_to_fit(); - } - - mapped_type& operator[](key_type&& key) { - const iterator iter = find(key); - return iter != end() - ? iter->second - : emplace(std::move(key), mapped_type()).first->second; - } - - mapped_type& operator[](const key_type& key) { - const iterator iter = find(key); - return iter != end() - ? iter->second - : emplace(key, mapped_type()).first->second; - } - - mapped_type& at(const key_type& key) { - const iterator iter = find(key); - if ( iter != end() ) { - return iter->second; - } - throw std::out_of_range("flat_map::at: key not found"); - } - - const mapped_type& at(const key_type& key) const { - const const_iterator iter = find(key); - if ( iter != end() ) { - return iter->second; - } - throw std::out_of_range("flat_map::at: key not found"); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - mapped_type&> - at(const K& key) { - const iterator iter = find(key); - if ( iter != end() ) { - return iter->second; - } - throw std::out_of_range("flat_map::at: key not found"); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - const mapped_type&> - at(const K& key) const { - const const_iterator iter = find(key); - if ( iter != end() ) { - return iter->second; - } - throw std::out_of_range("flat_map::at: key not found"); - } - - std::pair insert(value_type&& value) { - const iterator iter = lower_bound(value.first); - return iter == end() || this->operator()(value, *iter) - ? std::make_pair(data_.insert(iter, std::move(value)), true) - : std::make_pair(iter, false); - } - - std::pair insert(const value_type& value) { - const iterator iter = lower_bound(value.first); - return iter == end() || this->operator()(value, *iter) - ? std::make_pair(data_.insert(iter, value), true) - : std::make_pair(iter, false); - } - - iterator insert(const_iterator hint, value_type&& value) { - return (hint == begin() || this->operator()(*(hint - 1), value)) - && (hint == end() || this->operator()(value, *hint)) - ? data_.insert(hint, std::move(value)) - : insert(std::move(value)).first; - } - - iterator insert(const_iterator hint, const value_type& value) { - return (hint == begin() || this->operator()(*(hint - 1), value)) - && (hint == end() || this->operator()(value, *hint)) - ? data_.insert(hint, value) - : insert(value).first; - } - - template < typename TT > - std::pair insert_or_assign(key_type&& key, TT&& value) { - iterator iter = lower_bound(key); - if ( iter == end() || this->operator()(key, *iter) ) { - iter = emplace_hint(iter, std::move(key), std::forward(value)); - return {iter, true}; - } - (*iter).second = std::forward(value); - return {iter, false}; - } - - template < typename TT > - std::pair insert_or_assign(const key_type& key, TT&& value) { - iterator iter = lower_bound(key); - if ( iter == end() || this->operator()(key, *iter) ) { - iter = emplace_hint(iter, key, std::forward(value)); - return {iter, true}; - } - (*iter).second = std::forward(value); - return {iter, false}; - } - - template < typename InputIter > - void insert(InputIter first, InputIter last) { - insert_range_(first, last); - } - - template < typename InputIter > - void insert(sorted_range_t, InputIter first, InputIter last) { - insert_range_(sorted_range, first, last); - } - - void insert(std::initializer_list ilist) { - insert_range_(ilist.begin(), ilist.end()); - } - - void insert(sorted_range_t, std::initializer_list ilist) { - insert_range_(sorted_range, ilist.begin(), ilist.end()); - } - - template < typename... Args > - std::pair emplace(Args&&... args) { - return insert(value_type(std::forward(args)...)); - } - - template < typename... Args > - iterator emplace_hint(const_iterator hint, Args&&... args) { - return insert(hint, value_type(std::forward(args)...)); - } - - template < typename... Args > - std::pair try_emplace(key_type&& key, Args&&... args) { - iterator iter = lower_bound(key); - if ( iter == end() || this->operator()(key, *iter) ) { - iter = emplace_hint(iter, std::move(key), std::forward(args)...); - return {iter, true}; - } - return {iter, false}; - } - - template < typename... Args > - std::pair try_emplace(const key_type& key, Args&&... args) { - iterator iter = lower_bound(key); - if ( iter == end() || this->operator()(key, *iter) ) { - iter = emplace_hint(iter, key, std::forward(args)...); - return {iter, true}; - } - return {iter, false}; - } - - void clear() - noexcept(noexcept(std::declval().clear())) { - data_.clear(); - } - - iterator erase(const_iterator iter) { - return data_.erase(iter); - } - - iterator erase(const_iterator first, const_iterator last) { - return data_.erase(first, last); - } - - size_type erase(const key_type& key) { - const const_iterator iter = find(key); - return iter != end() - ? (erase(iter), 1) - : 0; - } - - void swap(flat_map& other) - noexcept(std::is_nothrow_swappable_v - && std::is_nothrow_swappable_v) - { - using std::swap; - swap( - static_cast(*this), - static_cast(other)); - swap(data_, other.data_); - } - - size_type count(const key_type& key) const { - const const_iterator iter = find(key); - return iter != end() ? 1 : 0; - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - size_type> - count(const K& key) const { - const const_iterator iter = find(key); - return iter != end() ? 1 : 0; - } - - iterator find(const key_type& key) { - const iterator iter = lower_bound(key); - return iter != end() && !this->operator()(key, *iter) - ? iter - : end(); - } - - const_iterator find(const key_type& key) const { - const const_iterator iter = lower_bound(key); - return iter != end() && !this->operator()(key, *iter) - ? iter - : end(); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - iterator> - find(const K& key) { - const iterator iter = lower_bound(key); - return iter != end() && !this->operator()(key, *iter) - ? iter - : end(); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - const_iterator> - find(const K& key) const { - const const_iterator iter = lower_bound(key); - return iter != end() && !this->operator()(key, *iter) - ? iter - : end(); - } - - bool contains(const key_type& key) const { - return find(key) != end(); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - bool> - contains(const K& key) const { - return find(key) != end(); - } - - std::pair equal_range(const key_type& key) { - const base_type& comp = *this; - return std::equal_range(begin(), end(), key, comp); - } - - std::pair equal_range(const key_type& key) const { - const base_type& comp = *this; - return std::equal_range(begin(), end(), key, comp); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - std::pair> - equal_range(const K& key) { - const base_type& comp = *this; - return std::equal_range(begin(), end(), key, comp); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - std::pair> - equal_range(const K& key) const { - const base_type& comp = *this; - return std::equal_range(begin(), end(), key, comp); - } - - iterator lower_bound(const key_type& key) { - const base_type& comp = *this; - return std::lower_bound(begin(), end(), key, comp); - } - - const_iterator lower_bound(const key_type& key) const { - const base_type& comp = *this; - return std::lower_bound(begin(), end(), key, comp); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - iterator> - lower_bound(const K& key) { - const base_type& comp = *this; - return std::lower_bound(begin(), end(), key, comp); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - const_iterator> - lower_bound(const K& key) const { - const base_type& comp = *this; - return std::lower_bound(begin(), end(), key, comp); - } - - iterator upper_bound(const key_type& key) { - const base_type& comp = *this; - return std::upper_bound(begin(), end(), key, comp); - } - - const_iterator upper_bound(const key_type& key) const { - const base_type& comp = *this; - return std::upper_bound(begin(), end(), key, comp); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - iterator> - upper_bound(const K& key) { - const base_type& comp = *this; - return std::upper_bound(begin(), end(), key, comp); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - const_iterator> - upper_bound(const K& key) const { - const base_type& comp = *this; - return std::upper_bound(begin(), end(), key, comp); - } - - key_compare key_comp() const { - return *this; - } - - value_compare value_comp() const { - return value_compare(key_comp()); - } - private: - template < typename Iter > - void from_range_(Iter first, Iter last) { - assert(data_.empty()); - data_.insert(data_.end(), first, last); - std::sort(data_.begin(), data_.end(), value_comp()); - data_.erase( - std::unique(data_.begin(), data_.end(), - detail::eq_compare(value_comp())), - data_.end()); - } - - template < typename Iter > - void from_range_(sorted_range_t, Iter first, Iter last) { - assert(data_.empty()); - assert(detail::is_sorted(first, last, value_comp())); - data_.insert(data_.end(), first, last); - data_.erase( - std::unique(data_.begin(), data_.end(), - detail::eq_compare(value_comp())), - data_.end()); - } - - template < typename Iter > - void from_range_(sorted_unique_range_t, Iter first, Iter last) { - assert(data_.empty()); - assert(detail::is_sorted_unique(first, last, value_comp())); - data_.insert(data_.end(), first, last); - } - private: - template < typename Iter > - void insert_range_(Iter first, Iter last) { - const auto mid_iter = data_.insert(data_.end(), first, last); - std::sort(mid_iter, data_.end(), value_comp()); - std::inplace_merge(data_.begin(), mid_iter, data_.end(), value_comp()); - data_.erase( - std::unique(data_.begin(), data_.end(), - detail::eq_compare(value_comp())), - data_.end()); - } - - template < typename Iter > - void insert_range_(sorted_range_t, Iter first, Iter last) { - assert(detail::is_sorted(first, last, value_comp())); - const auto mid_iter = data_.insert(data_.end(), first, last); - std::inplace_merge(data_.begin(), mid_iter, data_.end(), value_comp()); - data_.erase( - std::unique(data_.begin(), data_.end(), - detail::eq_compare(value_comp())), - data_.end()); - } - private: - container_type data_; - }; -} - -namespace flat_hpp -{ - template < typename Key - , typename Value - , typename Compare - , typename Container > - void swap( - flat_map& l, - flat_map& r) - noexcept(noexcept(l.swap(r))) - { - l.swap(r); - } - - template < typename Key - , typename Value - , typename Compare - , typename Container > - bool operator==( - const flat_map& l, - const flat_map& r) - { - return l.size() == r.size() - && std::equal(l.begin(), l.end(), r.begin()); - } - - template < typename Key - , typename Value - , typename Compare - , typename Container > - bool operator!=( - const flat_map& l, - const flat_map& r) - { - return !(l == r); - } - - template < typename Key - , typename Value - , typename Compare - , typename Container > - bool operator<( - const flat_map& l, - const flat_map& r) - { - return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); - } - - template < typename Key - , typename Value - , typename Compare - , typename Container > - bool operator>( - const flat_map& l, - const flat_map& r) - { - return r < l; - } - - template < typename Key - , typename Value - , typename Compare - , typename Container > - bool operator<=( - const flat_map& l, - const flat_map& r) - { - return !(r < l); - } - - template < typename Key - , typename Value - , typename Compare - , typename Container > - bool operator>=( - const flat_map& l, - const flat_map& r) - { - return !(l < r); - } -} diff --git a/headers/3rdparty/flat.hpp/flat_multimap.hpp b/headers/3rdparty/flat.hpp/flat_multimap.hpp deleted file mode 100644 index a0adff75..00000000 --- a/headers/3rdparty/flat.hpp/flat_multimap.hpp +++ /dev/null @@ -1,677 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/flat.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2019, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include "flat_fwd.hpp" - -namespace flat_hpp -{ - template < typename Key - , typename Value - , typename Compare - , typename Container > - class flat_multimap - : private detail::pair_compare< - typename Container::value_type, - Compare> - { - using base_type = detail::pair_compare< - typename Container::value_type, - Compare>; - public: - using key_type = Key; - using mapped_type = Value; - using value_type = typename Container::value_type; - - using size_type = typename Container::size_type; - using difference_type = typename Container::difference_type; - - using key_compare = Compare; - using container_type = Container; - - using reference = typename Container::reference; - using const_reference = typename Container::const_reference; - using pointer = typename Container::pointer; - using const_pointer = typename Container::const_pointer; - - using iterator = typename Container::iterator; - using const_iterator = typename Container::const_iterator; - using reverse_iterator = typename Container::reverse_iterator; - using const_reverse_iterator = typename Container::const_reverse_iterator; - - class value_compare : private key_compare { - public: - bool operator()(const value_type& l, const value_type& r) const { - return key_compare::operator()(l.first, r.first); - } - protected: - friend class flat_multimap; - explicit value_compare(key_compare compare) - : key_compare(std::move(compare)) {} - }; - public: - flat_multimap() - noexcept(std::is_nothrow_default_constructible_v - && std::is_nothrow_default_constructible_v) {} - - explicit flat_multimap(const Compare& c) - : base_type(c) {} - - template < typename Allocator > - explicit flat_multimap(const Allocator& a) - : data_(a) {} - - template < typename Allocator > - flat_multimap(const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) {} - - template < typename InputIter > - flat_multimap(InputIter first, InputIter last) { - from_range_(first, last); - } - - template < typename InputIter > - flat_multimap(sorted_range_t, InputIter first, InputIter last) { - from_range_(sorted_range, first, last); - } - - template < typename InputIter > - flat_multimap(InputIter first, InputIter last, const Compare& c) - : base_type(c) { - from_range_(first, last); - } - - template < typename InputIter > - flat_multimap(sorted_range_t, InputIter first, InputIter last, const Compare& c) - : base_type(c) { - from_range_(sorted_range, first, last); - } - - template < typename InputIter, typename Allocator > - flat_multimap(InputIter first, InputIter last, const Allocator& a) - : data_(a) { - from_range_(first, last); - } - - template < typename InputIter, typename Allocator > - flat_multimap(sorted_range_t, InputIter first, InputIter last, const Allocator& a) - : data_(a) { - from_range_(sorted_range, first, last); - } - - template < typename InputIter, typename Allocator > - flat_multimap(InputIter first, InputIter last, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(first, last); - } - - template < typename InputIter, typename Allocator > - flat_multimap(sorted_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(sorted_range, first, last); - } - - flat_multimap(std::initializer_list ilist) { - from_range_(ilist.begin(), ilist.end()); - } - - flat_multimap(sorted_range_t, std::initializer_list ilist) { - from_range_(sorted_range, ilist.begin(), ilist.end()); - } - - flat_multimap(std::initializer_list ilist, const Compare& c) - : base_type(c) { - from_range_(ilist.begin(), ilist.end()); - } - - flat_multimap(sorted_range_t, std::initializer_list ilist, const Compare& c) - : base_type(c) { - from_range_(sorted_range, ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_multimap(std::initializer_list ilist, const Allocator& a) - : data_(a) { - from_range_(ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_multimap(sorted_range_t, std::initializer_list ilist, const Allocator& a) - : data_(a) { - from_range_(sorted_range, ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_multimap(std::initializer_list ilist, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_multimap(sorted_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(sorted_range, ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_multimap(flat_multimap&& other, const Allocator& a) - : base_type(static_cast(other)) - , data_(std::move(other.data_), a) {} - - template < typename Allocator > - flat_multimap(const flat_multimap& other, const Allocator& a) - : base_type(static_cast(other)) - , data_(other.data_, a) {} - - flat_multimap(flat_multimap&& other) = default; - flat_multimap(const flat_multimap& other) = default; - - flat_multimap& operator=(flat_multimap&& other) = default; - flat_multimap& operator=(const flat_multimap& other) = default; - - flat_multimap& operator=(std::initializer_list ilist) { - flat_multimap(ilist).swap(*this); - return *this; - } - - iterator begin() - noexcept(noexcept(std::declval().begin())) { - return data_.begin(); - } - - const_iterator begin() const - noexcept(noexcept(std::declval().begin())) { - return data_.begin(); - } - - const_iterator cbegin() const - noexcept(noexcept(std::declval().cbegin())) { - return data_.cbegin(); - } - - iterator end() - noexcept(noexcept(std::declval().end())) { - return data_.end(); - } - - const_iterator end() const - noexcept(noexcept(std::declval().end())) { - return data_.end(); - } - - const_iterator cend() const - noexcept(noexcept(std::declval().cend())) { - return data_.cend(); - } - - reverse_iterator rbegin() - noexcept(noexcept(std::declval().rbegin())) { - return data_.rbegin(); - } - - const_reverse_iterator rbegin() const - noexcept(noexcept(std::declval().rbegin())) { - return data_.rbegin(); - } - - const_reverse_iterator crbegin() const - noexcept(noexcept(std::declval().crbegin())) { - return data_.crbegin(); - } - - reverse_iterator rend() - noexcept(noexcept(std::declval().rend())) { - return data_.rend(); - } - - const_reverse_iterator rend() const - noexcept(noexcept(std::declval().rend())) { - return data_.rend(); - } - - const_reverse_iterator crend() const - noexcept(noexcept(std::declval().crend())) { - return data_.crend(); - } - - bool empty() const - noexcept(noexcept(std::declval().empty())) { - return data_.empty(); - } - - size_type size() const - noexcept(noexcept(std::declval().size())) { - return data_.size(); - } - - size_type max_size() const - noexcept(noexcept(std::declval().max_size())) { - return data_.max_size(); - } - - size_type capacity() const - noexcept(noexcept(std::declval().capacity())) { - return data_.capacity(); - } - - void reserve(size_type ncapacity) { - data_.reserve(ncapacity); - } - - void shrink_to_fit() { - data_.shrink_to_fit(); - } - - mapped_type& operator[](key_type&& key) { - const iterator iter = find(key); - return iter != end() - ? iter->second - : emplace(std::move(key), mapped_type())->second; - } - - mapped_type& operator[](const key_type& key) { - const iterator iter = find(key); - return iter != end() - ? iter->second - : emplace(key, mapped_type())->second; - } - - mapped_type& at(const key_type& key) { - const iterator iter = find(key); - if ( iter != end() ) { - return iter->second; - } - throw std::out_of_range("flat_multimap::at: key not found"); - } - - const mapped_type& at(const key_type& key) const { - const const_iterator iter = find(key); - if ( iter != end() ) { - return iter->second; - } - throw std::out_of_range("flat_multimap::at: key not found"); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - mapped_type&> - at(const K& key) { - const iterator iter = find(key); - if ( iter != end() ) { - return iter->second; - } - throw std::out_of_range("flat_multimap::at: key not found"); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - const mapped_type&> - at(const K& key) const { - const const_iterator iter = find(key); - if ( iter != end() ) { - return iter->second; - } - throw std::out_of_range("flat_multimap::at: key not found"); - } - - iterator insert(value_type&& value) { - const iterator iter = upper_bound(value.first); - return data_.insert(iter, std::move(value)); - } - - iterator insert(const value_type& value) { - const iterator iter = upper_bound(value.first); - return data_.insert(iter, value); - } - - iterator insert(const_iterator hint, value_type&& value) { - return (hint == begin() || !this->operator()(value, *(hint - 1))) - && (hint == end() || !this->operator()(*hint, value)) - ? data_.insert(hint, std::move(value)) - : insert(std::move(value)); - } - - iterator insert(const_iterator hint, const value_type& value) { - return (hint == begin() || !this->operator()(value, *(hint - 1))) - && (hint == end() || !this->operator()(*hint, value)) - ? data_.insert(hint, value) - : insert(value); - } - - template < typename InputIter > - void insert(InputIter first, InputIter last) { - insert_range_(first, last); - } - - template < typename InputIter > - void insert(sorted_range_t, InputIter first, InputIter last) { - insert_range_(sorted_range, first, last); - } - - void insert(std::initializer_list ilist) { - insert_range_(ilist.begin(), ilist.end()); - } - - void insert(sorted_range_t, std::initializer_list ilist) { - insert_range_(sorted_range, ilist.begin(), ilist.end()); - } - - template < typename... Args > - iterator emplace(Args&&... args) { - return insert(value_type(std::forward(args)...)); - } - - template < typename... Args > - iterator emplace_hint(const_iterator hint, Args&&... args) { - return insert(hint, value_type(std::forward(args)...)); - } - - void clear() - noexcept(noexcept(std::declval().clear())) { - data_.clear(); - } - - iterator erase(const_iterator iter) { - return data_.erase(iter); - } - - iterator erase(const_iterator first, const_iterator last) { - return data_.erase(first, last); - } - - size_type erase(const key_type& key) { - const auto p = equal_range(key); - size_type r = std::distance(p.first, p.second); - erase(p.first, p.second); - return r; - } - - void swap(flat_multimap& other) - noexcept(std::is_nothrow_swappable_v - && std::is_nothrow_swappable_v) - { - using std::swap; - swap( - static_cast(*this), - static_cast(other)); - swap(data_, other.data_); - } - - size_type count(const key_type& key) const { - const auto p = equal_range(key); - return std::distance(p.first, p.second); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - size_type> - count(const K& key) const { - const auto p = equal_range(key); - return std::distance(p.first, p.second); - } - - iterator find(const key_type& key) { - const iterator iter = lower_bound(key); - return iter != end() && !this->operator()(key, *iter) - ? iter - : end(); - } - - const_iterator find(const key_type& key) const { - const const_iterator iter = lower_bound(key); - return iter != end() && !this->operator()(key, *iter) - ? iter - : end(); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - iterator> - find(const K& key) { - const iterator iter = lower_bound(key); - return iter != end() && !this->operator()(key, *iter) - ? iter - : end(); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - const_iterator> - find(const K& key) const { - const const_iterator iter = lower_bound(key); - return iter != end() && !this->operator()(key, *iter) - ? iter - : end(); - } - - bool contains(const key_type& key) const { - return find(key) != end(); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - bool> - contains(const K& key) const { - return find(key) != end(); - } - - std::pair equal_range(const key_type& key) { - const base_type& comp = *this; - return std::equal_range(begin(), end(), key, comp); - } - - std::pair equal_range(const key_type& key) const { - const base_type& comp = *this; - return std::equal_range(begin(), end(), key, comp); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - std::pair> - equal_range(const K& key) { - const base_type& comp = *this; - return std::equal_range(begin(), end(), key, comp); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - std::pair> - equal_range(const K& key) const { - const base_type& comp = *this; - return std::equal_range(begin(), end(), key, comp); - } - - iterator lower_bound(const key_type& key) { - const base_type& comp = *this; - return std::lower_bound(begin(), end(), key, comp); - } - - const_iterator lower_bound(const key_type& key) const { - const base_type& comp = *this; - return std::lower_bound(begin(), end(), key, comp); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - iterator> - lower_bound(const K& key) { - const base_type& comp = *this; - return std::lower_bound(begin(), end(), key, comp); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - const_iterator> - lower_bound(const K& key) const { - const base_type& comp = *this; - return std::lower_bound(begin(), end(), key, comp); - } - - iterator upper_bound(const key_type& key) { - const base_type& comp = *this; - return std::upper_bound(begin(), end(), key, comp); - } - - const_iterator upper_bound(const key_type& key) const { - const base_type& comp = *this; - return std::upper_bound(begin(), end(), key, comp); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - iterator> - upper_bound(const K& key) { - const base_type& comp = *this; - return std::upper_bound(begin(), end(), key, comp); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - const_iterator> - upper_bound(const K& key) const { - const base_type& comp = *this; - return std::upper_bound(begin(), end(), key, comp); - } - - key_compare key_comp() const { - return *this; - } - - value_compare value_comp() const { - return value_compare(key_comp()); - } - private: - template < typename Iter > - void from_range_(Iter first, Iter last) { - assert(data_.empty()); - data_.insert(data_.end(), first, last); - std::sort(data_.begin(), data_.end(), value_comp()); - } - - template < typename Iter > - void from_range_(sorted_range_t, Iter first, Iter last) { - assert(data_.empty()); - assert(detail::is_sorted(first, last, value_comp())); - data_.insert(data_.end(), first, last); - } - private: - template < typename Iter > - void insert_range_(Iter first, Iter last) { - const auto mid_iter = data_.insert(data_.end(), first, last); - std::sort(mid_iter, data_.end(), value_comp()); - std::inplace_merge(data_.begin(), mid_iter, data_.end(), value_comp()); - } - - template < typename Iter > - void insert_range_(sorted_range_t, Iter first, Iter last) { - assert(detail::is_sorted(first, last, value_comp())); - const auto mid_iter = data_.insert(data_.end(), first, last); - std::inplace_merge(data_.begin(), mid_iter, data_.end(), value_comp()); - } - private: - container_type data_; - }; -} - -namespace flat_hpp -{ - template < typename Key - , typename Value - , typename Compare - , typename Container > - void swap( - flat_multimap& l, - flat_multimap& r) - noexcept(noexcept(l.swap(r))) - { - l.swap(r); - } - - template < typename Key - , typename Value - , typename Compare - , typename Container > - bool operator==( - const flat_multimap& l, - const flat_multimap& r) - { - return l.size() == r.size() - && std::equal(l.begin(), l.end(), r.begin()); - } - - template < typename Key - , typename Value - , typename Compare - , typename Container > - bool operator!=( - const flat_multimap& l, - const flat_multimap& r) - { - return !(l == r); - } - - template < typename Key - , typename Value - , typename Compare - , typename Container > - bool operator<( - const flat_multimap& l, - const flat_multimap& r) - { - return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); - } - - template < typename Key - , typename Value - , typename Compare - , typename Container > - bool operator>( - const flat_multimap& l, - const flat_multimap& r) - { - return r < l; - } - - template < typename Key - , typename Value - , typename Compare - , typename Container > - bool operator<=( - const flat_multimap& l, - const flat_multimap& r) - { - return !(r < l); - } - - template < typename Key - , typename Value - , typename Compare - , typename Container > - bool operator>=( - const flat_multimap& l, - const flat_multimap& r) - { - return !(l < r); - } -} diff --git a/headers/3rdparty/flat.hpp/flat_multiset.hpp b/headers/3rdparty/flat.hpp/flat_multiset.hpp deleted file mode 100644 index 54e46e1c..00000000 --- a/headers/3rdparty/flat.hpp/flat_multiset.hpp +++ /dev/null @@ -1,586 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/flat.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2019, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include "flat_fwd.hpp" - -namespace flat_hpp -{ - template < typename Key - , typename Compare - , typename Container > - class flat_multiset : private Compare { - using base_type = Compare; - public: - using key_type = Key; - using value_type = Key; - - using size_type = typename Container::size_type; - using difference_type = typename Container::difference_type; - - using key_compare = Compare; - using value_compare = Compare; - using container_type = Container; - - using reference = typename Container::reference; - using const_reference = typename Container::const_reference; - using pointer = typename Container::pointer; - using const_pointer = typename Container::const_pointer; - - using iterator = typename Container::const_iterator; - using const_iterator = typename Container::const_iterator; - using reverse_iterator = typename Container::const_reverse_iterator; - using const_reverse_iterator = typename Container::const_reverse_iterator; - public: - flat_multiset() - noexcept(std::is_nothrow_default_constructible_v - && std::is_nothrow_default_constructible_v) {} - - explicit flat_multiset(const Compare& c) - : base_type(c) {} - - template < typename Allocator > - explicit flat_multiset(const Allocator& a) - : data_(a) {} - - template < typename Allocator > - flat_multiset(const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) {} - - template < typename InputIter > - flat_multiset(InputIter first, InputIter last) { - from_range_(first, last); - } - - template < typename InputIter > - flat_multiset(sorted_range_t, InputIter first, InputIter last) { - from_range_(sorted_range, first, last); - } - - template < typename InputIter > - flat_multiset(InputIter first, InputIter last, const Compare& c) - : base_type(c) { - from_range_(first, last); - } - - template < typename InputIter > - flat_multiset(sorted_range_t, InputIter first, InputIter last, const Compare& c) - : base_type(c) { - from_range_(sorted_range, first, last); - } - - template < typename InputIter, typename Allocator > - flat_multiset(InputIter first, InputIter last, const Allocator& a) - : data_(a) { - from_range_(first, last); - } - - template < typename InputIter, typename Allocator > - flat_multiset(sorted_range_t, InputIter first, InputIter last, const Allocator& a) - : data_(a) { - from_range_(sorted_range, first, last); - } - - template < typename InputIter, typename Allocator > - flat_multiset(InputIter first, InputIter last, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(first, last); - } - - template < typename InputIter, typename Allocator > - flat_multiset(sorted_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(sorted_range, first, last); - } - - flat_multiset(std::initializer_list ilist) { - from_range_(ilist.begin(), ilist.end()); - } - - flat_multiset(sorted_range_t, std::initializer_list ilist) { - from_range_(sorted_range, ilist.begin(), ilist.end()); - } - - flat_multiset(std::initializer_list ilist, const Compare& c) - : base_type(c) { - from_range_(ilist.begin(), ilist.end()); - } - - flat_multiset(sorted_range_t, std::initializer_list ilist, const Compare& c) - : base_type(c) { - from_range_(sorted_range, ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_multiset(std::initializer_list ilist, const Allocator& a) - : data_(a) { - from_range_(ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_multiset(sorted_range_t, std::initializer_list ilist, const Allocator& a) - : data_(a) { - from_range_(sorted_range, ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_multiset(std::initializer_list ilist, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_multiset(sorted_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(sorted_range, ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_multiset(flat_multiset&& other, const Allocator& a) - : base_type(static_cast(other)) - , data_(std::move(other.data_), a) {} - - template < typename Allocator > - flat_multiset(const flat_multiset& other, const Allocator& a) - : base_type(static_cast(other)) - , data_(other.data_, a) {} - - flat_multiset(flat_multiset&& other) = default; - flat_multiset(const flat_multiset& other) = default; - - flat_multiset& operator=(flat_multiset&& other) = default; - flat_multiset& operator=(const flat_multiset& other) = default; - - flat_multiset& operator=(std::initializer_list ilist) { - flat_multiset(ilist).swap(*this); - return *this; - } - - iterator begin() - noexcept(noexcept(std::declval().begin())) { - return data_.begin(); - } - - const_iterator begin() const - noexcept(noexcept(std::declval().begin())) { - return data_.begin(); - } - - const_iterator cbegin() const - noexcept(noexcept(std::declval().cbegin())) { - return data_.cbegin(); - } - - iterator end() - noexcept(noexcept(std::declval().end())) { - return data_.end(); - } - - const_iterator end() const - noexcept(noexcept(std::declval().end())) { - return data_.end(); - } - - const_iterator cend() const - noexcept(noexcept(std::declval().cend())) { - return data_.cend(); - } - - reverse_iterator rbegin() - noexcept(noexcept(std::declval().rbegin())) { - return data_.rbegin(); - } - - const_reverse_iterator rbegin() const - noexcept(noexcept(std::declval().rbegin())) { - return data_.rbegin(); - } - - const_reverse_iterator crbegin() const - noexcept(noexcept(std::declval().crbegin())) { - return data_.crbegin(); - } - - reverse_iterator rend() - noexcept(noexcept(std::declval().rend())) { - return data_.rend(); - } - - const_reverse_iterator rend() const - noexcept(noexcept(std::declval().rend())) { - return data_.rend(); - } - - const_reverse_iterator crend() const - noexcept(noexcept(std::declval().crend())) { - return data_.crend(); - } - - bool empty() const - noexcept(noexcept(std::declval().empty())) { - return data_.empty(); - } - - size_type size() const - noexcept(noexcept(std::declval().size())) { - return data_.size(); - } - - size_type max_size() const - noexcept(noexcept(std::declval().max_size())) { - return data_.max_size(); - } - - size_type capacity() const - noexcept(noexcept(std::declval().capacity())) { - return data_.capacity(); - } - - void reserve(size_type ncapacity) { - data_.reserve(ncapacity); - } - - void shrink_to_fit() { - data_.shrink_to_fit(); - } - - iterator insert(value_type&& value) { - const iterator iter = upper_bound(value); - return data_.insert(iter, std::move(value)); - } - - iterator insert(const value_type& value) { - const iterator iter = upper_bound(value); - return data_.insert(iter, value); - } - - iterator insert(const_iterator hint, value_type&& value) { - return (hint == begin() || !this->operator()(value, *(hint - 1))) - && (hint == end() || !this->operator()(*hint, value)) - ? data_.insert(hint, std::move(value)) - : insert(std::move(value)); - } - - iterator insert(const_iterator hint, const value_type& value) { - return (hint == begin() || !this->operator()(value, *(hint - 1))) - && (hint == end() || !this->operator()(*hint, value)) - ? data_.insert(hint, value) - : insert(value); - } - - template < typename InputIter > - void insert(InputIter first, InputIter last) { - insert_range_(first, last); - } - - template < typename InputIter > - void insert(sorted_range_t, InputIter first, InputIter last) { - insert_range_(sorted_range, first, last); - } - - void insert(std::initializer_list ilist) { - insert_range_(ilist.begin(), ilist.end()); - } - - void insert(sorted_range_t, std::initializer_list ilist) { - insert_range_(sorted_range, ilist.begin(), ilist.end()); - } - - template < typename... Args > - iterator emplace(Args&&... args) { - return insert(value_type(std::forward(args)...)); - } - - template < typename... Args > - iterator emplace_hint(const_iterator hint, Args&&... args) { - return insert(hint, value_type(std::forward(args)...)); - } - - void clear() - noexcept(noexcept(std::declval().clear())) { - data_.clear(); - } - - iterator erase(const_iterator iter) { - return data_.erase(iter); - } - - iterator erase(const_iterator first, const_iterator last) { - return data_.erase(first, last); - } - - size_type erase(const key_type& key) { - const auto p = equal_range(key); - size_type r = std::distance(p.first, p.second); - erase(p.first, p.second); - return r; - } - - void swap(flat_multiset& other) - noexcept(std::is_nothrow_swappable_v - && std::is_nothrow_swappable_v) - { - using std::swap; - swap( - static_cast(*this), - static_cast(other)); - swap(data_, other.data_); - } - - size_type count(const key_type& key) const { - const auto p = equal_range(key); - return std::distance(p.first, p.second); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - size_type> - count(const K& key) const { - const auto p = equal_range(key); - return std::distance(p.first, p.second); - } - - iterator find(const key_type& key) { - const iterator iter = lower_bound(key); - return iter != end() && !this->operator()(key, *iter) - ? iter - : end(); - } - - const_iterator find(const key_type& key) const { - const const_iterator iter = lower_bound(key); - return iter != end() && !this->operator()(key, *iter) - ? iter - : end(); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - iterator> - find(const K& key) { - const iterator iter = lower_bound(key); - return iter != end() && !this->operator()(key, *iter) - ? iter - : end(); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - const_iterator> - find(const K& key) const { - const const_iterator iter = lower_bound(key); - return iter != end() && !this->operator()(key, *iter) - ? iter - : end(); - } - - bool contains(const key_type& key) const { - return find(key) != end(); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - bool> - contains(const K& key) const { - return find(key) != end(); - } - - std::pair equal_range(const key_type& key) { - return std::equal_range(begin(), end(), key, key_comp()); - } - - std::pair equal_range(const key_type& key) const { - return std::equal_range(begin(), end(), key, key_comp()); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - std::pair> - equal_range(const K& key) { - return std::equal_range(begin(), end(), key, key_comp()); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - std::pair> - equal_range(const K& key) const { - return std::equal_range(begin(), end(), key, key_comp()); - } - - iterator lower_bound(const key_type& key) { - return std::lower_bound(begin(), end(), key, key_comp()); - } - - const_iterator lower_bound(const key_type& key) const { - return std::lower_bound(begin(), end(), key, key_comp()); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - iterator> - lower_bound(const K& key) { - return std::lower_bound(begin(), end(), key, key_comp()); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - const_iterator> - lower_bound(const K& key) const { - return std::lower_bound(begin(), end(), key, key_comp()); - } - - iterator upper_bound(const key_type& key) { - return std::upper_bound(begin(), end(), key, key_comp()); - } - - const_iterator upper_bound(const key_type& key) const { - return std::upper_bound(begin(), end(), key, key_comp()); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - iterator> - upper_bound(const K& key) { - return std::upper_bound(begin(), end(), key, key_comp()); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - const_iterator> - upper_bound(const K& key) const { - return std::upper_bound(begin(), end(), key, key_comp()); - } - - key_compare key_comp() const { - return *this; - } - - value_compare value_comp() const { - return value_compare(key_comp()); - } - private: - template < typename Iter > - void from_range_(Iter first, Iter last) { - assert(data_.empty()); - data_.insert(data_.end(), first, last); - std::sort(data_.begin(), data_.end(), key_comp()); - } - - template < typename Iter > - void from_range_(sorted_range_t, Iter first, Iter last) { - assert(data_.empty()); - assert(detail::is_sorted(first, last, key_comp())); - data_.insert(data_.end(), first, last); - } - private: - template < typename Iter > - void insert_range_(Iter first, Iter last) { - const auto mid_iter = data_.insert(data_.end(), first, last); - std::sort(mid_iter, data_.end(), key_comp()); - std::inplace_merge(data_.begin(), mid_iter, data_.end(), key_comp()); - } - - template < typename Iter > - void insert_range_(sorted_range_t, Iter first, Iter last) { - assert(detail::is_sorted(first, last, key_comp())); - const auto mid_iter = data_.insert(data_.end(), first, last); - std::inplace_merge(data_.begin(), mid_iter, data_.end(), key_comp()); - } - private: - container_type data_; - }; -} - -namespace flat_hpp -{ - template < typename Key - , typename Compare - , typename Container > - void swap( - flat_multiset& l, - flat_multiset& r) - noexcept(noexcept(l.swap(r))) - { - l.swap(r); - } - - template < typename Key - , typename Compare - , typename Container > - bool operator==( - const flat_multiset& l, - const flat_multiset& r) - { - return l.size() == r.size() - && std::equal(l.begin(), l.end(), r.begin()); - } - - template < typename Key - , typename Compare - , typename Container > - bool operator!=( - const flat_multiset& l, - const flat_multiset& r) - { - return !(l == r); - } - - template < typename Key - , typename Compare - , typename Container > - bool operator<( - const flat_multiset& l, - const flat_multiset& r) - { - return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); - } - - template < typename Key - , typename Compare - , typename Container > - bool operator>( - const flat_multiset& l, - const flat_multiset& r) - { - return r < l; - } - - template < typename Key - , typename Compare - , typename Container > - bool operator<=( - const flat_multiset& l, - const flat_multiset& r) - { - return !(r < l); - } - - template < typename Key - , typename Compare - , typename Container > - bool operator>=( - const flat_multiset& l, - const flat_multiset& r) - { - return !(l < r); - } -} diff --git a/headers/3rdparty/flat.hpp/flat_set.hpp b/headers/3rdparty/flat.hpp/flat_set.hpp deleted file mode 100644 index 23244f1b..00000000 --- a/headers/3rdparty/flat.hpp/flat_set.hpp +++ /dev/null @@ -1,659 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/flat.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2019, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include "flat_fwd.hpp" - -namespace flat_hpp -{ - template < typename Key - , typename Compare - , typename Container > - class flat_set : private Compare { - using base_type = Compare; - public: - using key_type = Key; - using value_type = Key; - - using size_type = typename Container::size_type; - using difference_type = typename Container::difference_type; - - using key_compare = Compare; - using value_compare = Compare; - using container_type = Container; - - using reference = typename Container::reference; - using const_reference = typename Container::const_reference; - using pointer = typename Container::pointer; - using const_pointer = typename Container::const_pointer; - - using iterator = typename Container::const_iterator; - using const_iterator = typename Container::const_iterator; - using reverse_iterator = typename Container::const_reverse_iterator; - using const_reverse_iterator = typename Container::const_reverse_iterator; - public: - flat_set() - noexcept(std::is_nothrow_default_constructible_v - && std::is_nothrow_default_constructible_v) {} - - explicit flat_set(const Compare& c) - : base_type(c) {} - - template < typename Allocator > - explicit flat_set(const Allocator& a) - : data_(a) {} - - template < typename Allocator > - flat_set(const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) {} - - template < typename InputIter > - flat_set(InputIter first, InputIter last) { - from_range_(first, last); - } - - template < typename InputIter > - flat_set(sorted_range_t, InputIter first, InputIter last) { - from_range_(sorted_range, first, last); - } - - template < typename InputIter > - flat_set(sorted_unique_range_t, InputIter first, InputIter last) { - from_range_(sorted_unique_range, first, last); - } - - template < typename InputIter > - flat_set(InputIter first, InputIter last, const Compare& c) - : base_type(c) { - from_range_(first, last); - } - - template < typename InputIter > - flat_set(sorted_range_t, InputIter first, InputIter last, const Compare& c) - : base_type(c) { - from_range_(sorted_range, first, last); - } - - template < typename InputIter > - flat_set(sorted_unique_range_t, InputIter first, InputIter last, const Compare& c) - : base_type(c) { - from_range_(sorted_unique_range, first, last); - } - - template < typename InputIter, typename Allocator > - flat_set(InputIter first, InputIter last, const Allocator& a) - : data_(a) { - from_range_(first, last); - } - - template < typename InputIter, typename Allocator > - flat_set(sorted_range_t, InputIter first, InputIter last, const Allocator& a) - : data_(a) { - from_range_(sorted_range, first, last); - } - - template < typename InputIter, typename Allocator > - flat_set(sorted_unique_range_t, InputIter first, InputIter last, const Allocator& a) - : data_(a) { - from_range_(sorted_unique_range, first, last); - } - - template < typename InputIter, typename Allocator > - flat_set(InputIter first, InputIter last, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(first, last); - } - - template < typename InputIter, typename Allocator > - flat_set(sorted_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(sorted_range, first, last); - } - - template < typename InputIter, typename Allocator > - flat_set(sorted_unique_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(sorted_unique_range, first, last); - } - - flat_set(std::initializer_list ilist) { - from_range_(ilist.begin(), ilist.end()); - } - - flat_set(sorted_range_t, std::initializer_list ilist) { - from_range_(sorted_range, ilist.begin(), ilist.end()); - } - - flat_set(sorted_unique_range_t, std::initializer_list ilist) { - from_range_(sorted_unique_range, ilist.begin(), ilist.end()); - } - - flat_set(std::initializer_list ilist, const Compare& c) - : base_type(c) { - from_range_(ilist.begin(), ilist.end()); - } - - flat_set(sorted_range_t, std::initializer_list ilist, const Compare& c) - : base_type(c) { - from_range_(sorted_range, ilist.begin(), ilist.end()); - } - - flat_set(sorted_unique_range_t, std::initializer_list ilist, const Compare& c) - : base_type(c) { - from_range_(sorted_unique_range, ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_set(std::initializer_list ilist, const Allocator& a) - : data_(a) { - from_range_(ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_set(sorted_range_t, std::initializer_list ilist, const Allocator& a) - : data_(a) { - from_range_(sorted_range, ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_set(sorted_unique_range_t, std::initializer_list ilist, const Allocator& a) - : data_(a) { - from_range_(sorted_unique_range, ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_set(std::initializer_list ilist, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_set(sorted_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(sorted_range, ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_set(sorted_unique_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a) - : base_type(c) - , data_(a) { - from_range_(sorted_unique_range, ilist.begin(), ilist.end()); - } - - template < typename Allocator > - flat_set(flat_set&& other, const Allocator& a) - : base_type(static_cast(other)) - , data_(std::move(other.data_), a) {} - - template < typename Allocator > - flat_set(const flat_set& other, const Allocator& a) - : base_type(static_cast(other)) - , data_(other.data_, a) {} - - flat_set(flat_set&& other) = default; - flat_set(const flat_set& other) = default; - - flat_set& operator=(flat_set&& other) = default; - flat_set& operator=(const flat_set& other) = default; - - flat_set& operator=(std::initializer_list ilist) { - flat_set(ilist).swap(*this); - return *this; - } - - iterator begin() - noexcept(noexcept(std::declval().begin())) { - return data_.begin(); - } - - const_iterator begin() const - noexcept(noexcept(std::declval().begin())) { - return data_.begin(); - } - - const_iterator cbegin() const - noexcept(noexcept(std::declval().cbegin())) { - return data_.cbegin(); - } - - iterator end() - noexcept(noexcept(std::declval().end())) { - return data_.end(); - } - - const_iterator end() const - noexcept(noexcept(std::declval().end())) { - return data_.end(); - } - - const_iterator cend() const - noexcept(noexcept(std::declval().cend())) { - return data_.cend(); - } - - reverse_iterator rbegin() - noexcept(noexcept(std::declval().rbegin())) { - return data_.rbegin(); - } - - const_reverse_iterator rbegin() const - noexcept(noexcept(std::declval().rbegin())) { - return data_.rbegin(); - } - - const_reverse_iterator crbegin() const - noexcept(noexcept(std::declval().crbegin())) { - return data_.crbegin(); - } - - reverse_iterator rend() - noexcept(noexcept(std::declval().rend())) { - return data_.rend(); - } - - const_reverse_iterator rend() const - noexcept(noexcept(std::declval().rend())) { - return data_.rend(); - } - - const_reverse_iterator crend() const - noexcept(noexcept(std::declval().crend())) { - return data_.crend(); - } - - bool empty() const - noexcept(noexcept(std::declval().empty())) { - return data_.empty(); - } - - size_type size() const - noexcept(noexcept(std::declval().size())) { - return data_.size(); - } - - size_type max_size() const - noexcept(noexcept(std::declval().max_size())) { - return data_.max_size(); - } - - size_type capacity() const - noexcept(noexcept(std::declval().capacity())) { - return data_.capacity(); - } - - void reserve(size_type ncapacity) { - data_.reserve(ncapacity); - } - - void shrink_to_fit() { - data_.shrink_to_fit(); - } - - std::pair insert(value_type&& value) { - const iterator iter = lower_bound(value); - return iter == end() || this->operator()(value, *iter) - ? std::make_pair(data_.insert(iter, std::move(value)), true) - : std::make_pair(iter, false); - } - - std::pair insert(const value_type& value) { - const iterator iter = lower_bound(value); - return iter == end() || this->operator()(value, *iter) - ? std::make_pair(data_.insert(iter, value), true) - : std::make_pair(iter, false); - } - - iterator insert(const_iterator hint, value_type&& value) { - return (hint == begin() || this->operator()(*(hint - 1), value)) - && (hint == end() || this->operator()(value, *hint)) - ? data_.insert(hint, std::move(value)) - : insert(std::move(value)).first; - } - - iterator insert(const_iterator hint, const value_type& value) { - return (hint == begin() || this->operator()(*(hint - 1), value)) - && (hint == end() || this->operator()(value, *hint)) - ? data_.insert(hint, value) - : insert(value).first; - } - - template < typename InputIter > - void insert(InputIter first, InputIter last) { - insert_range_(first, last); - } - - template < typename InputIter > - void insert(sorted_range_t, InputIter first, InputIter last) { - insert_range_(sorted_range, first, last); - } - - void insert(std::initializer_list ilist) { - insert_range_(ilist.begin(), ilist.end()); - } - - void insert(sorted_range_t, std::initializer_list ilist) { - insert_range_(sorted_range, ilist.begin(), ilist.end()); - } - - template < typename... Args > - std::pair emplace(Args&&... args) { - return insert(value_type(std::forward(args)...)); - } - - template < typename... Args > - iterator emplace_hint(const_iterator hint, Args&&... args) { - return insert(hint, value_type(std::forward(args)...)); - } - - void clear() - noexcept(noexcept(std::declval().clear())) { - data_.clear(); - } - - iterator erase(const_iterator iter) { - return data_.erase(iter); - } - - iterator erase(const_iterator first, const_iterator last) { - return data_.erase(first, last); - } - - size_type erase(const key_type& key) { - const const_iterator iter = find(key); - return iter != end() - ? (erase(iter), 1) - : 0; - } - - void swap(flat_set& other) - noexcept(std::is_nothrow_swappable_v - && std::is_nothrow_swappable_v) - { - using std::swap; - swap( - static_cast(*this), - static_cast(other)); - swap(data_, other.data_); - } - - size_type count(const key_type& key) const { - const const_iterator iter = find(key); - return iter != end() ? 1 : 0; - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - size_type> - count(const K& key) const { - const const_iterator iter = find(key); - return iter != end() ? 1 : 0; - } - - iterator find(const key_type& key) { - const iterator iter = lower_bound(key); - return iter != end() && !this->operator()(key, *iter) - ? iter - : end(); - } - - const_iterator find(const key_type& key) const { - const const_iterator iter = lower_bound(key); - return iter != end() && !this->operator()(key, *iter) - ? iter - : end(); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - iterator> - find(const K& key) { - const iterator iter = lower_bound(key); - return iter != end() && !this->operator()(key, *iter) - ? iter - : end(); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - const_iterator> - find(const K& key) const { - const const_iterator iter = lower_bound(key); - return iter != end() && !this->operator()(key, *iter) - ? iter - : end(); - } - - bool contains(const key_type& key) const { - return find(key) != end(); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - bool> - contains(const K& key) const { - return find(key) != end(); - } - - std::pair equal_range(const key_type& key) { - return std::equal_range(begin(), end(), key, key_comp()); - } - - std::pair equal_range(const key_type& key) const { - return std::equal_range(begin(), end(), key, key_comp()); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - std::pair> - equal_range(const K& key) { - return std::equal_range(begin(), end(), key, key_comp()); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - std::pair> - equal_range(const K& key) const { - return std::equal_range(begin(), end(), key, key_comp()); - } - - iterator lower_bound(const key_type& key) { - return std::lower_bound(begin(), end(), key, key_comp()); - } - - const_iterator lower_bound(const key_type& key) const { - return std::lower_bound(begin(), end(), key, key_comp()); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - iterator> - lower_bound(const K& key) { - return std::lower_bound(begin(), end(), key, key_comp()); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - const_iterator> - lower_bound(const K& key) const { - return std::lower_bound(begin(), end(), key, key_comp()); - } - - iterator upper_bound(const key_type& key) { - return std::upper_bound(begin(), end(), key, key_comp()); - } - - const_iterator upper_bound(const key_type& key) const { - return std::upper_bound(begin(), end(), key, key_comp()); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - iterator> - upper_bound(const K& key) { - return std::upper_bound(begin(), end(), key, key_comp()); - } - - template < typename K > - std::enable_if_t< - detail::is_transparent_v, - const_iterator> - upper_bound(const K& key) const { - return std::upper_bound(begin(), end(), key, key_comp()); - } - - key_compare key_comp() const { - return *this; - } - - value_compare value_comp() const { - return value_compare(key_comp()); - } - private: - template < typename Iter > - void from_range_(Iter first, Iter last) { - assert(data_.empty()); - data_.insert(data_.end(), first, last); - std::sort(data_.begin(), data_.end(), key_comp()); - data_.erase( - std::unique(data_.begin(), data_.end(), - detail::eq_compare(key_comp())), - data_.end()); - } - - template < typename Iter > - void from_range_(sorted_range_t, Iter first, Iter last) { - assert(data_.empty()); - assert(detail::is_sorted(first, last, key_comp())); - data_.insert(data_.end(), first, last); - data_.erase( - std::unique(data_.begin(), data_.end(), - detail::eq_compare(key_comp())), - data_.end()); - } - - template < typename Iter > - void from_range_(sorted_unique_range_t, Iter first, Iter last) { - assert(data_.empty()); - assert(detail::is_sorted_unique(first, last, key_comp())); - data_.insert(data_.end(), first, last); - } - private: - template < typename Iter > - void insert_range_(Iter first, Iter last) { - const auto mid_iter = data_.insert(data_.end(), first, last); - std::sort(mid_iter, data_.end(), key_comp()); - std::inplace_merge(data_.begin(), mid_iter, data_.end(), key_comp()); - data_.erase( - std::unique(data_.begin(), data_.end(), - detail::eq_compare(key_comp())), - data_.end()); - } - - template < typename Iter > - void insert_range_(sorted_range_t, Iter first, Iter last) { - assert(detail::is_sorted(first, last, key_comp())); - const auto mid_iter = data_.insert(data_.end(), first, last); - std::inplace_merge(data_.begin(), mid_iter, data_.end(), key_comp()); - data_.erase( - std::unique(data_.begin(), data_.end(), - detail::eq_compare(key_comp())), - data_.end()); - } - private: - container_type data_; - }; -} - -namespace flat_hpp -{ - template < typename Key - , typename Compare - , typename Container > - void swap( - flat_set& l, - flat_set& r) - noexcept(noexcept(l.swap(r))) - { - l.swap(r); - } - - template < typename Key - , typename Compare - , typename Container > - bool operator==( - const flat_set& l, - const flat_set& r) - { - return l.size() == r.size() - && std::equal(l.begin(), l.end(), r.begin()); - } - - template < typename Key - , typename Compare - , typename Container > - bool operator!=( - const flat_set& l, - const flat_set& r) - { - return !(l == r); - } - - template < typename Key - , typename Compare - , typename Container > - bool operator<( - const flat_set& l, - const flat_set& r) - { - return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); - } - - template < typename Key - , typename Compare - , typename Container > - bool operator>( - const flat_set& l, - const flat_set& r) - { - return r < l; - } - - template < typename Key - , typename Compare - , typename Container > - bool operator<=( - const flat_set& l, - const flat_set& r) - { - return !(r < l); - } - - template < typename Key - , typename Compare - , typename Container > - bool operator>=( - const flat_set& l, - const flat_set& r) - { - return !(l < r); - } -} diff --git a/headers/3rdparty/promise.hpp/invoke.hpp b/headers/3rdparty/promise.hpp/invoke.hpp deleted file mode 100644 index b75657fd..00000000 --- a/headers/3rdparty/promise.hpp/invoke.hpp +++ /dev/null @@ -1,248 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/invoke.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include -#include -#include -#include - -#define INVOKE_HPP_NOEXCEPT_RETURN(...) \ - noexcept(noexcept(__VA_ARGS__)) { return __VA_ARGS__; } - -#define INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN(...) \ - noexcept(noexcept(__VA_ARGS__)) -> decltype (__VA_ARGS__) { return __VA_ARGS__; } - -// -// void_t -// - -namespace invoke_hpp -{ - namespace impl - { - template < typename... Args > - struct make_void { - using type = void; - }; - } - - template < typename... Args > - using void_t = typename impl::make_void::type; -} - -// -// is_reference_wrapper -// - -namespace invoke_hpp -{ - namespace impl - { - template < typename T > - struct is_reference_wrapper_impl - : std::false_type {}; - - template < typename U > - struct is_reference_wrapper_impl> - : std::true_type {}; - } - - template < typename T > - struct is_reference_wrapper - : impl::is_reference_wrapper_impl> {}; -} - -// -// invoke -// - -namespace invoke_hpp -{ - namespace impl - { - // - // invoke_member_object_impl - // - - template - < - typename Base, typename F, typename Derived, - typename std::enable_if_t>::value, int> = 0 - > - constexpr auto invoke_member_object_impl(F Base::* f, Derived&& ref) - INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( - std::forward(ref).*f) - - template - < - typename Base, typename F, typename RefWrap, - typename std::enable_if_t>::value, int> = 0 - > - constexpr auto invoke_member_object_impl(F Base::* f, RefWrap&& ref) - INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( - ref.get().*f) - - template - < - typename Base, typename F, typename Pointer, - typename std::enable_if_t< - !std::is_base_of>::value && - !is_reference_wrapper>::value - , int> = 0 - > - constexpr auto invoke_member_object_impl(F Base::* f, Pointer&& ptr) - INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( - (*std::forward(ptr)).*f) - - // - // invoke_member_function_impl - // - - template - < - typename Base, typename F, typename Derived, typename... Args, - typename std::enable_if_t>::value, int> = 0 - > - constexpr auto invoke_member_function_impl(F Base::* f, Derived&& ref, Args&&... args) - INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( - (std::forward(ref).*f)(std::forward(args)...)) - - template - < - typename Base, typename F, typename RefWrap, typename... Args, - typename std::enable_if_t>::value, int> = 0 - > - constexpr auto invoke_member_function_impl(F Base::* f, RefWrap&& ref, Args&&... args) - INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( - (ref.get().*f)(std::forward(args)...)) - - template - < - typename Base, typename F, typename Pointer, typename... Args, - typename std::enable_if_t< - !std::is_base_of>::value && - !is_reference_wrapper>::value - , int> = 0 - > - constexpr auto invoke_member_function_impl(F Base::* f, Pointer&& ptr, Args&&... args) - INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( - ((*std::forward(ptr)).*f)(std::forward(args)...)) - } - - template - < - typename F, typename... Args, - typename std::enable_if_t>::value, int> = 0 - > - constexpr auto invoke(F&& f, Args&&... args) - INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( - std::forward(f)(std::forward(args)...)) - - template - < - typename F, typename T, - typename std::enable_if_t>::value, int> = 0 - > - constexpr auto invoke(F&& f, T&& t) - INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( - impl::invoke_member_object_impl(std::forward(f), std::forward(t))) - - template - < - typename F, typename... Args, - typename std::enable_if_t>::value, int> = 0 - > - constexpr auto invoke(F&& f, Args&&... args) - INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN( - impl::invoke_member_function_impl(std::forward(f), std::forward(args)...)) -} - -// -// invoke_result -// - -namespace invoke_hpp -{ - namespace impl - { - struct invoke_result_impl_tag {}; - - template < typename Void, typename F, typename... Args > - struct invoke_result_impl {}; - - template < typename F, typename... Args > - struct invoke_result_impl(), std::declval()...))>, F, Args...> { - using type = decltype(invoke_hpp::invoke(std::declval(), std::declval()...)); - }; - } - - template < typename F, typename... Args > - struct invoke_result - : impl::invoke_result_impl {}; - - template < typename F, typename... Args > - using invoke_result_t = typename invoke_result::type; -} - -// -// is_invocable -// - -namespace invoke_hpp -{ - namespace impl - { - struct is_invocable_r_impl_tag {}; - - template < typename Void, typename R, typename F, typename... Args > - struct is_invocable_r_impl - : std::false_type {}; - - template < typename R, typename F, typename... Args > - struct is_invocable_r_impl>, R, F, Args...> - : std::conditional_t< - std::is_void::value, - std::true_type, - std::is_convertible, R>> {}; - } - - template < typename R, typename F, typename... Args > - struct is_invocable_r - : impl::is_invocable_r_impl {}; - - template < typename F, typename... Args > - using is_invocable = is_invocable_r; -} - -// -// apply -// - -namespace invoke_hpp -{ - namespace impl - { - template < typename F, typename Tuple, std::size_t... I > - constexpr decltype(auto) apply_impl(F&& f, Tuple&& args, std::index_sequence) - INVOKE_HPP_NOEXCEPT_RETURN( - invoke_hpp::invoke( - std::forward(f), - std::get(std::forward(args))...)) - } - - template < typename F, typename Tuple > - constexpr decltype(auto) apply(F&& f, Tuple&& args) - INVOKE_HPP_NOEXCEPT_RETURN( - impl::apply_impl( - std::forward(f), - std::forward(args), - std::make_index_sequence>::value>())) -} - -#undef INVOKE_HPP_NOEXCEPT_RETURN -#undef INVOKE_HPP_NOEXCEPT_DECLTYPE_RETURN diff --git a/headers/3rdparty/promise.hpp/jobber.hpp b/headers/3rdparty/promise.hpp/jobber.hpp deleted file mode 100644 index 958f8504..00000000 --- a/headers/3rdparty/promise.hpp/jobber.hpp +++ /dev/null @@ -1,427 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/promise.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "promise.hpp" - -namespace jobber_hpp -{ - using namespace promise_hpp; - - enum class jobber_priority { - lowest, - below_normal, - normal, - above_normal, - highest - }; - - enum class jobber_wait_status { - no_timeout, - cancelled, - timeout - }; - - class jobber_cancelled_exception : public std::runtime_error { - public: - jobber_cancelled_exception() - : std::runtime_error("jobber has stopped working") {} - }; - - class jobber final : private detail::noncopyable { - public: - explicit jobber(std::size_t threads); - ~jobber() noexcept; - - using active_wait_result_t = std::pair< - jobber_wait_status, - std::size_t>; - - template < typename F, typename... Args > - using async_invoke_result_t = invoke_hpp::invoke_result_t< - std::decay_t, - std::decay_t...>; - - template < typename F, typename... Args - , typename R = async_invoke_result_t > - promise async(F&& f, Args&&... args); - - template < typename F, typename... Args - , typename R = async_invoke_result_t > - promise async(jobber_priority priority, F&& f, Args&&... args); - - void pause() noexcept; - void resume() noexcept; - bool is_paused() const noexcept; - - jobber_wait_status wait_all() const noexcept; - active_wait_result_t active_wait_all() noexcept; - active_wait_result_t active_wait_one() noexcept; - - template < typename Rep, typename Period > - jobber_wait_status wait_all_for( - const std::chrono::duration& timeout_duration) const; - - template < typename Clock, typename Duration > - jobber_wait_status wait_all_until( - const std::chrono::time_point& timeout_time) const; - - template < typename Rep, typename Period > - active_wait_result_t active_wait_all_for( - const std::chrono::duration& timeout_duration); - - template < typename Clock, typename Duration > - active_wait_result_t active_wait_all_until( - const std::chrono::time_point& timeout_time); - private: - class task; - using task_ptr = std::unique_ptr; - template < typename R, typename F, typename... Args > - class concrete_task; - private: - void push_task_(jobber_priority priority, task_ptr task); - task_ptr pop_task_() noexcept; - void shutdown_() noexcept; - void worker_main_() noexcept; - void process_task_(std::unique_lock lock) noexcept; - private: - std::vector threads_; - std::vector> tasks_; - std::atomic paused_{false}; - std::atomic cancelled_{false}; - std::atomic active_task_count_{0}; - mutable std::mutex tasks_mutex_; - mutable std::condition_variable cond_var_; - }; - - class jobber::task : private noncopyable { - public: - virtual ~task() noexcept = default; - virtual void run() noexcept = 0; - virtual void cancel() noexcept = 0; - }; - - template < typename R, typename F, typename... Args > - class jobber::concrete_task : public task { - F f_; - std::tuple args_; - promise promise_; - public: - template < typename U > - concrete_task(U&& u, std::tuple&& args); - void run() noexcept final; - void cancel() noexcept final; - promise future() noexcept; - }; - - template < typename F, typename... Args > - class jobber::concrete_task : public task { - F f_; - std::tuple args_; - promise promise_; - public: - template < typename U > - concrete_task(U&& u, std::tuple&& args); - void run() noexcept final; - void cancel() noexcept final; - promise future() noexcept; - }; -} - -namespace jobber_hpp -{ - inline jobber::jobber(std::size_t threads) { - try { - threads_.resize(threads); - for ( std::thread& thread : threads_ ) { - thread = std::thread(&jobber::worker_main_, this); - } - } catch (...) { - shutdown_(); - throw; - } - } - - inline jobber::~jobber() noexcept { - shutdown_(); - } - - template < typename F, typename... Args, typename R > - promise jobber::async(F&& f, Args&&... args) { - return async( - jobber_priority::normal, - std::forward(f), - std::forward(args)...); - } - - template < typename F, typename... Args, typename R > - promise jobber::async(jobber_priority priority, F&& f, Args&&... args) { - using task_t = concrete_task< - R, - std::decay_t, - std::decay_t...>; - std::unique_ptr task = std::make_unique( - std::forward(f), - std::make_tuple(std::forward(args)...)); - promise future = task->future(); - std::lock_guard guard(tasks_mutex_); - push_task_(priority, std::move(task)); - return future; - } - - inline void jobber::pause() noexcept { - std::lock_guard guard(tasks_mutex_); - paused_.store(true); - cond_var_.notify_all(); - } - - inline void jobber::resume() noexcept { - std::lock_guard guard(tasks_mutex_); - paused_.store(false); - cond_var_.notify_all(); - } - - inline bool jobber::is_paused() const noexcept { - return paused_; - } - - inline jobber_wait_status jobber::wait_all() const noexcept { - std::unique_lock lock(tasks_mutex_); - cond_var_.wait(lock, [this](){ - return cancelled_ || !active_task_count_; - }); - return cancelled_ - ? jobber_wait_status::cancelled - : jobber_wait_status::no_timeout; - } - - inline jobber::active_wait_result_t jobber::active_wait_all() noexcept { - std::size_t processed_tasks = 0; - while ( !cancelled_ && active_task_count_ ) { - std::unique_lock lock(tasks_mutex_); - cond_var_.wait(lock, [this](){ - return cancelled_ || !active_task_count_ || !tasks_.empty(); - }); - if ( !tasks_.empty() ) { - process_task_(std::move(lock)); - ++processed_tasks; - } - } - return std::make_pair( - cancelled_ - ? jobber_wait_status::cancelled - : jobber_wait_status::no_timeout, - processed_tasks); - } - - inline jobber::active_wait_result_t jobber::active_wait_one() noexcept { - std::unique_lock lock(tasks_mutex_); - if ( cancelled_ ) { - return std::make_pair(jobber_wait_status::cancelled, 0u); - } - if ( tasks_.empty() ) { - return std::make_pair(jobber_wait_status::no_timeout, 0u); - } - process_task_(std::move(lock)); - return std::make_pair(jobber_wait_status::no_timeout, 1u); - } - - template < typename Rep, typename Period > - jobber_wait_status jobber::wait_all_for( - const std::chrono::duration& timeout_duration) const - { - return wait_all_until( - std::chrono::steady_clock::now() + timeout_duration); - } - - template < typename Clock, typename Duration > - jobber_wait_status jobber::wait_all_until( - const std::chrono::time_point& timeout_time) const - { - std::unique_lock lock(tasks_mutex_); - return cond_var_.wait_until(lock, timeout_time, [this](){ - return cancelled_ || !active_task_count_; - }) ? jobber_wait_status::no_timeout - : jobber_wait_status::timeout; - } - - template < typename Rep, typename Period > - jobber::active_wait_result_t jobber::active_wait_all_for( - const std::chrono::duration& timeout_duration) - { - return active_wait_all_until( - std::chrono::steady_clock::now() + timeout_duration); - } - - template < typename Clock, typename Duration > - jobber::active_wait_result_t jobber::active_wait_all_until( - const std::chrono::time_point& timeout_time) - { - std::size_t processed_tasks = 0; - while ( !cancelled_ && active_task_count_ ) { - if ( !(Clock::now() < timeout_time) ) { - return std::make_pair( - jobber_wait_status::timeout, - processed_tasks); - } - std::unique_lock lock(tasks_mutex_); - cond_var_.wait_until(lock, timeout_time, [this](){ - return cancelled_ || !active_task_count_ || !tasks_.empty(); - }); - if ( !tasks_.empty() ) { - process_task_(std::move(lock)); - ++processed_tasks; - } - } - return std::make_pair( - cancelled_ - ? jobber_wait_status::cancelled - : jobber_wait_status::no_timeout, - processed_tasks); - } - - inline void jobber::push_task_(jobber_priority priority, task_ptr task) { - tasks_.emplace_back(priority, std::move(task)); - std::push_heap(tasks_.begin(), tasks_.end()); - ++active_task_count_; - cond_var_.notify_one(); - } - - inline jobber::task_ptr jobber::pop_task_() noexcept { - if ( !tasks_.empty() ) { - std::pop_heap(tasks_.begin(), tasks_.end()); - task_ptr task = std::move(tasks_.back().second); - tasks_.pop_back(); - return task; - } - return nullptr; - } - - inline void jobber::shutdown_() noexcept { - { - std::lock_guard guard(tasks_mutex_); - while ( !tasks_.empty() ) { - task_ptr task = pop_task_(); - if ( task ) { - task->cancel(); - --active_task_count_; - } - } - cancelled_.store(true); - cond_var_.notify_all(); - } - for ( std::thread& thread : threads_ ) { - if ( thread.joinable() ) { - thread.join(); - } - } - } - - inline void jobber::worker_main_() noexcept { - while ( true ) { - std::unique_lock lock(tasks_mutex_); - cond_var_.wait(lock, [this](){ - return cancelled_ || (!paused_ && !tasks_.empty()); - }); - if ( cancelled_ ) { - break; - } - process_task_(std::move(lock)); - } - } - - inline void jobber::process_task_(std::unique_lock lock) noexcept { - assert(lock.owns_lock()); - task_ptr task = pop_task_(); - if ( task ) { - lock.unlock(); - task->run(); - lock.lock(); - --active_task_count_; - cond_var_.notify_all(); - } - } -} - -namespace jobber_hpp -{ - // - // concrete_task - // - - template < typename R, typename F, typename... Args > - template < typename U > - jobber::concrete_task::concrete_task(U&& u, std::tuple&& args) - : f_(std::forward(u)) - , args_(std::move(args)) {} - - template < typename R, typename F, typename... Args > - void jobber::concrete_task::run() noexcept { - try { - R value = invoke_hpp::apply(std::move(f_), std::move(args_)); - promise_.resolve(std::move(value)); - } catch (...) { - promise_.reject(std::current_exception()); - } - } - - template < typename R, typename F, typename... Args > - void jobber::concrete_task::cancel() noexcept { - promise_.reject(jobber_cancelled_exception()); - } - - template < typename R, typename F, typename... Args > - promise jobber::concrete_task::future() noexcept { - return promise_; - } - - // - // concrete_task - // - - template < typename F, typename... Args > - template < typename U > - jobber::concrete_task::concrete_task(U&& u, std::tuple&& args) - : f_(std::forward(u)) - , args_(std::move(args)) {} - - template < typename F, typename... Args > - void jobber::concrete_task::run() noexcept { - try { - invoke_hpp::apply(std::move(f_), std::move(args_)); - promise_.resolve(); - } catch (...) { - promise_.reject(std::current_exception()); - } - } - - template < typename F, typename... Args > - void jobber::concrete_task::cancel() noexcept { - promise_.reject(jobber_cancelled_exception()); - } - - template < typename F, typename... Args > - promise jobber::concrete_task::future() noexcept { - return promise_; - } -} diff --git a/headers/3rdparty/promise.hpp/promise.hpp b/headers/3rdparty/promise.hpp/promise.hpp deleted file mode 100644 index abd65023..00000000 --- a/headers/3rdparty/promise.hpp/promise.hpp +++ /dev/null @@ -1,1306 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/promise.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "invoke.hpp" - -namespace promise_hpp -{ - // - // forward declaration - // - - template < typename T = void > - class promise; - - // - // is_promise - // - - namespace impl - { - template < typename T > - struct is_promise_impl - : std::false_type {}; - - template < typename R > - struct is_promise_impl> - : std::true_type {}; - } - - template < typename T > - struct is_promise - : impl::is_promise_impl> {}; - - // - // is_promise_r - // - - namespace impl - { - template < typename R, typename T > - struct is_promise_r_impl - : std::false_type {}; - - template < typename R, typename PR > - struct is_promise_r_impl> - : std::is_convertible {}; - } - - template < typename R, typename T > - struct is_promise_r - : impl::is_promise_r_impl> {}; - - // - // detail - // - - namespace detail - { - class noncopyable { - public: - noncopyable(const noncopyable&) = delete; - noncopyable& operator=(const noncopyable&) = delete; - protected: - noncopyable() = default; - ~noncopyable() = default; - }; - - template < typename T > - class storage final : private noncopyable { - public: - storage() = default; - - ~storage() - noexcept(std::is_nothrow_destructible::value) - { - if ( initialized_ ) { - ptr_()->~T(); - } - } - - template < typename U > - void set(U&& value) - noexcept(std::is_nothrow_constructible::value) - { - assert(!initialized_); - ::new(ptr_()) T(std::forward(value)); - initialized_ = true; - } - - T get() - noexcept(std::is_nothrow_move_constructible::value) - { - assert(initialized_); - return std::move(*ptr_()); - } - - const T& value() const noexcept { - assert(initialized_); - return *ptr_(); - } - private: - T* ptr_() noexcept { - return reinterpret_cast(&data_); - } - - const T* ptr_() const noexcept { - return reinterpret_cast(&data_); - } - private: - std::aligned_storage_t data_; - bool initialized_ = false; - }; - } - - // - // promise_wait_status - // - - enum class promise_wait_status { - no_timeout, - timeout - }; - - // - // promise - // - - template < typename T > - class promise final { - public: - using value_type = T; - public: - promise() - : state_(std::make_shared()) {} - - promise(const promise&) noexcept = default; - promise& operator=(const promise&) noexcept = default; - - void swap(promise& other) noexcept { - state_.swap(other.state_); - } - - std::size_t hash() const noexcept { - return std::hash()(state_.get()); - } - - friend bool operator<(const promise& l, const promise& r) noexcept { - return l.state_ < r.state_; - } - - friend bool operator==(const promise& l, const promise& r) noexcept { - return l.state_ == r.state_; - } - - friend bool operator!=(const promise& l, const promise& r) noexcept { - return l.state_ != r.state_; - } - - template < typename ResolveF - , typename ResolveFR = invoke_hpp::invoke_result_t > - std::enable_if_t< - is_promise::value && std::is_void::value, - promise> - then(ResolveF&& on_resolve) { - promise next; - - then([ - n = next, - f = std::forward(on_resolve) - ](auto&& v) mutable { - auto np = invoke_hpp::invoke( - std::forward(f), - std::forward(v)); - std::move(np).then([n]() mutable { - n.resolve(); - }).except([n](std::exception_ptr e) mutable { - n.reject(e); - }); - }).except([n = next](std::exception_ptr e) mutable { - n.reject(e); - }); - - return next; - } - - template < typename ResolveF - , typename ResolveFR = invoke_hpp::invoke_result_t > - std::enable_if_t< - is_promise::value && !std::is_void::value, - promise> - then(ResolveF&& on_resolve) { - promise next; - - then([ - n = next, - f = std::forward(on_resolve) - ](auto&& v) mutable { - auto np = invoke_hpp::invoke( - std::forward(f), - std::forward(v)); - std::move(np).then([n](auto&& nv) mutable { - n.resolve(std::forward(nv)); - }).except([n](std::exception_ptr e) mutable { - n.reject(e); - }); - }).except([n = next](std::exception_ptr e) mutable { - n.reject(e); - }); - - return next; - } - - template < typename ResolveF > - auto then_all(ResolveF&& on_resolve) { - return then([ - f = std::forward(on_resolve) - ](auto&& v) mutable { - auto r = invoke_hpp::invoke( - std::forward(f), - std::forward(v)); - return make_all_promise(std::move(r)); - }); - } - - template < typename ResolveF > - auto then_race(ResolveF&& on_resolve) { - return then([ - f = std::forward(on_resolve) - ](auto&& v) mutable { - auto r = invoke_hpp::invoke( - std::forward(f), - std::forward(v)); - return make_race_promise(std::move(r)); - }); - } - - template < typename ResolveF > - auto then_tuple(ResolveF&& on_resolve) { - return then([ - f = std::forward(on_resolve) - ](auto&& v) mutable { - auto r = invoke_hpp::invoke( - std::forward(f), - std::forward(v)); - return make_tuple_promise(std::move(r)); - }); - } - - template < typename ResolveF - , typename RejectF - , typename ResolveFR = invoke_hpp::invoke_result_t > - std::enable_if_t< - !is_promise::value, - promise> - then(ResolveF&& on_resolve, RejectF&& on_reject) { - promise next; - state_->attach( - next, - std::forward(on_resolve), - std::forward(on_reject), - true); - return next; - } - - template < typename ResolveF - , typename ResolveFR = invoke_hpp::invoke_result_t > - std::enable_if_t< - !is_promise::value, - promise> - then(ResolveF&& on_resolve) { - promise next; - state_->attach( - next, - std::forward(on_resolve), - [](std::exception_ptr e) -> ResolveFR { - std::rethrow_exception(e); - }, - false); - return next; - } - - template < typename RejectF > - promise except(RejectF&& on_reject) { - return then( - [](auto&& v) { return std::forward(v); }, - std::forward(on_reject)); - } - - template < typename U > - bool resolve(U&& value) { - return state_->resolve(std::forward(value)); - } - - bool reject(std::exception_ptr e) noexcept { - return state_->reject(e); - } - - template < typename E > - bool reject(E&& e) { - return state_->reject( - std::make_exception_ptr(std::forward(e))); - } - - const T& get() const { - return state_->get(); - } - - template < typename U > - T get_or_default(U&& def) const { - try { - return get(); - } catch (...) { - return std::forward(def); - } - } - - void wait() const noexcept { - state_->wait(); - } - - template < typename Rep, typename Period > - promise_wait_status wait_for( - const std::chrono::duration& timeout_duration) const - { - return state_->wait_for(timeout_duration); - } - - template < typename Clock, typename Duration > - promise_wait_status wait_until( - const std::chrono::time_point& timeout_time) const - { - return state_->wait_until(timeout_time); - } - private: - class state; - std::shared_ptr state_; - private: - class state final : private detail::noncopyable { - public: - state() = default; - - template < typename U > - bool resolve(U&& value) { - std::lock_guard guard(mutex_); - if ( status_ != status::pending ) { - return false; - } - storage_.set(std::forward(value)); - status_ = status::resolved; - invoke_resolve_handlers_(); - cond_var_.notify_all(); - return true; - } - - bool reject(std::exception_ptr e) noexcept { - std::lock_guard guard(mutex_); - if ( status_ != status::pending ) { - return false; - } - exception_ = e; - status_ = status::rejected; - invoke_reject_handlers_(); - cond_var_.notify_all(); - return true; - } - - const T& get() { - std::unique_lock lock(mutex_); - cond_var_.wait(lock, [this](){ - return status_ != status::pending; - }); - if ( status_ == status::rejected ) { - std::rethrow_exception(exception_); - } - assert(status_ == status::resolved); - return storage_.value(); - } - - void wait() const noexcept { - std::unique_lock lock(mutex_); - cond_var_.wait(lock, [this](){ - return status_ != status::pending; - }); - } - - template < typename Rep, typename Period > - promise_wait_status wait_for( - const std::chrono::duration& timeout_duration) const - { - std::unique_lock lock(mutex_); - return cond_var_.wait_for(lock, timeout_duration, [this](){ - return status_ != status::pending; - }) ? promise_wait_status::no_timeout - : promise_wait_status::timeout; - } - - template < typename Clock, typename Duration > - promise_wait_status wait_until( - const std::chrono::time_point& timeout_time) const - { - std::unique_lock lock(mutex_); - return cond_var_.wait_until(lock, timeout_time, [this](){ - return status_ != status::pending; - }) ? promise_wait_status::no_timeout - : promise_wait_status::timeout; - } - - template < typename U, typename ResolveF, typename RejectF > - std::enable_if_t::value, void> - attach( - promise& next, - ResolveF&& on_resolve, - RejectF&& on_reject, - bool has_reject) - { - auto reject_h = [ - n = next, - f = std::forward(on_reject), - has_reject - ](std::exception_ptr e) mutable { - if ( has_reject ) { - try { - invoke_hpp::invoke( - std::forward(f), - e); - n.resolve(); - } catch (...) { - n.reject(std::current_exception()); - } - } else { - n.reject(e); - } - }; - - auto resolve_h = [ - n = next, - f = std::forward(on_resolve) - ](auto&& v) mutable { - try { - invoke_hpp::invoke( - std::forward(f), - std::forward(v)); - n.resolve(); - } catch (...) { - n.reject(std::current_exception()); - } - }; - - std::lock_guard guard(mutex_); - add_handlers_(std::move(resolve_h), std::move(reject_h)); - } - - template < typename U, typename ResolveF, typename RejectF > - std::enable_if_t::value, void> - attach( - promise& next, - ResolveF&& on_resolve, - RejectF&& on_reject, - bool has_reject) - { - auto reject_h = [ - n = next, - f = std::forward(on_reject), - has_reject - ](std::exception_ptr e) mutable { - if ( has_reject ) { - try { - auto r = invoke_hpp::invoke( - std::forward(f), - e); - n.resolve(std::move(r)); - } catch (...) { - n.reject(std::current_exception()); - } - } else { - n.reject(e); - } - }; - - auto resolve_h = [ - n = next, - f = std::forward(on_resolve) - ](auto&& v) mutable { - try { - auto r = invoke_hpp::invoke( - std::forward(f), - std::forward(v)); - n.resolve(std::move(r)); - } catch (...) { - n.reject(std::current_exception()); - } - }; - - std::lock_guard guard(mutex_); - add_handlers_(std::move(resolve_h), std::move(reject_h)); - } - private: - template < typename ResolveF, typename RejectF > - void add_handlers_(ResolveF&& resolve, RejectF&& reject) { - if ( status_ == status::resolved ) { - invoke_hpp::invoke( - std::forward(resolve), - storage_.value()); - } else if ( status_ == status::rejected ) { - invoke_hpp::invoke( - std::forward(reject), - exception_); - } else { - handlers_.emplace_back( - std::forward(resolve), - std::forward(reject)); - } - } - - void invoke_resolve_handlers_() noexcept { - const T& value = storage_.value(); - for ( const auto& h : handlers_ ) { - h.resolve_(value); - } - handlers_.clear(); - } - - void invoke_reject_handlers_() noexcept { - for ( const auto& h : handlers_ ) { - h.reject_(exception_); - } - handlers_.clear(); - } - private: - enum class status { - pending, - resolved, - rejected - }; - - status status_{status::pending}; - std::exception_ptr exception_{nullptr}; - - mutable std::mutex mutex_; - mutable std::condition_variable cond_var_; - - struct handler { - using resolve_t = std::function; - using reject_t = std::function; - - resolve_t resolve_; - reject_t reject_; - - template < typename ResolveF, typename RejectF > - handler(ResolveF&& resolve, RejectF&& reject) - : resolve_(std::forward(resolve)) - , reject_(std::forward(reject)) {} - }; - - std::vector handlers_; - detail::storage storage_; - }; - }; - - // - // promise - // - - template <> - class promise final { - public: - using value_type = void; - public: - promise() - : state_(std::make_shared()) {} - - promise(const promise&) noexcept = default; - promise& operator=(const promise&) noexcept = default; - - void swap(promise& other) noexcept { - state_.swap(other.state_); - } - - std::size_t hash() const noexcept { - return std::hash()(state_.get()); - } - - friend bool operator<(const promise& l, const promise& r) noexcept { - return l.state_ < r.state_; - } - - friend bool operator==(const promise& l, const promise& r) noexcept { - return l.state_ == r.state_; - } - - friend bool operator!=(const promise& l, const promise& r) noexcept { - return l.state_ != r.state_; - } - - template < typename ResolveF - , typename ResolveFR = invoke_hpp::invoke_result_t > - std::enable_if_t< - is_promise::value && std::is_void::value, - promise> - then(ResolveF&& on_resolve) { - promise next; - - then([ - n = next, - f = std::forward(on_resolve) - ]() mutable { - auto np = invoke_hpp::invoke( - std::forward(f)); - std::move(np).then([n]() mutable { - n.resolve(); - }).except([n](std::exception_ptr e) mutable { - n.reject(e); - }); - }).except([n = next](std::exception_ptr e) mutable { - n.reject(e); - }); - - return next; - } - - template < typename ResolveF - , typename ResolveFR = invoke_hpp::invoke_result_t > - std::enable_if_t< - is_promise::value && !std::is_void::value, - promise> - then(ResolveF&& on_resolve) { - promise next; - - then([ - n = next, - f = std::forward(on_resolve) - ]() mutable { - auto np = invoke_hpp::invoke( - std::forward(f)); - std::move(np).then([n](auto&& nv) mutable { - n.resolve(std::forward(nv)); - }).except([n](std::exception_ptr e) mutable { - n.reject(e); - }); - }).except([n = next](std::exception_ptr e) mutable { - n.reject(e); - }); - - return next; - } - - template < typename ResolveF > - auto then_all(ResolveF&& on_resolve) { - return then([ - f = std::forward(on_resolve) - ]() mutable { - auto r = invoke_hpp::invoke( - std::forward(f)); - return make_all_promise(std::move(r)); - }); - } - - template < typename ResolveF > - auto then_race(ResolveF&& on_resolve) { - return then([ - f = std::forward(on_resolve) - ]() mutable { - auto r = invoke_hpp::invoke( - std::forward(f)); - return make_race_promise(std::move(r)); - }); - } - - template < typename ResolveF > - auto then_tuple(ResolveF&& on_resolve) { - return then([ - f = std::forward(on_resolve) - ]() mutable { - auto r = invoke_hpp::invoke( - std::forward(f)); - return make_tuple_promise(std::move(r)); - }); - } - - template < typename ResolveF - , typename RejectF - , typename ResolveFR = invoke_hpp::invoke_result_t > - std::enable_if_t< - !is_promise::value, - promise> - then(ResolveF&& on_resolve, RejectF&& on_reject) { - promise next; - state_->attach( - next, - std::forward(on_resolve), - std::forward(on_reject), - true); - return next; - } - - template < typename ResolveF - , typename ResolveFR = invoke_hpp::invoke_result_t > - std::enable_if_t< - !is_promise::value, - promise> - then(ResolveF&& on_resolve) { - promise next; - state_->attach( - next, - std::forward(on_resolve), - [](std::exception_ptr e) -> ResolveFR { - std::rethrow_exception(e); - }, - false); - return next; - } - - template < typename RejectF > - promise except(RejectF&& on_reject) { - return then( - []{}, - std::forward(on_reject)); - } - - bool resolve() { - return state_->resolve(); - } - - bool reject(std::exception_ptr e) noexcept { - return state_->reject(e); - } - - template < typename E > - bool reject(E&& e) { - return state_->reject( - std::make_exception_ptr(std::forward(e))); - } - - void get() const { - state_->get(); - } - - void get_or_default() const { - try { - return get(); - } catch (...) { - // nothing - } - } - - void wait() const noexcept { - state_->wait(); - } - - template < typename Rep, typename Period > - promise_wait_status wait_for( - const std::chrono::duration& timeout_duration) const - { - return state_->wait_for(timeout_duration); - } - - template < typename Clock, typename Duration > - promise_wait_status wait_until( - const std::chrono::time_point& timeout_time) const - { - return state_->wait_until(timeout_time); - } - private: - class state; - std::shared_ptr state_; - private: - class state final : private detail::noncopyable { - public: - state() = default; - - bool resolve() { - std::lock_guard guard(mutex_); - if ( status_ != status::pending ) { - return false; - } - status_ = status::resolved; - invoke_resolve_handlers_(); - cond_var_.notify_all(); - return true; - } - - bool reject(std::exception_ptr e) noexcept { - std::lock_guard guard(mutex_); - if ( status_ != status::pending ) { - return false; - } - exception_ = e; - status_ = status::rejected; - invoke_reject_handlers_(); - cond_var_.notify_all(); - return true; - } - - void get() { - std::unique_lock lock(mutex_); - cond_var_.wait(lock, [this](){ - return status_ != status::pending; - }); - if ( status_ == status::rejected ) { - std::rethrow_exception(exception_); - } - assert(status_ == status::resolved); - } - - void wait() const noexcept { - std::unique_lock lock(mutex_); - cond_var_.wait(lock, [this](){ - return status_ != status::pending; - }); - } - - template < typename Rep, typename Period > - promise_wait_status wait_for( - const std::chrono::duration& timeout_duration) const - { - std::unique_lock lock(mutex_); - return cond_var_.wait_for(lock, timeout_duration, [this](){ - return status_ != status::pending; - }) ? promise_wait_status::no_timeout - : promise_wait_status::timeout; - } - - template < typename Clock, typename Duration > - promise_wait_status wait_until( - const std::chrono::time_point& timeout_time) const - { - std::unique_lock lock(mutex_); - return cond_var_.wait_until(lock, timeout_time, [this](){ - return status_ != status::pending; - }) ? promise_wait_status::no_timeout - : promise_wait_status::timeout; - } - - template < typename U, typename ResolveF, typename RejectF > - std::enable_if_t::value, void> - attach( - promise& next, - ResolveF&& on_resolve, - RejectF&& on_reject, - bool has_reject) - { - auto reject_h = [ - n = next, - f = std::forward(on_reject), - has_reject - ](std::exception_ptr e) mutable { - if ( has_reject ) { - try { - invoke_hpp::invoke( - std::forward(f), - e); - n.resolve(); - } catch (...) { - n.reject(std::current_exception()); - } - } else { - n.reject(e); - } - }; - - auto resolve_h = [ - n = next, - f = std::forward(on_resolve) - ]() mutable { - try { - invoke_hpp::invoke( - std::forward(f)); - n.resolve(); - } catch (...) { - n.reject(std::current_exception()); - } - }; - - std::lock_guard guard(mutex_); - add_handlers_(std::move(resolve_h), std::move(reject_h)); - } - - template < typename U, typename ResolveF, typename RejectF > - std::enable_if_t::value, void> - attach( - promise& next, - ResolveF&& on_resolve, - RejectF&& on_reject, - bool has_reject) - { - auto reject_h = [ - n = next, - f = std::forward(on_reject), - has_reject - ](std::exception_ptr e) mutable { - if ( has_reject ) { - try { - auto r = invoke_hpp::invoke( - std::forward(f), - e); - n.resolve(std::move(r)); - } catch (...) { - n.reject(std::current_exception()); - } - } else { - n.reject(e); - } - }; - - auto resolve_h = [ - n = next, - f = std::forward(on_resolve) - ]() mutable { - try { - auto r = invoke_hpp::invoke( - std::forward(f)); - n.resolve(std::move(r)); - } catch (...) { - n.reject(std::current_exception()); - } - }; - - std::lock_guard guard(mutex_); - add_handlers_(std::move(resolve_h), std::move(reject_h)); - } - private: - template < typename ResolveF, typename RejectF > - void add_handlers_(ResolveF&& resolve, RejectF&& reject) { - if ( status_ == status::resolved ) { - invoke_hpp::invoke( - std::forward(resolve)); - } else if ( status_ == status::rejected ) { - invoke_hpp::invoke( - std::forward(reject), - exception_); - } else { - handlers_.emplace_back( - std::forward(resolve), - std::forward(reject)); - } - } - - void invoke_resolve_handlers_() noexcept { - for ( const auto& h : handlers_ ) { - h.resolve_(); - } - handlers_.clear(); - } - - void invoke_reject_handlers_() noexcept { - for ( const auto& h : handlers_ ) { - h.reject_(exception_); - } - handlers_.clear(); - } - private: - enum class status { - pending, - resolved, - rejected - }; - - status status_{status::pending}; - std::exception_ptr exception_{nullptr}; - - mutable std::mutex mutex_; - mutable std::condition_variable cond_var_; - - struct handler { - using resolve_t = std::function; - using reject_t = std::function; - - resolve_t resolve_; - reject_t reject_; - - template < typename ResolveF, typename RejectF > - handler(ResolveF&& resolve, RejectF&& reject) - : resolve_(std::forward(resolve)) - , reject_(std::forward(reject)) {} - }; - - std::vector handlers_; - }; - }; - - // - // swap - // - - template < typename T > - void swap(promise& l, promise& r) noexcept { - l.swap(r); - } - - // - // make_promise - // - - template < typename R > - promise make_promise() { - return promise(); - } - - template < typename R, typename F > - promise make_promise(F&& f) { - promise result; - - auto resolver = [result](auto&& v) mutable { - return result.resolve(std::forward(v)); - }; - - auto rejector = [result](auto&& e) mutable { - return result.reject(std::forward(e)); - }; - - try { - invoke_hpp::invoke( - std::forward(f), - std::move(resolver), - std::move(rejector)); - } catch (...) { - result.reject(std::current_exception()); - } - - return result; - } - - // - // make_resolved_promise - // - - inline promise make_resolved_promise() { - promise result; - result.resolve(); - return result; - } - - template < typename R > - promise> make_resolved_promise(R&& v) { - promise> result; - result.resolve(std::forward(v)); - return result; - } - - // - // make_rejected_promise - // - - template < typename E > - promise make_rejected_promise(E&& e) { - promise result; - result.reject(std::forward(e)); - return result; - } - - template < typename R, typename E > - promise make_rejected_promise(E&& e) { - promise result; - result.reject(std::forward(e)); - return result; - } - - // - // make_all_promise - // - - namespace impl - { - template < typename ResultType > - class all_promise_context_t final : private detail::noncopyable { - public: - all_promise_context_t(std::size_t count) - : results_(count) {} - - template < typename T > - bool apply_result(std::size_t index, T&& value) { - results_[index].set(std::forward(value)); - return ++counter_ == results_.size(); - } - - std::vector get_results() { - std::vector ret; - ret.reserve(results_.size()); - for ( auto&& v : results_ ) { - ret.emplace_back(v.get()); - } - return ret; - } - private: - std::atomic_size_t counter_{0}; - std::vector> results_; - }; - } - - template < typename Iter - , typename SubPromise = typename Iter::value_type - , typename SubPromiseResult = typename SubPromise::value_type - , typename ResultPromiseValueType = std::vector > - promise - make_all_promise(Iter begin, Iter end) { - if ( begin == end ) { - return make_resolved_promise(ResultPromiseValueType()); - } - return make_promise([begin, end](auto&& resolver, auto&& rejector){ - std::size_t result_index = 0; - auto context = std::make_shared>(std::distance(begin, end)); - for ( Iter iter = begin; iter != end; ++iter, ++result_index ) { - (*iter).then([ - context, - resolver, - result_index - ](auto&& v) mutable { - if ( context->apply_result(result_index, std::forward(v)) ) { - resolver(context->get_results()); - } - }).except(rejector); - } - }); - } - - template < typename Container > - auto make_all_promise(Container&& container) { - return make_all_promise( - std::begin(container), - std::end(container)); - } - - // - // make_race_promise - // - - template < typename Iter - , typename SubPromise = typename Iter::value_type - , typename SubPromiseResult = typename SubPromise::value_type > - auto make_race_promise(Iter begin, Iter end) { - if ( begin == end ) { - throw std::logic_error("at least one input promise must be provided for make_race_promise"); - } - return make_promise([begin, end](auto&& resolver, auto&& rejector){ - for ( Iter iter = begin; iter != end; ++iter ) { - (*iter) - .then(resolver) - .except(rejector); - } - }); - } - - template < typename Container > - auto make_race_promise(Container&& container) { - return make_race_promise( - std::begin(container), - std::end(container)); - } - - // - // make_tuple_promise - // - - namespace impl - { - template < typename Tuple > - struct tuple_promise_result_impl {}; - - template < typename... Args > - struct tuple_promise_result_impl...>> { - using type = std::tuple; - }; - - template < typename Tuple > - struct tuple_promise_result { - using type = typename tuple_promise_result_impl>::type; - }; - - template < typename Tuple > - using tuple_promise_result_t = typename tuple_promise_result::type; - - template < typename... ResultTypes > - class tuple_promise_context_t { - public: - template < std::size_t N, typename T > - bool apply_result(T&& value) { - std::get(results_).set(std::forward(value)); - return ++counter_ == sizeof...(ResultTypes); - } - - std::tuple get_results() { - return get_results_impl( - std::make_index_sequence()); - } - private: - template < std::size_t... Is > - std::tuple get_results_impl(std::index_sequence) { - return std::make_tuple(std::get(results_).get()...); - } - private: - std::atomic_size_t counter_{0}; - std::tuple...> results_; - }; - - template < typename... ResultTypes > - using tuple_promise_context_ptr = std::shared_ptr< - tuple_promise_context_t>; - - template < std::size_t I - , typename Tuple - , typename Resolver - , typename Rejector - , typename... ResultTypes > - promise make_tuple_sub_promise_impl( - Tuple&& tuple, - Resolver&& resolver, - Rejector&& rejector, - const tuple_promise_context_ptr& context) - { - return std::get(tuple).then([ - context, - resolver - ](auto&& v) mutable { - if (context->template apply_result(std::forward(v))) { - resolver(context->get_results()); - } - }).except(rejector); - } - - template < typename Tuple - , std::size_t... Is - , typename ResultTuple = tuple_promise_result_t> > - std::enable_if_t< - sizeof...(Is) == 0, - promise> - make_tuple_promise_impl(Tuple&&, std::index_sequence) { - return make_resolved_promise(ResultTuple()); - } - - template < typename Tuple - , std::size_t... Is - , typename ResultTuple = tuple_promise_result_t> > - std::enable_if_t< - sizeof...(Is) != 0, - promise> - make_tuple_promise_impl(Tuple&& tuple, std::index_sequence) { - auto result = promise(); - - auto resolver = [result](auto&& v) mutable { - return result.resolve(std::forward(v)); - }; - - auto rejector = [result](auto&& e) mutable { - return result.reject(std::forward(e)); - }; - - try { - auto context = std::make_shared...>>(); - auto promises = std::make_tuple(make_tuple_sub_promise_impl( - tuple, - resolver, - rejector, - context)...); - (void)promises; - } catch (...) { - result.reject(std::current_exception()); - } - - return result; - } - } - - template < typename Tuple - , typename ResultTuple = impl::tuple_promise_result_t> > - promise - make_tuple_promise(Tuple&& tuple) { - return impl::make_tuple_promise_impl( - std::forward(tuple), - std::make_index_sequence::value>()); - } -} - -namespace std -{ - template < typename T > - struct hash> final { - std::size_t operator()(const promise_hpp::promise& p) const noexcept { - return p.hash(); - } - }; -} diff --git a/headers/3rdparty/promise.hpp/scheduler.hpp b/headers/3rdparty/promise.hpp/scheduler.hpp deleted file mode 100644 index 93a17bf1..00000000 --- a/headers/3rdparty/promise.hpp/scheduler.hpp +++ /dev/null @@ -1,335 +0,0 @@ -/******************************************************************************* - * This file is part of the "https://github.com/blackmatov/promise.hpp" - * For conditions of distribution and use, see copyright notice in LICENSE.md - * Copyright (C) 2018-2019, by Matvey Cherevko (blackmatov@gmail.com) - ******************************************************************************/ - -#pragma once - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "promise.hpp" - -namespace scheduler_hpp -{ - using namespace promise_hpp; - - enum class scheduler_priority { - lowest, - below_normal, - normal, - above_normal, - highest - }; - - enum class scheduler_processing_status { - done, - timeout, - cancelled - }; - - class scheduler_cancelled_exception : public std::runtime_error { - public: - scheduler_cancelled_exception() - : std::runtime_error("scheduler has stopped working") {} - }; - - class scheduler final : private detail::noncopyable { - public: - scheduler(); - ~scheduler() noexcept; - - using processing_result_t = std::pair< - scheduler_processing_status, - std::size_t>; - - template < typename F, typename... Args > - using schedule_invoke_result_t = invoke_hpp::invoke_result_t< - std::decay_t, - std::decay_t...>; - - template < typename F, typename... Args - , typename R = schedule_invoke_result_t > - promise schedule(F&& f, Args&&... args); - - template < typename F, typename... Args - , typename R = schedule_invoke_result_t > - promise schedule(scheduler_priority scheduler_priority, F&& f, Args&&... args); - - processing_result_t process_one_task() noexcept; - processing_result_t process_all_tasks() noexcept; - - template < typename Rep, typename Period > - processing_result_t process_tasks_for( - const std::chrono::duration& timeout_duration) noexcept; - - template < typename Clock, typename Duration > - processing_result_t process_tasks_until( - const std::chrono::time_point& timeout_time) noexcept; - private: - class task; - using task_ptr = std::unique_ptr; - template < typename R, typename F, typename... Args > - class concrete_task; - private: - void push_task_(scheduler_priority scheduler_priority, task_ptr task); - task_ptr pop_task_() noexcept; - void shutdown_() noexcept; - void process_task_(std::unique_lock lock) noexcept; - private: - std::vector> tasks_; - std::atomic cancelled_{false}; - std::atomic active_task_count_{0}; - mutable std::mutex tasks_mutex_; - mutable std::condition_variable cond_var_; - }; - - class scheduler::task : private noncopyable { - public: - virtual ~task() noexcept = default; - virtual void run() noexcept = 0; - virtual void cancel() noexcept = 0; - }; - - template < typename R, typename F, typename... Args > - class scheduler::concrete_task : public task { - F f_; - std::tuple args_; - promise promise_; - public: - template < typename U > - concrete_task(U&& u, std::tuple&& args); - void run() noexcept final; - void cancel() noexcept final; - promise future() noexcept; - }; - - template < typename F, typename... Args > - class scheduler::concrete_task : public task { - F f_; - std::tuple args_; - promise promise_; - public: - template < typename U > - concrete_task(U&& u, std::tuple&& args); - void run() noexcept final; - void cancel() noexcept final; - promise future() noexcept; - }; -} - -namespace scheduler_hpp -{ - inline scheduler::scheduler() = default; - - inline scheduler::~scheduler() noexcept { - shutdown_(); - } - - template < typename F, typename... Args, typename R > - promise scheduler::schedule(F&& f, Args&&... args) { - return schedule( - scheduler_priority::normal, - std::forward(f), - std::forward(args)...); - } - - template < typename F, typename... Args, typename R > - promise scheduler::schedule(scheduler_priority priority, F&& f, Args&&... args) { - using task_t = concrete_task< - R, - std::decay_t, - std::decay_t...>; - std::unique_ptr task = std::make_unique( - std::forward(f), - std::make_tuple(std::forward(args)...)); - promise future = task->future(); - std::lock_guard guard(tasks_mutex_); - push_task_(priority, std::move(task)); - return future; - } - - inline scheduler::processing_result_t scheduler::process_one_task() noexcept { - std::unique_lock lock(tasks_mutex_); - if ( cancelled_ ) { - return std::make_pair(scheduler_processing_status::cancelled, 0u); - } - if ( tasks_.empty() ) { - return std::make_pair(scheduler_processing_status::done, 0u); - } - process_task_(std::move(lock)); - return std::make_pair(scheduler_processing_status::done, 1u); - } - - inline scheduler::processing_result_t scheduler::process_all_tasks() noexcept { - std::size_t processed_tasks = 0; - while ( !cancelled_ && active_task_count_ ) { - std::unique_lock lock(tasks_mutex_); - cond_var_.wait(lock, [this](){ - return cancelled_ || !active_task_count_ || !tasks_.empty(); - }); - if ( !tasks_.empty() ) { - process_task_(std::move(lock)); - ++processed_tasks; - } - } - return std::make_pair( - cancelled_ - ? scheduler_processing_status::cancelled - : scheduler_processing_status::done, - processed_tasks); - } - - template < typename Rep, typename Period > - scheduler::processing_result_t scheduler::process_tasks_for( - const std::chrono::duration& timeout_duration) noexcept - { - return process_tasks_until( - std::chrono::steady_clock::now() + timeout_duration); - } - - template < typename Clock, typename Duration > - scheduler::processing_result_t scheduler::process_tasks_until( - const std::chrono::time_point& timeout_time) noexcept - { - std::size_t processed_tasks = 0; - while ( !cancelled_ && active_task_count_ ) { - if ( !(Clock::now() < timeout_time) ) { - return std::make_pair( - scheduler_processing_status::timeout, - processed_tasks); - } - std::unique_lock lock(tasks_mutex_); - cond_var_.wait_until(lock, timeout_time, [this](){ - return cancelled_ || !active_task_count_ || !tasks_.empty(); - }); - if ( !tasks_.empty() ) { - process_task_(std::move(lock)); - ++processed_tasks; - } - } - return std::make_pair( - cancelled_ - ? scheduler_processing_status::cancelled - : scheduler_processing_status::done, - processed_tasks); - } - - inline void scheduler::push_task_(scheduler_priority priority, task_ptr task) { - tasks_.emplace_back(priority, std::move(task)); - std::push_heap(tasks_.begin(), tasks_.end()); - ++active_task_count_; - cond_var_.notify_one(); - } - - inline scheduler::task_ptr scheduler::pop_task_() noexcept { - if ( !tasks_.empty() ) { - std::pop_heap(tasks_.begin(), tasks_.end()); - task_ptr task = std::move(tasks_.back().second); - tasks_.pop_back(); - return task; - } - return nullptr; - } - - inline void scheduler::shutdown_() noexcept { - std::lock_guard guard(tasks_mutex_); - while ( !tasks_.empty() ) { - task_ptr task = pop_task_(); - if ( task ) { - task->cancel(); - --active_task_count_; - } - } - cancelled_.store(true); - cond_var_.notify_all(); - } - - inline void scheduler::process_task_(std::unique_lock lock) noexcept { - assert(lock.owns_lock()); - task_ptr task = pop_task_(); - if ( task ) { - lock.unlock(); - task->run(); - lock.lock(); - --active_task_count_; - cond_var_.notify_all(); - } - } -} - -namespace scheduler_hpp -{ - // - // concrete_task - // - - template < typename R, typename F, typename... Args > - template < typename U > - scheduler::concrete_task::concrete_task(U&& u, std::tuple&& args) - : f_(std::forward(u)) - , args_(std::move(args)) {} - - template < typename R, typename F, typename... Args > - void scheduler::concrete_task::run() noexcept { - try { - R value = invoke_hpp::apply(std::move(f_), std::move(args_)); - promise_.resolve(std::move(value)); - } catch (...) { - promise_.reject(std::current_exception()); - } - } - - template < typename R, typename F, typename... Args > - void scheduler::concrete_task::cancel() noexcept { - promise_.reject(scheduler_cancelled_exception()); - } - - template < typename R, typename F, typename... Args > - promise scheduler::concrete_task::future() noexcept { - return promise_; - } - - // - // concrete_task - // - - template < typename F, typename... Args > - template < typename U > - scheduler::concrete_task::concrete_task(U&& u, std::tuple&& args) - : f_(std::forward(u)) - , args_(std::move(args)) {} - - template < typename F, typename... Args > - void scheduler::concrete_task::run() noexcept { - try { - invoke_hpp::apply(std::move(f_), std::move(args_)); - promise_.resolve(); - } catch (...) { - promise_.reject(std::current_exception()); - } - } - - template < typename F, typename... Args > - void scheduler::concrete_task::cancel() noexcept { - promise_.reject(scheduler_cancelled_exception()); - } - - template < typename F, typename... Args > - promise scheduler::concrete_task::future() noexcept { - return promise_; - } -} diff --git a/headers/enduro2d/base/types.hpp b/headers/enduro2d/base/types.hpp index 612be8f6..9c1e56f9 100644 --- a/headers/enduro2d/base/types.hpp +++ b/headers/enduro2d/base/types.hpp @@ -8,11 +8,12 @@ #include "_base.hpp" +#include +#include +#include +#include + #include <3rdparty/variant/variant.hpp> -#include <3rdparty/flat.hpp/flat_set.hpp> -#include <3rdparty/flat.hpp/flat_map.hpp> -#include <3rdparty/flat.hpp/flat_multiset.hpp> -#include <3rdparty/flat.hpp/flat_multimap.hpp> namespace e2d { diff --git a/headers/enduro2d/core/_core.hpp b/headers/enduro2d/core/_core.hpp index 1718fd9e..15e8dd73 100644 --- a/headers/enduro2d/core/_core.hpp +++ b/headers/enduro2d/core/_core.hpp @@ -12,10 +12,10 @@ #include -#include <3rdparty/promise.hpp/invoke.hpp> -#include <3rdparty/promise.hpp/jobber.hpp> -#include <3rdparty/promise.hpp/promise.hpp> -#include <3rdparty/promise.hpp/scheduler.hpp> +#include +#include +#include +#include namespace e2d { diff --git a/headers/enduro2d/high/_high.hpp b/headers/enduro2d/high/_high.hpp index 0cc13c2f..a593f322 100644 --- a/headers/enduro2d/high/_high.hpp +++ b/headers/enduro2d/high/_high.hpp @@ -8,7 +8,7 @@ #include "../core/_all.hpp" -#include <3rdparty/ecs.hpp/ecs.hpp> +#include namespace e2d { diff --git a/scripts/cloc_all.sh b/scripts/cloc_all.sh index 300be35a..f6abdbd9 100755 --- a/scripts/cloc_all.sh +++ b/scripts/cloc_all.sh @@ -2,9 +2,6 @@ SCRIPT_DIR=`dirname "$BASH_SOURCE"` cloc \ $SCRIPT_DIR/../headers/enduro2d \ - $SCRIPT_DIR/../headers/3rdparty/ecs.hpp \ - $SCRIPT_DIR/../headers/3rdparty/flat.hpp \ - $SCRIPT_DIR/../headers/3rdparty/promise.hpp \ $SCRIPT_DIR/../sources/enduro2d \ $SCRIPT_DIR/../samples/sources \ $SCRIPT_DIR/../untests/sources diff --git a/scripts/cloc_engine.sh b/scripts/cloc_engine.sh index b2159971..57b570c6 100755 --- a/scripts/cloc_engine.sh +++ b/scripts/cloc_engine.sh @@ -2,7 +2,4 @@ SCRIPT_DIR=`dirname "$BASH_SOURCE"` cloc \ $SCRIPT_DIR/../headers/enduro2d \ - $SCRIPT_DIR/../headers/3rdparty/ecs.hpp \ - $SCRIPT_DIR/../headers/3rdparty/flat.hpp \ - $SCRIPT_DIR/../headers/3rdparty/promise.hpp \ $SCRIPT_DIR/../sources/enduro2d diff --git a/scripts/cloc_headers.sh b/scripts/cloc_headers.sh index e9c382a5..beff52c2 100755 --- a/scripts/cloc_headers.sh +++ b/scripts/cloc_headers.sh @@ -1,7 +1,3 @@ #!/bin/bash SCRIPT_DIR=`dirname "$BASH_SOURCE"` -cloc \ - $SCRIPT_DIR/../headers/enduro2d \ - $SCRIPT_DIR/../headers/3rdparty/ecs.hpp \ - $SCRIPT_DIR/../headers/3rdparty/flat.hpp \ - $SCRIPT_DIR/../headers/3rdparty/promise.hpp \ +cloc $SCRIPT_DIR/../headers/enduro2d diff --git a/scripts/update_modules.sh b/scripts/update_modules.sh index 1a1f7338..a59b3841 100755 --- a/scripts/update_modules.sh +++ b/scripts/update_modules.sh @@ -20,12 +20,6 @@ git submodule update --remote mkdir -p $UNTESTS_DIR/catch cp -fv $MODULES_DIR/catch2/single_include/catch2/catch.hpp $UNTESTS_DIR/catch/catch.hpp -mkdir -p $HEADERS_RDPARTY_DIR/ecs.hpp -cp -rfv $MODULES_DIR/ecs.hpp/headers/ecs.hpp/. $HEADERS_RDPARTY_DIR/ecs.hpp/ - -mkdir -p $HEADERS_RDPARTY_DIR/flat.hpp -cp -rfv $MODULES_DIR/flat.hpp/headers/flat.hpp/. $HEADERS_RDPARTY_DIR/flat.hpp/ - mkdir -p $SOURCES_RDPARTY_DIR/imgui cp -fv $MODULES_DIR/imgui/imgui.cpp $SOURCES_RDPARTY_DIR/imgui/imgui.cpp cp -fv $MODULES_DIR/imgui/imgui.h $SOURCES_RDPARTY_DIR/imgui/imgui.h @@ -48,9 +42,6 @@ cp -fv $MODULES_DIR/miniz/miniz_tinfl.h $SOURCES_RDPARTY_DIR/miniz/miniz_tinfl.h cp -fv $MODULES_DIR/miniz/miniz_zip.c $SOURCES_RDPARTY_DIR/miniz/miniz_zip.c cp -fv $MODULES_DIR/miniz/miniz_zip.h $SOURCES_RDPARTY_DIR/miniz/miniz_zip.h -mkdir -p $HEADERS_RDPARTY_DIR/promise.hpp -cp -rfv $MODULES_DIR/promise.hpp/headers/promise.hpp/. $HEADERS_RDPARTY_DIR/promise.hpp/ - mkdir -p $HEADERS_RDPARTY_DIR/pugixml cp -rfv $MODULES_DIR/pugixml/src/. $HEADERS_RDPARTY_DIR/pugixml/