Cleanups and codestyle for the godot4 containers that I added in unmodified yesterday.

This commit is contained in:
Relintai 2023-01-16 22:09:32 +01:00
parent 0a79f38843
commit d999f63cbd
4 changed files with 41 additions and 25 deletions

View File

@ -31,8 +31,8 @@
#ifndef BIN_SORTED_ARRAY_H #ifndef BIN_SORTED_ARRAY_H
#define BIN_SORTED_ARRAY_H #define BIN_SORTED_ARRAY_H
#include "core/templates/local_vector.h" #include "core/containers/local_vector.h"
#include "core/templates/paged_array.h" #include "core/containers/paged_array.h"
template <class T> template <class T>
class BinSortedArray { class BinSortedArray {

View File

@ -35,8 +35,6 @@
#include "core/os/spin_lock.h" #include "core/os/spin_lock.h"
#include "core/typedefs.h" #include "core/typedefs.h"
#include <type_traits>
// PagedArray is used mainly for filling a very large array from multiple threads efficiently and without causing major fragmentation // 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 // PageArrayPool manages central page allocation in a thread safe matter
@ -199,7 +197,7 @@ public:
uint32_t page = count >> page_size_shift; uint32_t page = count >> page_size_shift;
uint32_t offset = count & page_size_mask; uint32_t offset = count & page_size_mask;
if (!std::is_trivially_constructible<T>::value) { if (!__has_trivial_constructor(T)) {
memnew_placement(&page_data[page][offset], T(p_value)); memnew_placement(&page_data[page][offset], T(p_value));
} else { } else {
page_data[page][offset] = p_value; page_data[page][offset] = p_value;
@ -211,7 +209,7 @@ public:
_FORCE_INLINE_ void pop_back() { _FORCE_INLINE_ void pop_back() {
ERR_FAIL_COND(count == 0); ERR_FAIL_COND(count == 0);
if (!std::is_trivially_destructible<T>::value) { if (!__has_trivial_destructor(T)) {
uint32_t page = (count - 1) >> page_size_shift; uint32_t page = (count - 1) >> page_size_shift;
uint32_t offset = (count - 1) & page_size_mask; uint32_t offset = (count - 1) & page_size_mask;
page_data[page][offset].~T(); page_data[page][offset].~T();
@ -228,7 +226,7 @@ public:
void clear() { void clear() {
//destruct if needed //destruct if needed
if (!std::is_trivially_destructible<T>::value) { if (!__has_trivial_destructor(T)) {
for (uint64_t i = 0; i < count; i++) { for (uint64_t i = 0; i < count; i++) {
uint32_t page = i >> page_size_shift; uint32_t page = i >> page_size_shift;
uint32_t offset = i & page_size_mask; uint32_t offset = i & page_size_mask;
@ -311,13 +309,13 @@ public:
uint32_t to_copy = MIN(page_size - new_remainder, remainder); uint32_t to_copy = MIN(page_size - new_remainder, remainder);
for (uint32_t i = 0; i < to_copy; i++) { for (uint32_t i = 0; i < to_copy; i++) {
if (!std::is_trivially_constructible<T>::value) { if (!__has_trivial_constructor(T)) {
memnew_placement(&dst_page[i + new_remainder], T(remainder_page[i + remainder - to_copy])); memnew_placement(&dst_page[i + new_remainder], T(remainder_page[i + remainder - to_copy]));
} else { } else {
dst_page[i + new_remainder] = remainder_page[i + remainder - to_copy]; dst_page[i + new_remainder] = remainder_page[i + remainder - to_copy];
} }
if (!std::is_trivially_destructible<T>::value) { if (!__has_trivial_destructor(T)) {
remainder_page[i + remainder - to_copy].~T(); remainder_page[i + remainder - to_copy].~T();
} }
} }

View File

@ -57,33 +57,41 @@ class SafeList {
// to the previous list item in time that was also logically deleted. // to the previous list item in time that was also logically deleted.
std::atomic<SafeListNode *> graveyard_next = nullptr; std::atomic<SafeListNode *> graveyard_next = nullptr;
std::function<void(T)> deletion_fn = [](T t) { return; }; void (*deletion_fn)(T t);
T val; T val;
static void default_deletion_fn(T) {}
SafeListNode() {
next = NULL;
graveyard_next = NULL;
deletion_fn = default_deletion_fn;
}
}; };
static_assert(std::atomic<T>::is_always_lock_free); std::atomic<SafeListNode *> head;
std::atomic<SafeListNode *> graveyard_head;
std::atomic<SafeListNode *> head = nullptr; std::atomic<uint32_t> active_iterator_count;
std::atomic<SafeListNode *> graveyard_head = nullptr;
std::atomic_uint active_iterator_count = 0;
public: public:
class Iterator { class Iterator {
friend class SafeList; friend class SafeList;
SafeListNode *cursor = nullptr; SafeListNode *cursor;
SafeList *list = nullptr; SafeList *list;
Iterator(SafeListNode *p_cursor, SafeList *p_list) : Iterator(SafeListNode *p_cursor, SafeList *p_list) {
cursor(p_cursor), list(p_list) { cursor = p_cursor;
list = p_list;
list->active_iterator_count++; list->active_iterator_count++;
} }
public: public:
Iterator(const Iterator &p_other) : Iterator(const Iterator &p_other) {
cursor(p_other.cursor), list(p_other.list) { cursor = p_other.cursor;
list = p_other.list;
list->active_iterator_count++; list->active_iterator_count++;
} }
@ -197,13 +205,14 @@ public:
} }
Iterator end() { Iterator end() {
return Iterator(nullptr, this); return Iterator(NULL, this);
} }
// Calling this will cause zero to many deallocations. // Calling this will cause zero to many deallocations.
bool maybe_cleanup() { bool maybe_cleanup() {
SafeListNode *cursor = nullptr; SafeListNode *cursor = NULL;
SafeListNode *new_graveyard_head = nullptr; SafeListNode *new_graveyard_head = NULL;
do { do {
// The access order here is theoretically important. // The access order here is theoretically important.
cursor = graveyard_head.load(); cursor = graveyard_head.load();
@ -215,6 +224,7 @@ public:
// Any iterator created after this point will never point to a deleted node. // Any iterator created after this point will never point to a deleted node.
// Swap it out with the current graveyard head. // Swap it out with the current graveyard head.
} while (!graveyard_head.compare_exchange_strong(/* expected= */ cursor, /* new= */ new_graveyard_head)); } while (!graveyard_head.compare_exchange_strong(/* expected= */ cursor, /* new= */ new_graveyard_head));
// Our graveyard list is now unreachable by any active iterators, // Our graveyard list is now unreachable by any active iterators,
// detached from the main graveyard head and ready for deletion. // detached from the main graveyard head and ready for deletion.
while (cursor) { while (cursor) {
@ -223,9 +233,17 @@ public:
tmp->deletion_fn(tmp->val); tmp->deletion_fn(tmp->val);
memdelete_allocator<SafeListNode, A>(tmp); memdelete_allocator<SafeListNode, A>(tmp);
} }
return true; return true;
} }
SafeList() {
head = NULL;
graveyard_head = NULL;
active_iterator_count = 0;
}
~SafeList() { ~SafeList() {
#ifdef DEBUG_ENABLED #ifdef DEBUG_ENABLED
if (!maybe_cleanup()) { if (!maybe_cleanup()) {

View File

@ -31,7 +31,7 @@
#ifndef SEARCH_ARRAY_H #ifndef SEARCH_ARRAY_H
#define SEARCH_ARRAY_H #define SEARCH_ARRAY_H
#include <core/templates/sort_array.h> #include "sort_array.h"
template <class T, class Comparator = _DefaultComparator<T>> template <class T, class Comparator = _DefaultComparator<T>>
class SearchArray { class SearchArray {