made GObjects generic with respect to the object type
This commit is contained in:
parent
3be8219eca
commit
720065242c
|
@ -1,74 +1,82 @@
|
||||||
use std::{cell::UnsafeCell, ops::Index, ptr::NonNull, sync::RwLock};
|
use std::{cell::UnsafeCell, ops::Index, ptr::NonNull, sync::RwLock};
|
||||||
|
|
||||||
use rayon::prelude::ParallelIterator;
|
use crate::v2_types::{self, traits::AsUObject};
|
||||||
|
|
||||||
use crate::v2_types::{
|
|
||||||
self,
|
|
||||||
traits::{AsUObject, UObjectTrait},
|
|
||||||
};
|
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
pub static ref GOBJECTS: RwLock<GObjects> = RwLock::new(GObjects::new());
|
pub static ref GOBJECTS: RwLock<GObjects<v2_types::UObject>> = RwLock::new(GObjects::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct GObjects {
|
pub struct GObjects<Object: Sized> {
|
||||||
objects: Option<NonNull<UnsafeCell<ObjectArray>>>,
|
objects: Option<NonNull<UnsafeCell<ObjectArray<Object>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GObjects {
|
impl<Object> GObjects<Object>
|
||||||
|
where
|
||||||
|
Object: Sized,
|
||||||
|
{
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self { objects: None }
|
Self { objects: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_objects(&mut self, objects: NonNull<ObjectArray>) {
|
pub fn set_objects(&mut self, objects: NonNull<ObjectArray<Object>>) {
|
||||||
self.objects = Some(objects.cast());
|
self.objects = Some(objects.cast());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_objects(&self) -> Option<&ObjectArray> {
|
pub fn as_objects(&self) -> Option<&ObjectArray<Object>> {
|
||||||
self.objects
|
self.objects
|
||||||
.map(|objects| unsafe { &*objects.as_ref().get() })
|
.map(|objects| unsafe { &*objects.as_ref().get() })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for GObjects {}
|
unsafe impl<Object: Sized> Send for GObjects<Object> {}
|
||||||
unsafe impl Sync for GObjects {}
|
unsafe impl<Object: Sized> Sync for GObjects<Object> {}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ObjectArrayItem {
|
pub struct ObjectArrayItem<Object: Sized> {
|
||||||
object: Option<v2_types::UObject>,
|
object: Option<Object>,
|
||||||
sn: u32,
|
sn: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for ObjectArrayItem {}
|
unsafe impl<Object: Sized> Send for ObjectArrayItem<Object> {}
|
||||||
unsafe impl Sync for ObjectArrayItem {}
|
unsafe impl<Object: Sized> Sync for ObjectArrayItem<Object> {}
|
||||||
|
|
||||||
impl ObjectArrayItem {
|
impl<Object> ObjectArrayItem<Object>
|
||||||
pub fn object(&self) -> Option<v2_types::UObject> {
|
where
|
||||||
|
Object: Sized,
|
||||||
|
{
|
||||||
|
pub fn object(&self) -> Option<Object>
|
||||||
|
where
|
||||||
|
Object: Copy,
|
||||||
|
{
|
||||||
self.object
|
self.object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_object(&self) -> &Option<Object> {
|
||||||
|
&self.object
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ObjectArrayInner {
|
pub struct ObjectArrayInner<Object: Sized> {
|
||||||
objects: NonNull<Option<NonNull<ObjectArrayItem>>>,
|
objects: NonNull<Option<NonNull<ObjectArrayItem<Object>>>>,
|
||||||
pre_allocated_objects: Option<NonNull<ObjectArrayItem>>,
|
pre_allocated_objects: Option<NonNull<ObjectArrayItem<Object>>>,
|
||||||
max_elements: u32,
|
max_elements: u32,
|
||||||
num_elements: u32,
|
num_elements: u32,
|
||||||
max_chunks: u32,
|
max_chunks: u32,
|
||||||
num_chunks: u32,
|
num_chunks: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectArrayInner {
|
impl<Object: Sized> ObjectArrayInner<Object> {
|
||||||
const ELEMENTS_PER_CHUNK: usize = 64 * 1024;
|
const ELEMENTS_PER_CHUNK: usize = 64 * 1024;
|
||||||
|
|
||||||
fn chunks_as_slice(&self) -> &[Option<NonNull<ObjectArrayItem>>] {
|
fn chunks_as_slice(&self) -> &[Option<NonNull<ObjectArrayItem<Object>>>] {
|
||||||
unsafe { std::slice::from_raw_parts(self.objects.as_ptr(), self.num_chunks as usize) }
|
unsafe { std::slice::from_raw_parts(self.objects.as_ptr(), self.num_chunks as usize) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_chunks(&self) -> Vec<&[ObjectArrayItem]> {
|
pub fn get_chunks(&self) -> Vec<&[ObjectArrayItem<Object>]> {
|
||||||
(0..self.num_chunks as usize)
|
(0..self.num_chunks as usize)
|
||||||
.filter_map(|i| self.chunk_as_slice(i))
|
.filter_map(|i| self.chunk_as_slice(i))
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -86,7 +94,7 @@ impl ObjectArrayInner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn chunk_as_slice(&self, chunk_index: usize) -> Option<&[ObjectArrayItem]> {
|
fn chunk_as_slice(&self, chunk_index: usize) -> Option<&[ObjectArrayItem<Object>]> {
|
||||||
let chunks = self.chunks_as_slice();
|
let chunks = self.chunks_as_slice();
|
||||||
let chunk = unsafe {
|
let chunk = unsafe {
|
||||||
chunks[chunk_index].map(|ptr| {
|
chunks[chunk_index].map(|ptr| {
|
||||||
|
@ -109,7 +117,7 @@ impl ObjectArrayInner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_index(&self, i: usize) -> Option<&ObjectArrayItem> {
|
pub fn get_index(&self, i: usize) -> Option<&ObjectArrayItem<Object>> {
|
||||||
if let Some((chunk, within_chunk)) = self.get_chunked_index(i) {
|
if let Some((chunk, within_chunk)) = self.get_chunked_index(i) {
|
||||||
self.chunk_as_slice(chunk)?.get(within_chunk)
|
self.chunk_as_slice(chunk)?.get(within_chunk)
|
||||||
} else {
|
} else {
|
||||||
|
@ -120,43 +128,33 @@ impl ObjectArrayInner {
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ObjectArray {
|
pub struct ObjectArray<Object: Sized> {
|
||||||
first_gc_index: u32,
|
first_gc_index: u32,
|
||||||
last_non_gc_index: u32,
|
last_non_gc_index: u32,
|
||||||
max_objects_not_considered_by_gc: u32,
|
max_objects_not_considered_by_gc: u32,
|
||||||
open_for_disregard_for_gc: bool,
|
open_for_disregard_for_gc: bool,
|
||||||
inner: ObjectArrayInner,
|
inner: ObjectArrayInner<Object>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for ObjectArray {}
|
unsafe impl<Object: Sized> Send for ObjectArray<Object> {}
|
||||||
unsafe impl Sync for ObjectArray {}
|
unsafe impl<Object: Sized> Sync for ObjectArray<Object> {}
|
||||||
|
|
||||||
impl ObjectArray {
|
impl<Object: Sized> ObjectArray<Object> {
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.inner.num_elements as usize
|
self.inner.num_elements as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter(&self) -> iter::ObjectArrayIterator<'_> {
|
pub fn iter(&self) -> iter::ObjectArrayIterator<'_, Object> {
|
||||||
iter::ObjectArrayIterator::new(self)
|
iter::ObjectArrayIterator::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_package_objects(&self) -> impl Iterator<Item = &'_ ObjectArrayItem> {
|
pub fn par_iter(&self) -> par_iter::ObjectArrayChunkedParallelIterator<'_, Object> {
|
||||||
self.iter()
|
|
||||||
.filter(|entry| matches!(entry.object(), Some(object) if object.is_package_object()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn par_iter(&self) -> par_iter::ObjectArrayChunkedParallelIterator<'_> {
|
|
||||||
par_iter::ObjectArrayChunkedParallelIterator::new(self.inner.get_chunks())
|
par_iter::ObjectArrayChunkedParallelIterator::new(self.inner.get_chunks())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn par_iter_package_objects(&self) -> impl ParallelIterator<Item = &'_ ObjectArrayItem> {
|
|
||||||
self.par_iter()
|
|
||||||
.filter(|entry| matches!(entry.object(), Some(object) if object.is_package_object()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Index<usize> for ObjectArray {
|
impl<Object> Index<usize> for ObjectArray<Object> {
|
||||||
type Output = ObjectArrayItem;
|
type Output = ObjectArrayItem<Object>;
|
||||||
|
|
||||||
fn index(&self, i: usize) -> &Self::Output {
|
fn index(&self, i: usize) -> &Self::Output {
|
||||||
self.inner.get_index(i).expect("Out of bounds access")
|
self.inner.get_index(i).expect("Out of bounds access")
|
||||||
|
@ -166,19 +164,28 @@ impl Index<usize> for ObjectArray {
|
||||||
pub mod iter {
|
pub mod iter {
|
||||||
use super::{ObjectArray, ObjectArrayItem};
|
use super::{ObjectArray, ObjectArrayItem};
|
||||||
|
|
||||||
pub struct ObjectArrayIterator<'a> {
|
pub struct ObjectArrayIterator<'a, Object>
|
||||||
objects: &'a ObjectArray,
|
where
|
||||||
|
Object: Sized,
|
||||||
|
{
|
||||||
|
objects: &'a ObjectArray<Object>,
|
||||||
index: usize,
|
index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ObjectArrayIterator<'a> {
|
impl<'a, Object> ObjectArrayIterator<'a, Object>
|
||||||
pub(super) fn new(objects: &'a ObjectArray) -> Self {
|
where
|
||||||
|
Object: Sized,
|
||||||
|
{
|
||||||
|
pub(super) fn new(objects: &'a ObjectArray<Object>) -> Self {
|
||||||
Self { objects, index: 0 }
|
Self { objects, index: 0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for ObjectArrayIterator<'a> {
|
impl<'a, Object> Iterator for ObjectArrayIterator<'a, Object>
|
||||||
type Item = &'a ObjectArrayItem;
|
where
|
||||||
|
Object: Sized,
|
||||||
|
{
|
||||||
|
type Item = &'a ObjectArrayItem<Object>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let item = if self.index < self.objects.len() {
|
let item = if self.index < self.objects.len() {
|
||||||
|
@ -193,9 +200,12 @@ pub mod iter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> IntoIterator for &'a ObjectArray {
|
impl<'a, Object> IntoIterator for &'a ObjectArray<Object>
|
||||||
type Item = &'a ObjectArrayItem;
|
where
|
||||||
type IntoIter = ObjectArrayIterator<'a>;
|
Object: Sized,
|
||||||
|
{
|
||||||
|
type Item = &'a ObjectArrayItem<Object>;
|
||||||
|
type IntoIter = ObjectArrayIterator<'a, Object>;
|
||||||
|
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
ObjectArrayIterator {
|
ObjectArrayIterator {
|
||||||
|
@ -211,18 +221,27 @@ pub mod par_iter {
|
||||||
|
|
||||||
use super::ObjectArrayItem;
|
use super::ObjectArrayItem;
|
||||||
|
|
||||||
pub struct ObjectArrayChunkedParallelIterator<'a> {
|
pub struct ObjectArrayChunkedParallelIterator<'a, Object>
|
||||||
chunks: Vec<&'a [ObjectArrayItem]>,
|
where
|
||||||
|
Object: Sized,
|
||||||
|
{
|
||||||
|
chunks: Vec<&'a [ObjectArrayItem<Object>]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ObjectArrayChunkedParallelIterator<'a> {
|
impl<'a, Object> ObjectArrayChunkedParallelIterator<'a, Object>
|
||||||
pub fn new(chunks: Vec<&'a [ObjectArrayItem]>) -> Self {
|
where
|
||||||
|
Object: Sized,
|
||||||
|
{
|
||||||
|
pub fn new(chunks: Vec<&'a [ObjectArrayItem<Object>]>) -> Self {
|
||||||
Self { chunks }
|
Self { chunks }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ParallelIterator for ObjectArrayChunkedParallelIterator<'a> {
|
impl<'a, Object> ParallelIterator for ObjectArrayChunkedParallelIterator<'a, Object>
|
||||||
type Item = &'a ObjectArrayItem;
|
where
|
||||||
|
Object: Sized,
|
||||||
|
{
|
||||||
|
type Item = &'a ObjectArrayItem<Object>;
|
||||||
|
|
||||||
fn drive_unindexed<C>(self, consumer: C) -> C::Result
|
fn drive_unindexed<C>(self, consumer: C) -> C::Result
|
||||||
where
|
where
|
||||||
|
@ -242,7 +261,7 @@ pub trait FindClass {
|
||||||
S: Into<String>;
|
S: Into<String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FindClass for ObjectArray {
|
impl FindClass for ObjectArray<v2_types::UObject> {
|
||||||
fn find_class<S>(&self, class_name: S) -> Option<v2_types::UClass>
|
fn find_class<S>(&self, class_name: S) -> Option<v2_types::UClass>
|
||||||
where
|
where
|
||||||
S: Into<String>,
|
S: Into<String>,
|
||||||
|
|
Loading…
Reference in a new issue