made GObjects generic with respect to the object type

This commit is contained in:
Janis 2023-04-22 01:19:15 +02:00
parent 3be8219eca
commit 720065242c

View file

@ -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>,