EnTT  3.10.0
cache.hpp
1 #ifndef ENTT_RESOURCE_RESOURCE_CACHE_HPP
2 #define ENTT_RESOURCE_RESOURCE_CACHE_HPP
3 
4 #include <cstddef>
5 #include <functional>
6 #include <iterator>
7 #include <memory>
8 #include <tuple>
9 #include <type_traits>
10 #include <utility>
11 #include "../config/config.h"
12 #include "../container/dense_map.hpp"
13 #include "../core/compressed_pair.hpp"
14 #include "../core/fwd.hpp"
15 #include "../core/iterator.hpp"
16 #include "../core/utility.hpp"
17 #include "fwd.hpp"
18 #include "loader.hpp"
19 #include "resource.hpp"
20 
21 namespace entt {
22 
28 namespace internal {
29 
30 template<typename Type, typename It>
31 class resource_cache_iterator final {
32  template<typename, typename>
33  friend class resource_cache_iterator;
34 
35 public:
36  using value_type = std::pair<id_type, resource<Type>>;
37  using pointer = input_iterator_pointer<value_type>;
38  using reference = value_type;
39  using difference_type = std::ptrdiff_t;
40  using iterator_category = std::input_iterator_tag;
41 
42  resource_cache_iterator() ENTT_NOEXCEPT = default;
43 
44  resource_cache_iterator(const It iter) ENTT_NOEXCEPT
45  : it{iter} {}
46 
47  template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>>
48  resource_cache_iterator(const resource_cache_iterator<std::remove_const_t<Type>, Other> &other) ENTT_NOEXCEPT
49  : it{other.it} {}
50 
51  resource_cache_iterator &operator++() ENTT_NOEXCEPT {
52  return ++it, *this;
53  }
54 
55  resource_cache_iterator operator++(int) ENTT_NOEXCEPT {
56  resource_cache_iterator orig = *this;
57  return ++(*this), orig;
58  }
59 
60  resource_cache_iterator &operator--() ENTT_NOEXCEPT {
61  return --it, *this;
62  }
63 
64  resource_cache_iterator operator--(int) ENTT_NOEXCEPT {
65  resource_cache_iterator orig = *this;
66  return operator--(), orig;
67  }
68 
69  resource_cache_iterator &operator+=(const difference_type value) ENTT_NOEXCEPT {
70  it += value;
71  return *this;
72  }
73 
74  resource_cache_iterator operator+(const difference_type value) const ENTT_NOEXCEPT {
75  resource_cache_iterator copy = *this;
76  return (copy += value);
77  }
78 
79  resource_cache_iterator &operator-=(const difference_type value) ENTT_NOEXCEPT {
80  return (*this += -value);
81  }
82 
83  resource_cache_iterator operator-(const difference_type value) const ENTT_NOEXCEPT {
84  return (*this + -value);
85  }
86 
87  [[nodiscard]] reference operator[](const difference_type value) const ENTT_NOEXCEPT {
88  return {it[value].first, resource<Type>{it[value].second}};
89  }
90 
91  [[nodiscard]] reference operator*() const ENTT_NOEXCEPT {
92  return (*this)[0];
93  }
94 
95  [[nodiscard]] pointer operator->() const ENTT_NOEXCEPT {
96  return operator*();
97  }
98 
99  template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
100  friend std::ptrdiff_t operator-(const resource_cache_iterator<TLhs, ILhs> &, const resource_cache_iterator<TRhs, IRhs> &) ENTT_NOEXCEPT;
101 
102  template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
103  friend bool operator==(const resource_cache_iterator<TLhs, ILhs> &, const resource_cache_iterator<TRhs, IRhs> &) ENTT_NOEXCEPT;
104 
105  template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
106  friend bool operator<(const resource_cache_iterator<TLhs, ILhs> &, const resource_cache_iterator<TRhs, IRhs> &) ENTT_NOEXCEPT;
107 
108 private:
109  It it;
110 };
111 
112 template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
113 [[nodiscard]] std::ptrdiff_t operator-(const resource_cache_iterator<TLhs, ILhs> &lhs, const resource_cache_iterator<TRhs, IRhs> &rhs) ENTT_NOEXCEPT {
114  return lhs.it - rhs.it;
115 }
116 
117 template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
118 [[nodiscard]] bool operator==(const resource_cache_iterator<TLhs, ILhs> &lhs, const resource_cache_iterator<TRhs, IRhs> &rhs) ENTT_NOEXCEPT {
119  return lhs.it == rhs.it;
120 }
121 
122 template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
123 [[nodiscard]] bool operator!=(const resource_cache_iterator<TLhs, ILhs> &lhs, const resource_cache_iterator<TRhs, IRhs> &rhs) ENTT_NOEXCEPT {
124  return !(lhs == rhs);
125 }
126 
127 template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
128 [[nodiscard]] bool operator<(const resource_cache_iterator<TLhs, ILhs> &lhs, const resource_cache_iterator<TRhs, IRhs> &rhs) ENTT_NOEXCEPT {
129  return lhs.it < rhs.it;
130 }
131 
132 template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
133 [[nodiscard]] bool operator>(const resource_cache_iterator<TLhs, ILhs> &lhs, const resource_cache_iterator<TRhs, IRhs> &rhs) ENTT_NOEXCEPT {
134  return rhs < lhs;
135 }
136 
137 template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
138 [[nodiscard]] bool operator<=(const resource_cache_iterator<TLhs, ILhs> &lhs, const resource_cache_iterator<TRhs, IRhs> &rhs) ENTT_NOEXCEPT {
139  return !(lhs > rhs);
140 }
141 
142 template<typename TLhs, typename ILhs, typename TRhs, typename IRhs>
143 [[nodiscard]] bool operator>=(const resource_cache_iterator<TLhs, ILhs> &lhs, const resource_cache_iterator<TRhs, IRhs> &rhs) ENTT_NOEXCEPT {
144  return !(lhs < rhs);
145 }
146 
147 } // namespace internal
148 
160 template<typename Type, typename Loader, typename Allocator>
162  using alloc_traits = typename std::allocator_traits<Allocator>;
163  static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
164  using container_allocator = typename alloc_traits::template rebind_alloc<std::pair<const id_type, typename Loader::result_type>>;
166 
167 public:
169  using value_type = Type;
171  using size_type = std::size_t;
173  using loader_type = Loader;
175  using allocator_type = Allocator;
177  using iterator = internal::resource_cache_iterator<Type, typename container_type::iterator>;
179  using const_iterator = internal::resource_cache_iterator<const Type, typename container_type::const_iterator>;
180 
184 
189  explicit resource_cache(const allocator_type &allocator)
190  : resource_cache{loader_type{}, allocator} {}
191 
197  explicit resource_cache(const loader_type &callable, const allocator_type &allocator = allocator_type{})
198  : pool{container_type{allocator}, callable} {}
199 
201  resource_cache(const resource_cache &) = default;
202 
208  resource_cache(const resource_cache &other, const allocator_type &allocator)
209  : pool{std::piecewise_construct, std::forward_as_tuple(other.pool.first(), allocator), std::forward_as_tuple(other.pool.second())} {}
210 
213 
219  resource_cache(resource_cache &&other, const allocator_type &allocator)
220  : pool{std::piecewise_construct, std::forward_as_tuple(std::move(other.pool.first()), allocator), std::forward_as_tuple(std::move(other.pool.second()))} {}
221 
227 
233 
238  [[nodiscard]] constexpr allocator_type get_allocator() const ENTT_NOEXCEPT {
239  return pool.first().get_allocator();
240  }
241 
250  [[nodiscard]] const_iterator cbegin() const ENTT_NOEXCEPT {
251  return pool.first().begin();
252  }
253 
255  [[nodiscard]] const_iterator begin() const ENTT_NOEXCEPT {
256  return cbegin();
257  }
258 
260  [[nodiscard]] iterator begin() ENTT_NOEXCEPT {
261  return pool.first().begin();
262  }
263 
274  [[nodiscard]] const_iterator cend() const ENTT_NOEXCEPT {
275  return pool.first().end();
276  }
277 
279  [[nodiscard]] const_iterator end() const ENTT_NOEXCEPT {
280  return cend();
281  }
282 
284  [[nodiscard]] iterator end() ENTT_NOEXCEPT {
285  return pool.first().end();
286  }
287 
292  [[nodiscard]] bool empty() const ENTT_NOEXCEPT {
293  return pool.first().empty();
294  }
295 
300  [[nodiscard]] size_type size() const ENTT_NOEXCEPT {
301  return pool.first().size();
302  }
303 
305  void clear() ENTT_NOEXCEPT {
306  pool.first().clear();
307  }
308 
326  template<typename... Args>
327  std::pair<iterator, bool> load(const id_type id, Args &&...args) {
328  if(auto it = pool.first().find(id); it != pool.first().end()) {
329  return {it, false};
330  }
331 
332  return pool.first().emplace(id, pool.second()(std::forward<Args>(args)...));
333  }
334 
339  template<typename... Args>
340  std::pair<iterator, bool> force_load(const id_type id, Args &&...args) {
341  return {pool.first().insert_or_assign(id, pool.second()(std::forward<Args>(args)...)).first, true};
342  }
343 
354  [[nodiscard]] resource<const value_type> operator[](const id_type id) const {
355  if(auto it = pool.first().find(id); it != pool.first().cend()) {
356  return resource<const value_type>{it->second};
357  }
358 
359  return {};
360  }
361 
363  [[nodiscard]] resource<value_type> operator[](const id_type id) {
364  if(auto it = pool.first().find(id); it != pool.first().end()) {
365  return resource<value_type>{it->second};
366  }
367 
368  return {};
369  }
370 
376  [[nodiscard]] bool contains(const id_type id) const {
377  return pool.first().contains(id);
378  }
379 
386  const auto it = pool.first().begin();
387  return pool.first().erase(it + (pos - const_iterator{it}));
388  }
389 
397  const auto it = pool.first().begin();
398  return pool.first().erase(it + (first - const_iterator{it}), it + (last - const_iterator{it}));
399  }
400 
406  size_type erase(const id_type id) {
407  return pool.first().erase(id);
408  }
409 
414  [[nodiscard]] loader_type loader() const {
415  return pool.second();
416  }
417 
418 private:
420 };
421 
422 } // namespace entt
423 
424 #endif
A compressed pair.
Associative container for key-value pairs with unique keys.
Definition: dense_map.hpp:265
Basic cache for resources of any type.
Definition: cache.hpp:161
size_type erase(const id_type id)
Removes the given elements from a cache.
Definition: cache.hpp:406
resource_cache()
Default constructor.
Definition: cache.hpp:182
iterator end()
Returns an iterator to the end.
Definition: cache.hpp:284
resource_cache(const resource_cache &other, const allocator_type &allocator)
Allocator-extended copy constructor.
Definition: cache.hpp:208
const_iterator cend() const
Returns an iterator to the end.
Definition: cache.hpp:274
loader_type loader() const
Returns the loader used to create resources.
Definition: cache.hpp:414
std::pair< iterator, bool > force_load(const id_type id, Args &&...args)
Force loads a resource, if its identifier does not exist.
Definition: cache.hpp:340
void clear()
Clears a cache.
Definition: cache.hpp:305
const_iterator begin() const
Returns an iterator to the beginning.
Definition: cache.hpp:255
iterator erase(const_iterator pos)
Removes an element from a given position.
Definition: cache.hpp:385
size_type size() const
Number of resources managed by a cache.
Definition: cache.hpp:300
Type value_type
Resource type.
Definition: cache.hpp:169
bool empty() const
Returns true if a cache contains no resources, false otherwise.
Definition: cache.hpp:292
constexpr allocator_type get_allocator() const
Returns the associated allocator.
Definition: cache.hpp:238
Loader loader_type
Loader type.
Definition: cache.hpp:173
resource_cache(resource_cache &&other, const allocator_type &allocator)
Allocator-extended move constructor.
Definition: cache.hpp:219
resource_cache(const allocator_type &allocator)
Constructs an empty cache with a given allocator.
Definition: cache.hpp:189
resource_cache(const loader_type &callable, const allocator_type &allocator=allocator_type{})
Constructs an empty cache with a given allocator and loader.
Definition: cache.hpp:197
internal::resource_cache_iterator< const Type, typename container_type::const_iterator > const_iterator
Constant input iterator type.
Definition: cache.hpp:179
std::pair< iterator, bool > load(const id_type id, Args &&...args)
Loads a resource, if its identifier does not exist.
Definition: cache.hpp:327
resource_cache & operator=(resource_cache &&)=default
Default move assignment operator.
resource_cache(resource_cache &&)=default
Default move constructor.
internal::resource_cache_iterator< Type, typename container_type::iterator > iterator
Input iterator type.
Definition: cache.hpp:177
Allocator allocator_type
Allocator type.
Definition: cache.hpp:175
resource_cache(const resource_cache &)=default
Default copy constructor.
resource< const value_type > operator[](const id_type id) const
Returns a handle for a given resource identifier.
Definition: cache.hpp:354
resource_cache & operator=(const resource_cache &)=default
Default copy assignment operator.
iterator begin()
Returns an iterator to the beginning.
Definition: cache.hpp:260
const_iterator cbegin() const
Returns an iterator to the beginning.
Definition: cache.hpp:250
const_iterator end() const
Returns an iterator to the end.
Definition: cache.hpp:279
resource< value_type > operator[](const id_type id)
Returns a handle for a given resource identifier.
Definition: cache.hpp:363
std::size_t size_type
Unsigned integer type.
Definition: cache.hpp:171
iterator erase(const_iterator first, const_iterator last)
Removes the given elements from a cache.
Definition: cache.hpp:396
bool contains(const id_type id) const
Checks if a cache contains a given identifier.
Definition: cache.hpp:376
Basic resource handle.
Definition: resource.hpp:23
EnTT default namespace.
Definition: dense_map.hpp:22
constexpr bool operator==(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs)
Compares two hashed strings.
std::uint32_t id_type
Alias declaration for type identifiers.
Definition: fwd.hpp:14
constexpr bool operator<=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs)
Compares two hashed strings.
constexpr bool operator>=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs)
Compares two hashed strings.
constexpr type_list< Type..., Other... > operator+(type_list< Type... >, type_list< Other... >)
Concatenates multiple type lists.
constexpr bool operator<(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs)
Compares two hashed strings.
bool operator!=(const basic_any< Len, Align > &lhs, const basic_any< Len, Align > &rhs)
Checks if two wrappers differ in their content.
Definition: any.hpp:402
constexpr bool operator>(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs)
Compares two hashed strings.