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 rayon::prelude::ParallelIterator;
use crate::v2_types::{
self,
traits::{AsUObject, UObjectTrait},
};
use crate::v2_types::{self, traits::AsUObject};
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)]
pub struct GObjects {
objects: Option<NonNull<UnsafeCell<ObjectArray>>>,
pub struct GObjects<Object: Sized> {
objects: Option<NonNull<UnsafeCell<ObjectArray<Object>>>>,
}
impl GObjects {
impl<Object> GObjects<Object>
where
Object: Sized,
{
pub const fn new() -> Self {
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());
}
pub fn as_objects(&self) -> Option<&ObjectArray> {
pub fn as_objects(&self) -> Option<&ObjectArray<Object>> {
self.objects
.map(|objects| unsafe { &*objects.as_ref().get() })
}
}
unsafe impl Send for GObjects {}
unsafe impl Sync for GObjects {}
unsafe impl<Object: Sized> Send for GObjects<Object> {}
unsafe impl<Object: Sized> Sync for GObjects<Object> {}
#[repr(C)]
#[derive(Debug)]
pub struct ObjectArrayItem {
object: Option<v2_types::UObject>,
pub struct ObjectArrayItem<Object: Sized> {
object: Option<Object>,
sn: u32,
}
unsafe impl Send for ObjectArrayItem {}
unsafe impl Sync for ObjectArrayItem {}
unsafe impl<Object: Sized> Send for ObjectArrayItem<Object> {}
unsafe impl<Object: Sized> Sync for ObjectArrayItem<Object> {}
impl ObjectArrayItem {
pub fn object(&self) -> Option<v2_types::UObject> {
impl<Object> ObjectArrayItem<Object>
where
Object: Sized,
{
pub fn object(&self) -> Option<Object>
where
Object: Copy,
{
self.object
}
pub fn get_object(&self) -> &Option<Object> {
&self.object
}
}
#[repr(C)]
#[derive(Debug)]
pub struct ObjectArrayInner {
objects: NonNull<Option<NonNull<ObjectArrayItem>>>,
pre_allocated_objects: Option<NonNull<ObjectArrayItem>>,
pub struct ObjectArrayInner<Object: Sized> {
objects: NonNull<Option<NonNull<ObjectArrayItem<Object>>>>,
pre_allocated_objects: Option<NonNull<ObjectArrayItem<Object>>>,
max_elements: u32,
num_elements: u32,
max_chunks: u32,
num_chunks: u32,
}
impl ObjectArrayInner {
impl<Object: Sized> ObjectArrayInner<Object> {
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) }
}
pub fn get_chunks(&self) -> Vec<&[ObjectArrayItem]> {
pub fn get_chunks(&self) -> Vec<&[ObjectArrayItem<Object>]> {
(0..self.num_chunks as usize)
.filter_map(|i| self.chunk_as_slice(i))
.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 chunk = unsafe {
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) {
self.chunk_as_slice(chunk)?.get(within_chunk)
} else {
@ -120,43 +128,33 @@ impl ObjectArrayInner {
#[repr(C)]
#[derive(Debug)]
pub struct ObjectArray {
pub struct ObjectArray<Object: Sized> {
first_gc_index: u32,
last_non_gc_index: u32,
max_objects_not_considered_by_gc: u32,
open_for_disregard_for_gc: bool,
inner: ObjectArrayInner,
inner: ObjectArrayInner<Object>,
}
unsafe impl Send for ObjectArray {}
unsafe impl Sync for ObjectArray {}
unsafe impl<Object: Sized> Send for ObjectArray<Object> {}
unsafe impl<Object: Sized> Sync for ObjectArray<Object> {}
impl ObjectArray {
impl<Object: Sized> ObjectArray<Object> {
pub fn len(&self) -> usize {
self.inner.num_elements as usize
}
pub fn iter(&self) -> iter::ObjectArrayIterator<'_> {
pub fn iter(&self) -> iter::ObjectArrayIterator<'_, Object> {
iter::ObjectArrayIterator::new(self)
}
pub fn iter_package_objects(&self) -> impl Iterator<Item = &'_ ObjectArrayItem> {
self.iter()
.filter(|entry| matches!(entry.object(), Some(object) if object.is_package_object()))
}
pub fn par_iter(&self) -> par_iter::ObjectArrayChunkedParallelIterator<'_> {
pub fn par_iter(&self) -> par_iter::ObjectArrayChunkedParallelIterator<'_, Object> {
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 {
type Output = ObjectArrayItem;
impl<Object> Index<usize> for ObjectArray<Object> {
type Output = ObjectArrayItem<Object>;
fn index(&self, i: usize) -> &Self::Output {
self.inner.get_index(i).expect("Out of bounds access")
@ -166,19 +164,28 @@ impl Index<usize> for ObjectArray {
pub mod iter {
use super::{ObjectArray, ObjectArrayItem};
pub struct ObjectArrayIterator<'a> {
objects: &'a ObjectArray,
pub struct ObjectArrayIterator<'a, Object>
where
Object: Sized,
{
objects: &'a ObjectArray<Object>,
index: usize,
}
impl<'a> ObjectArrayIterator<'a> {
pub(super) fn new(objects: &'a ObjectArray) -> Self {
impl<'a, Object> ObjectArrayIterator<'a, Object>
where
Object: Sized,
{
pub(super) fn new(objects: &'a ObjectArray<Object>) -> Self {
Self { objects, index: 0 }
}
}
impl<'a> Iterator for ObjectArrayIterator<'a> {
type Item = &'a ObjectArrayItem;
impl<'a, Object> Iterator for ObjectArrayIterator<'a, Object>
where
Object: Sized,
{
type Item = &'a ObjectArrayItem<Object>;
fn next(&mut self) -> Option<Self::Item> {
let item = if self.index < self.objects.len() {
@ -193,9 +200,12 @@ pub mod iter {
}
}
impl<'a> IntoIterator for &'a ObjectArray {
type Item = &'a ObjectArrayItem;
type IntoIter = ObjectArrayIterator<'a>;
impl<'a, Object> IntoIterator for &'a ObjectArray<Object>
where
Object: Sized,
{
type Item = &'a ObjectArrayItem<Object>;
type IntoIter = ObjectArrayIterator<'a, Object>;
fn into_iter(self) -> Self::IntoIter {
ObjectArrayIterator {
@ -211,18 +221,27 @@ pub mod par_iter {
use super::ObjectArrayItem;
pub struct ObjectArrayChunkedParallelIterator<'a> {
chunks: Vec<&'a [ObjectArrayItem]>,
pub struct ObjectArrayChunkedParallelIterator<'a, Object>
where
Object: Sized,
{
chunks: Vec<&'a [ObjectArrayItem<Object>]>,
}
impl<'a> ObjectArrayChunkedParallelIterator<'a> {
pub fn new(chunks: Vec<&'a [ObjectArrayItem]>) -> Self {
impl<'a, Object> ObjectArrayChunkedParallelIterator<'a, Object>
where
Object: Sized,
{
pub fn new(chunks: Vec<&'a [ObjectArrayItem<Object>]>) -> Self {
Self { chunks }
}
}
impl<'a> ParallelIterator for ObjectArrayChunkedParallelIterator<'a> {
type Item = &'a ObjectArrayItem;
impl<'a, Object> ParallelIterator for ObjectArrayChunkedParallelIterator<'a, Object>
where
Object: Sized,
{
type Item = &'a ObjectArrayItem<Object>;
fn drive_unindexed<C>(self, consumer: C) -> C::Result
where
@ -242,7 +261,7 @@ pub trait FindClass {
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>
where
S: Into<String>,