diff --git a/core/containers/bin_sorted_array.h b/core/containers/bin_sorted_array.h index 500d1f137..6712e0c84 100644 --- a/core/containers/bin_sorted_array.h +++ b/core/containers/bin_sorted_array.h @@ -31,8 +31,8 @@ #ifndef BIN_SORTED_ARRAY_H #define BIN_SORTED_ARRAY_H -#include "core/templates/local_vector.h" -#include "core/templates/paged_array.h" +#include "core/containers/local_vector.h" +#include "core/containers/paged_array.h" template class BinSortedArray { diff --git a/core/containers/paged_array.h b/core/containers/paged_array.h index c447b5af6..7e589a696 100644 --- a/core/containers/paged_array.h +++ b/core/containers/paged_array.h @@ -35,8 +35,6 @@ #include "core/os/spin_lock.h" #include "core/typedefs.h" -#include - // PagedArray is used mainly for filling a very large array from multiple threads efficiently and without causing major fragmentation // PageArrayPool manages central page allocation in a thread safe matter @@ -199,7 +197,7 @@ public: uint32_t page = count >> page_size_shift; uint32_t offset = count & page_size_mask; - if (!std::is_trivially_constructible::value) { + if (!__has_trivial_constructor(T)) { memnew_placement(&page_data[page][offset], T(p_value)); } else { page_data[page][offset] = p_value; @@ -211,7 +209,7 @@ public: _FORCE_INLINE_ void pop_back() { ERR_FAIL_COND(count == 0); - if (!std::is_trivially_destructible::value) { + if (!__has_trivial_destructor(T)) { uint32_t page = (count - 1) >> page_size_shift; uint32_t offset = (count - 1) & page_size_mask; page_data[page][offset].~T(); @@ -228,7 +226,7 @@ public: void clear() { //destruct if needed - if (!std::is_trivially_destructible::value) { + if (!__has_trivial_destructor(T)) { for (uint64_t i = 0; i < count; i++) { uint32_t page = i >> page_size_shift; uint32_t offset = i & page_size_mask; @@ -311,13 +309,13 @@ public: uint32_t to_copy = MIN(page_size - new_remainder, remainder); for (uint32_t i = 0; i < to_copy; i++) { - if (!std::is_trivially_constructible::value) { + if (!__has_trivial_constructor(T)) { memnew_placement(&dst_page[i + new_remainder], T(remainder_page[i + remainder - to_copy])); } else { dst_page[i + new_remainder] = remainder_page[i + remainder - to_copy]; } - if (!std::is_trivially_destructible::value) { + if (!__has_trivial_destructor(T)) { remainder_page[i + remainder - to_copy].~T(); } } diff --git a/core/containers/safe_list.h b/core/containers/safe_list.h index 79457db24..c78ccf559 100644 --- a/core/containers/safe_list.h +++ b/core/containers/safe_list.h @@ -57,33 +57,41 @@ class SafeList { // to the previous list item in time that was also logically deleted. std::atomic graveyard_next = nullptr; - std::function deletion_fn = [](T t) { return; }; + void (*deletion_fn)(T t); T val; + + static void default_deletion_fn(T) {} + + SafeListNode() { + next = NULL; + graveyard_next = NULL; + deletion_fn = default_deletion_fn; + } }; - static_assert(std::atomic::is_always_lock_free); + std::atomic head; + std::atomic graveyard_head; - std::atomic head = nullptr; - std::atomic graveyard_head = nullptr; - - std::atomic_uint active_iterator_count = 0; + std::atomic active_iterator_count; public: class Iterator { friend class SafeList; - SafeListNode *cursor = nullptr; - SafeList *list = nullptr; + SafeListNode *cursor; + SafeList *list; - Iterator(SafeListNode *p_cursor, SafeList *p_list) : - cursor(p_cursor), list(p_list) { + Iterator(SafeListNode *p_cursor, SafeList *p_list) { + cursor = p_cursor; + list = p_list; list->active_iterator_count++; } public: - Iterator(const Iterator &p_other) : - cursor(p_other.cursor), list(p_other.list) { + Iterator(const Iterator &p_other) { + cursor = p_other.cursor; + list = p_other.list; list->active_iterator_count++; } @@ -197,13 +205,14 @@ public: } Iterator end() { - return Iterator(nullptr, this); + return Iterator(NULL, this); } // Calling this will cause zero to many deallocations. bool maybe_cleanup() { - SafeListNode *cursor = nullptr; - SafeListNode *new_graveyard_head = nullptr; + SafeListNode *cursor = NULL; + SafeListNode *new_graveyard_head = NULL; + do { // The access order here is theoretically important. cursor = graveyard_head.load(); @@ -215,6 +224,7 @@ public: // Any iterator created after this point will never point to a deleted node. // Swap it out with the current graveyard head. } while (!graveyard_head.compare_exchange_strong(/* expected= */ cursor, /* new= */ new_graveyard_head)); + // Our graveyard list is now unreachable by any active iterators, // detached from the main graveyard head and ready for deletion. while (cursor) { @@ -223,9 +233,17 @@ public: tmp->deletion_fn(tmp->val); memdelete_allocator(tmp); } + return true; } + SafeList() { + head = NULL; + graveyard_head = NULL; + + active_iterator_count = 0; + } + ~SafeList() { #ifdef DEBUG_ENABLED if (!maybe_cleanup()) { diff --git a/core/containers/search_array.h b/core/containers/search_array.h index f537ef67f..60cbdd362 100644 --- a/core/containers/search_array.h +++ b/core/containers/search_array.h @@ -31,7 +31,7 @@ #ifndef SEARCH_ARRAY_H #define SEARCH_ARRAY_H -#include +#include "sort_array.h" template > class SearchArray {