51 template <
typename CookieType>
64 iConsumer{ &aConsumer },
74 iConsumer{ aOther.iConsumer },
75 iCookie{ aOther.iCookie }
80 iConsumer{ aOther.iConsumer },
81 iCookie{ aOther.iCookie }
92 iConsumer = aOther.iConsumer;
93 iCookie = aOther.iCookie;
102 iConsumer = aOther.iConsumer;
103 iCookie = aOther.iCookie;
111 return iConsumer == aRhs.iConsumer && iCookie == aRhs.iCookie;
115 return !(*
this == aRhs);
119 return std::forward_as_tuple(iConsumer, iCookie) < std::forward_as_tuple(aRhs.iConsumer, aRhs.iCookie);
124 return have_consumer() && have_cookie();
153 bool have_consumer()
const
155 return iConsumer !=
nullptr;
157 i_basic_cookie_consumer<cookie_type>& consumer()
const
161 bool have_cookie()
const
166 mutable i_basic_cookie_consumer<cookie_type>* iConsumer;
172 template<
typename T>
struct is_smart_ptr : std::false_type {};
173 template<
typename T>
struct is_smart_ptr<
std::shared_ptr<T>> : std::true_type {};
174 template<
typename T>
struct is_smart_ptr<
std::unique_ptr<T>> : std::true_type {};
175 template<
typename T>
struct is_smart_ptr<ref_ptr<T>> : std::true_type {};
177 inline constexpr bool is_smart_ptr_v = is_smart_ptr<T>::value;
180 template <
typename T,
typename Container = vector<T>,
typename CookieType = cookie,
typename MutexType = null_mutex>
189 typedef typename container_type::iterator
iterator;
192 typedef typename container_type::size_type reverse_index_t;
193 typedef std::vector<reverse_index_t> reverse_indices_t;
194 typedef std::vector<cookie_type> cookies_t;
196 static constexpr cookie_type INVALID_COOKIE = invalid_cookie<cookie_type>;
197 static constexpr reverse_index_t INVALID_REVERSE_INDEX =
static_cast<reverse_index_t
>(~reverse_index_t{});
205 return items().empty();
209 return items().size();
213 std::scoped_lock<mutex_type> lock{
mutex() };
214 return aCookie < reverse_indices().size() && reverse_indices()[aCookie] != INVALID_REVERSE_INDEX;
218 std::scoped_lock<mutex_type> lock{
mutex() };
225 std::scoped_lock<mutex_type> lock{
mutex() };
232 std::scoped_lock<mutex_type> lock{
mutex() };
233 if (aCookie >= reverse_indices().
size())
235 auto reverseIndex = reverse_indices()[aCookie];
236 if (reverseIndex == INVALID_REVERSE_INDEX)
238 return items()[reverseIndex];
246 return items().at(aIndex);
250 return items().at(aIndex);
266 template <
typename... Args>
272 add(
cookie, std::forward<Args>(aArgs)...);
283 return add<const abstract_t<value_type>&>(aCookie, aItem);
289 template <
typename... Args>
292 std::scoped_lock<mutex_type> lock{
mutex() };
293 assert(std::find(free_cookies().
begin(), free_cookies().
end(), aCookie) == free_cookies().
end());
294 if (reverse_indices().
size() <= aCookie)
295 reverse_indices().insert(reverse_indices().
end(), (aCookie + 1) - reverse_indices().
size(), INVALID_REVERSE_INDEX);
296 if (reverse_indices()[aCookie] != INVALID_REVERSE_INDEX)
298 std::optional<iterator> result;
299 if constexpr (!detail::is_smart_ptr_v<value_type>)
300 result =
items().emplace(
items().end(), std::forward<Args>(aArgs)...);
301 else if constexpr (detail::is_smart_ptr_v<value_type> && std::is_abstract_v<typename value_type::element_type>)
302 result =
items().emplace(
items().end(), std::forward<Args>(aArgs)...);
303 else if constexpr (detail::is_smart_ptr_v<value_type> && !std::is_abstract_v<typename value_type::element_type>)
304 result =
items().insert(
items().end(),
value_type{
new typename value_type::element_type{std::forward<Args>(aArgs)...} });
307 allocated_cookies().insert(allocated_cookies().
end(), aCookie);
314 reverse_indices()[aCookie] =
items().size() - 1;
319 std::scoped_lock<mutex_type> lock{
mutex() };
324 std::scoped_lock<mutex_type> lock{
mutex() };
325 assert(std::find(free_cookies().
begin(), free_cookies().
end(), aCookie) == free_cookies().
end());
326 if (aCookie >= reverse_indices().
size())
328 auto& reverseIndex = reverse_indices()[aCookie];
329 if (reverseIndex == INVALID_REVERSE_INDEX)
333 auto& item =
items()[reverseIndex];
335 auto&
cookie = allocated_cookies()[reverseIndex];
337 reverse_indices()[
cookie] = reverseIndex;
339 auto resultIndex = reverseIndex;
340 reverseIndex = INVALID_REVERSE_INDEX;
341 allocated_cookies().pop_back();
349 if constexpr (!std::is_pointer_v<value_type>)
350 return allocated_cookies()[&
static_cast<value_type const&
>(aItem) - &
items()[0]];
356 std::scoped_lock<mutex_type> lock{
mutex() };
357 if (!free_cookies().
empty())
359 auto nextCookie = free_cookies().back();
360 free_cookies().pop_back();
363 auto nextCookie = ++iNextAvailableCookie;
364 if (nextCookie == INVALID_COOKIE)
366 assert(std::find(free_cookies().
begin(), free_cookies().
end(), nextCookie) == free_cookies().
end());
371 std::scoped_lock<mutex_type> lock{
mutex() };
372 assert(std::find(free_cookies().
begin(), free_cookies().
end(), aCookie) == free_cookies().
end());
373 free_cookies().push_back(aCookie);
382 return items().begin();
390 return items().begin();
394 return items().end();
402 return items().end();
407 std::scoped_lock<mutex_type> lock{
mutex() };
408 iNextAvailableCookie = 0ul;
409 allocated_cookies().clear();
410 free_cookies().clear();
412 reverse_indices().clear();
423 const cookies_t& allocated_cookies()
const
425 return iAllocatedCookies;
427 cookies_t& allocated_cookies()
429 return iAllocatedCookies;
431 const cookies_t& free_cookies()
const
435 cookies_t& free_cookies()
439 const reverse_indices_t& reverse_indices()
const
441 return iReverseIndices;
443 reverse_indices_t& reverse_indices()
445 return iReverseIndices;
449 mutable std::atomic<cookie_type> iNextAvailableCookie;
450 cookies_t iAllocatedCookies;
452 mutable cookies_t iFreeCookies;
453 reverse_indices_t iReverseIndices;
456 template <
typename T,
typename CookieType = cookie,
typename MutexType = null_mutex>
465 typedef typename container_type::iterator
iterator;
468 typedef typename container_type::size_type reverse_index_t;
469 typedef std::vector<reverse_index_t> reverse_indices_t;
470 typedef std::vector<cookie_type> cookies_t;
472 static constexpr cookie_type INVALID_COOKIE = invalid_cookie<cookie_type>;
473 static constexpr reverse_index_t INVALID_REVERSE_INDEX =
static_cast<reverse_index_t
>(~reverse_index_t{});
481 return items().empty();
485 return items().size();
489 std::scoped_lock<mutex_type> lock{
mutex() };
490 return aCookie < reverse_indices().size() && reverse_indices()[aCookie] != INVALID_REVERSE_INDEX;
494 std::scoped_lock<mutex_type> lock{
mutex() };
501 std::scoped_lock<mutex_type> lock{
mutex() };
508 std::scoped_lock<mutex_type> lock{
mutex() };
509 if (aCookie >= reverse_indices().
size())
511 auto reverseIndex = reverse_indices()[aCookie];
512 if (reverseIndex == INVALID_REVERSE_INDEX)
514 return items()[reverseIndex];
522 return items().at(aIndex);
526 return items().at(aIndex);
542 template <
typename... Args>
548 add(
cookie, std::forward<Args>(aArgs)...);
559 return add<const abstract_t<value_type>&>(aCookie, aItem);
565 template <
typename... Args>
568 std::scoped_lock<mutex_type> lock{
mutex() };
569 assert(std::find(free_cookies().
begin(), free_cookies().
end(), aCookie) == free_cookies().
end());
570 if (reverse_indices().
size() <= aCookie)
571 reverse_indices().insert(reverse_indices().
end(), (aCookie + 1) - reverse_indices().
size(), INVALID_REVERSE_INDEX);
572 if (reverse_indices()[aCookie] != INVALID_REVERSE_INDEX)
574 std::optional<iterator> result;
575 if constexpr (!detail::is_smart_ptr_v<value_type>)
576 result =
items().emplace(
items().end(), std::forward<Args>(aArgs)...);
577 else if constexpr (detail::is_smart_ptr_v<value_type> && std::is_abstract_v<typename value_type::element_type>)
578 result =
items().emplace(
items().end(), std::forward<Args>(aArgs)...);
579 else if constexpr (detail::is_smart_ptr_v<value_type> && !std::is_abstract_v<typename value_type::element_type>)
580 result =
items().insert(
items().end(),
value_type{
new typename value_type::element_type{std::forward<Args>(aArgs)...} });
583 allocated_cookies().insert(allocated_cookies().
end(), aCookie);
590 reverse_indices()[aCookie] =
items().size() - 1;
595 std::scoped_lock<mutex_type> lock{
mutex() };
600 std::scoped_lock<mutex_type> lock{
mutex() };
601 assert(std::find(free_cookies().
begin(), free_cookies().
end(), aCookie) == free_cookies().
end());
602 if (aCookie >= reverse_indices().
size())
604 auto& reverseIndex = reverse_indices()[aCookie];
605 if (reverseIndex == INVALID_REVERSE_INDEX)
609 auto& item =
items()[reverseIndex];
611 auto&
cookie = allocated_cookies()[reverseIndex];
613 reverse_indices()[
cookie] = reverseIndex;
615 auto resultIndex = reverseIndex;
616 reverseIndex = INVALID_REVERSE_INDEX;
617 allocated_cookies().pop_back();
625 if constexpr (!std::is_pointer_v<value_type>)
626 return allocated_cookies()[&
static_cast<value_type const&
>(aItem) - &
items()[0]];
632 std::scoped_lock<mutex_type> lock{
mutex() };
633 if (!free_cookies().
empty())
635 auto nextCookie = free_cookies().back();
636 free_cookies().pop_back();
639 auto nextCookie = ++iNextAvailableCookie;
640 if (nextCookie == INVALID_COOKIE)
642 assert(std::find(free_cookies().
begin(), free_cookies().
end(), nextCookie) == free_cookies().
end());
647 std::scoped_lock<mutex_type> lock{
mutex() };
648 assert(std::find(free_cookies().
begin(), free_cookies().
end(), aCookie) == free_cookies().
end());
649 free_cookies().push_back(aCookie);
658 return items().begin();
666 return items().begin();
670 return items().end();
678 return items().end();
683 std::scoped_lock<mutex_type> lock{
mutex() };
684 iNextAvailableCookie = 0ul;
685 allocated_cookies().clear();
686 free_cookies().clear();
688 reverse_indices().clear();
699 const cookies_t& allocated_cookies()
const
701 return iAllocatedCookies;
703 cookies_t& allocated_cookies()
705 return iAllocatedCookies;
707 const cookies_t& free_cookies()
const
711 cookies_t& free_cookies()
715 const reverse_indices_t& reverse_indices()
const
717 return iReverseIndices;
719 reverse_indices_t& reverse_indices()
721 return iReverseIndices;
725 mutable std::atomic<cookie_type> iNextAvailableCookie;
726 cookies_t iAllocatedCookies;
728 mutable cookies_t iFreeCookies;
729 reverse_indices_t iReverseIndices;
735 template <
typename T,
typename MutexType = null_mutex>
737 template <
typename T,
typename MutexType = null_mutex>
740 template <
typename T,
typename MutexType = null_mutex>
742 template <
typename T,
typename MutexType = null_mutex>
bool operator!=(basic_cookie_ref_ptr const &aRhs) const
bool operator==(basic_cookie_ref_ptr const &aRhs) const
static constexpr cookie_type no_cookie
basic_cookie_ref_ptr(i_basic_cookie_consumer< cookie_type > &aConsumer, cookie_type aCookie)
cookie_type cookie() const
basic_cookie_ref_ptr & operator=(basic_cookie_ref_ptr &&aOther)
basic_cookie_ref_ptr & operator=(basic_cookie_ref_ptr const &aOther)
basic_cookie_ref_ptr(basic_cookie_ref_ptr const &aOther)
basic_cookie_ref_ptr(basic_cookie_ref_ptr &&aOther)
bool operator<(basic_cookie_ref_ptr const &aRhs) const
void return_cookie(cookie_type aCookie) final
value_type & operator[](cookie_type aCookie) final
cookie_type next_cookie() final
iterator add(cookie_type aCookie, abstract_t< value_type > const &aItem) final
iterator add(cookie_type aCookie, Args &&... aArgs)
const container_type & items() const final
iterator remove(abstract_t< value_type > const &aItem) final
mutex_type & mutex() const
iterator find(cookie_type aCookie) final
const_iterator end() const final
iterator erase(const_iterator aItem) final
bool contains(cookie_type aCookie) const final
const_iterator find(cookie_type aCookie) const final
cookie_type insert(abstract_t< value_type > const &aItem) final
cookie_type emplace(Args &&... aArgs)
const value_type & at_index(std::size_t aIndex) const final
std::size_t size() const final
const value_type & operator[](cookie_type aCookie) const final
value_type & at_index(std::size_t aIndex) final
const_iterator begin() const final
container_type::iterator iterator
const_iterator cend() const final
cookie_type item_cookie(abstract_t< value_type > const &aItem) const final
const_iterator cbegin() const final
container_type::const_iterator const_iterator
container_type & items() final
iterator remove(cookie_type aCookie) final
const_iterator cend() const
iterator add(cookie_type aCookie, abstract_t< value_type > const &aItem)
const_iterator find(cookie_type aCookie) const
cookie_type item_cookie(abstract_t< value_type > const &aItem) const
value_type & at_index(std::size_t aIndex)
iterator add(cookie_type aCookie, Args &&... aArgs)
const_iterator end() const
bool contains(cookie_type aCookie) const
iterator remove(cookie_type aCookie)
const_iterator cbegin() const
const container_type & items() const
std::vector< value_type > container_type
value_type & operator[](cookie_type aCookie)
const_iterator begin() const
container_type::const_iterator const_iterator
mutex_type & mutex() const
cookie_type insert(abstract_t< value_type > const &aItem)
iterator find(cookie_type aCookie)
const value_type & at_index(std::size_t aIndex) const
const value_type & operator[](cookie_type aCookie) const
cookie_type next_cookie()
void return_cookie(cookie_type aCookie)
iterator erase(const_iterator aItem)
container_type::iterator iterator
iterator remove(abstract_t< value_type > const &aItem)
cookie_type emplace(Args &&... aArgs)
virtual void release(cookie_type aCookie)=0
virtual void add_ref(cookie_type aCookie)=0
typename detail::abstract_type< T >::type abstract_t
basic_vector_jar< T, cookie, MutexType > vector_jar
void swap(any &aLhs, any &aRhs)
basic_cookie_ref_ptr< small_cookie > small_cookie_ref_ptr
basic_jar< T, vector< T >, cookie, MutexType > jar
basic_cookie_ref_ptr< cookie > cookie_ref_ptr
to_const_reference_t< T > to_const(T &&object)
basic_jar< T, vector< T >, small_cookie, MutexType > small_jar
basic_vector_jar< T, small_cookie, MutexType > small_vector_jar
void swap(plf::hive< element_type, allocator_type > &a, plf::hive< element_type, allocator_type > &b) noexcept(std::allocator_traits< allocator_type >::propagate_on_container_swap::value||std::allocator_traits< allocator_type >::is_always_equal::value)
it_type next(it_type it, const typename iterator_traits< it_type >::difference_type distance=1)