mirror of
https://github.com/Relintai/pandemonium_engine.git
synced 2024-12-22 11:56:49 +01:00
Cleanups and codestyle for the godot4 containers that I added in unmodified yesterday.
This commit is contained in:
parent
0a79f38843
commit
d999f63cbd
@ -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 T>
|
||||
class BinSortedArray {
|
||||
|
@ -35,8 +35,6 @@
|
||||
#include "core/os/spin_lock.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
|
||||
|
||||
// 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<T>::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<T>::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<T>::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<T>::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<T>::value) {
|
||||
if (!__has_trivial_destructor(T)) {
|
||||
remainder_page[i + remainder - to_copy].~T();
|
||||
}
|
||||
}
|
||||
|
@ -57,33 +57,41 @@ class SafeList {
|
||||
// to the previous list item in time that was also logically deleted.
|
||||
std::atomic<SafeListNode *> graveyard_next = nullptr;
|
||||
|
||||
std::function<void(T)> 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<T>::is_always_lock_free);
|
||||
std::atomic<SafeListNode *> head;
|
||||
std::atomic<SafeListNode *> graveyard_head;
|
||||
|
||||
std::atomic<SafeListNode *> head = nullptr;
|
||||
std::atomic<SafeListNode *> graveyard_head = nullptr;
|
||||
|
||||
std::atomic_uint active_iterator_count = 0;
|
||||
std::atomic<uint32_t> 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<SafeListNode, A>(tmp);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SafeList() {
|
||||
head = NULL;
|
||||
graveyard_head = NULL;
|
||||
|
||||
active_iterator_count = 0;
|
||||
}
|
||||
|
||||
~SafeList() {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (!maybe_cleanup()) {
|
||||
|
@ -31,7 +31,7 @@
|
||||
#ifndef SEARCH_ARRAY_H
|
||||
#define SEARCH_ARRAY_H
|
||||
|
||||
#include <core/templates/sort_array.h>
|
||||
#include "sort_array.h"
|
||||
|
||||
template <class T, class Comparator = _DefaultComparator<T>>
|
||||
class SearchArray {
|
||||
|
Loading…
Reference in New Issue
Block a user