Compress EntityHandle

This commit is contained in:
micialware committed 2026-08-29 22:41:11 +03:00
1 parent d8e3a5b6db
commit 2c1163fc3b
3 files changed
+120 -111

No files matched your search

+28 -6
View File
@@ -182,8 +182,7 @@ impl CardStatistics {
#[derive(Copy)]
pub struct EntityHandle<E> {
pub(crate) id: Id,
pub(crate) real: bool,
pub(crate) index: u32,
index: i32,
pub(crate) _phantom: PhantomData<E>,
}
@@ -192,17 +191,40 @@ impl<T> Clone for EntityHandle<T> {
fn clone(&self) -> Self {
EntityHandle{
id: self.id,
real: self.real,
index: self.index,
_phantom: Default::default(),
}
}
}
impl<T> EntityHandle<T> {
pub fn new(id: Id, index: usize, real: bool) -> Self {
Self {
id,
index : index as i32 | (!real as i32) << 31,
_phantom: Default::default()
}
}
pub fn index(&self) -> usize {
(self.index << 1 >> 1) as usize
}
pub fn set_index(&mut self, index: usize) {
self.index = self.index >> 31 << 31 | index as i32;
}
pub fn real(&self) -> bool {
(self.index >> 31) == 0
}
pub fn set_real(&mut self, value: bool) {
self.index = self.index << 1 >> 1 | (!value as i32) << 31;
}
}
impl<T> Eq for EntityHandle<T> {}
impl<T> PartialEq<Self> for EntityHandle<T> {
fn eq(&self, other: &Self) -> bool {
self.real == other.real && self.id == other.id
self.real() == other.real() && self.id == other.id
}
}
impl<T> PartialOrd<Self> for EntityHandle<T> {
@@ -213,11 +235,11 @@ impl<T> PartialOrd<Self> for EntityHandle<T> {
impl<T> Ord for EntityHandle<T> {
fn cmp(&self, other: &Self) -> Ordering {
if self.real && !other.real {
if self.real() && !other.real() {
return Ordering::Less
}
if !self.real && other.real{
if !self.real() && other.real(){
return Ordering::Greater
}
+37 -81
View File
@@ -43,7 +43,7 @@ where
T: EntityData,
{
pub(crate) fn handle_save(&self, old: EntityHandle<T>, new: &mut EntityHandle<T>, data: &T) {
if old.real && new.real {
if old.real() && new.real() {
return;
}
@@ -52,7 +52,7 @@ where
let mut query = self.queries[q].lock();
let index = query.cache.binary_search(&old).unwrap();
query.cache.remove(index);
let real_end = query.cache.iter().rposition(|r| r.real).unwrap() + 1;
let real_end = query.cache.iter().rposition(|r| r.real()).unwrap() + 1;
query.cache.insert(real_end, new.clone());
}
}
@@ -86,7 +86,6 @@ where
for q in &self.queries {
let mut query = q.lock();
query.cache.clear();
}
}
}
@@ -122,7 +121,10 @@ impl<T: EntityData + Clone, R: Repository<T, D>, D: DbLayer<T>> Query<T, R, D> {
}
}
pub fn load(&mut self, data_repository: &DataRepositoryInner<T, D>) where T : Send + Sync {
pub fn load(&mut self, data_repository: &DataRepositoryInner<T, D>)
where
T: Send + Sync,
{
self.cache.clear();
if self.parallel {
self.cache = data_repository
@@ -130,28 +132,15 @@ impl<T: EntityData + Clone, R: Repository<T, D>, D: DbLayer<T>> Query<T, R, D> {
.par_iter()
.enumerate()
.filter(|(_, entity)| (self.rule)(entity))
.map(|(i, entity)| EntityHandle {
id: entity.id(),
real: true,
index: i as u32,
_phantom: PhantomData,
})
.map(|(i, entity)| EntityHandle::new(entity.id(), i, true))
.collect();
}
else {
} else {
self.cache = data_repository
.cache
.iter()
.enumerate()
.filter(|(_, entity)| (self.rule)(entity))
.map(|(i, entity)| EntityHandle {
id: entity.id(),
real: true,
index: i as u32,
_phantom: PhantomData,
})
.map(|(i, entity)| EntityHandle::new(entity.id(), i, true))
.collect();
}
@@ -161,12 +150,7 @@ impl<T: EntityData + Clone, R: Repository<T, D>, D: DbLayer<T>> Query<T, R, D> {
.iter()
.enumerate()
.filter(|(_, entity)| (self.rule)(entity))
.map(|(i, entity)| EntityHandle {
id: entity.id(),
real: false,
index: i as u32,
_phantom: PhantomData,
})
.map(|(i, entity)| EntityHandle::new(entity.id(), i, false))
.collect::<Vec<_>>(),
);
}
@@ -208,6 +192,7 @@ pub struct DataRepositoryInner<T: std::clone::Clone + EntityData, D: DbLayer<T>>
connection: Arc<Mutex<Connection>>,
data_layer: D,
query_manger: QueryManger<T, Self, D>,
version: u16
}
impl<T: std::clone::Clone + EntityData, D: DbLayer<T>> Deref for DataRepository<T, D> {
@@ -233,12 +218,7 @@ impl<T: EntityData + Clone, D: DbLayer<T>> DataRepository<T, D> {
.par_iter()
.enumerate()
.filter(|(_, entity)| rule(entity))
.map(|(i, entity)| EntityHandle {
id: entity.id(),
real: true,
index: i as u32,
_phantom: PhantomData,
})
.map(|(i, entity)| EntityHandle::new(entity.id(), i, true))
.collect();
cache.extend(
@@ -247,12 +227,7 @@ impl<T: EntityData + Clone, D: DbLayer<T>> DataRepository<T, D> {
.iter()
.enumerate()
.filter(|(_, entity)| rule(entity))
.map(|(i, entity)| EntityHandle {
id: entity.id(),
real: false,
index: i as u32,
_phantom: PhantomData,
})
.map(|(i, entity)| EntityHandle::new(entity.id(), i, false))
.collect::<Vec<_>>(),
);
@@ -264,7 +239,10 @@ impl<T: EntityData + Clone, D: DbLayer<T>> DataRepository<T, D> {
}
}
pub fn query(&self, rule: Box<dyn Fn(&T) -> bool + Send + Sync>) -> Query<T, DataRepositoryInner<T, D>, D>
pub fn query(
&self,
rule: Box<dyn Fn(&T) -> bool + Send + Sync>,
) -> Query<T, DataRepositoryInner<T, D>, D>
where
T: Send + Sync,
{
@@ -275,12 +253,7 @@ impl<T: EntityData + Clone, D: DbLayer<T>> DataRepository<T, D> {
.iter()
.enumerate()
.filter(|(_, entity)| rule(entity))
.map(|(i, entity)| EntityHandle {
id: entity.id(),
real: true,
index: i as u32,
_phantom: PhantomData,
})
.map(|(i, entity)| EntityHandle::new(entity.id(), i, true))
.collect();
cache.extend(
@@ -289,12 +262,7 @@ impl<T: EntityData + Clone, D: DbLayer<T>> DataRepository<T, D> {
.iter()
.enumerate()
.filter(|(_, entity)| rule(entity))
.map(|(i, entity)| EntityHandle {
id: entity.id(),
real: false,
index: i as u32,
_phantom: PhantomData,
})
.map(|(i, entity)| EntityHandle::new(entity.id(), i, false))
.collect::<Vec<_>>(),
);
@@ -309,7 +277,7 @@ impl<T: EntityData + Clone, D: DbLayer<T>> DataRepository<T, D> {
impl<T: EntityData + Clone, D: DbLayer<T>> Repository<T, D> for DataRepositoryInner<T, D> {
fn get(&self, handle: &mut EntityHandle<T>) -> Option<T> {
let slice = if handle.real {
let slice = if handle.real() {
self.cache.as_slice()
} else {
self.temporal.as_slice()
@@ -319,7 +287,7 @@ impl<T: EntityData + Clone, D: DbLayer<T>> Repository<T, D> for DataRepositoryIn
}
fn get_ref(&self, handle: &mut EntityHandle<T>) -> Option<&T> {
let slice = if handle.real {
let slice = if handle.real() {
self.cache.as_slice()
} else {
self.temporal.as_slice()
@@ -329,7 +297,7 @@ impl<T: EntityData + Clone, D: DbLayer<T>> Repository<T, D> for DataRepositoryIn
}
fn get_mut(&mut self, handle: &mut EntityHandle<T>) -> Option<&mut T> {
let slice = if handle.real {
let slice = if handle.real() {
self.cache.as_mut_slice()
} else {
self.temporal.as_mut_slice()
@@ -339,23 +307,13 @@ impl<T: EntityData + Clone, D: DbLayer<T>> Repository<T, D> for DataRepositoryIn
}
fn handle_by_id(&self, id: Id) -> EntityHandle<T> {
EntityHandle {
_phantom: Default::default(),
id,
real: true,
index: id.0,
}
EntityHandle::new(id, id.0 as usize, false)
}
fn create(&mut self, mut new: T) -> EntityHandle<T> {
let next_temporal = self.next_temporal;
self.next_temporal += 1;
let entity = EntityHandle {
id: next_temporal.into(),
real: false,
index: self.temporal.len() as u32,
_phantom: PhantomData,
};
let entity = EntityHandle::new(next_temporal.into(), self.temporal.len(), false);
new.set_id(entity.id);
self.temporal.push(new);
entity
@@ -363,7 +321,7 @@ impl<T: EntityData + Clone, D: DbLayer<T>> Repository<T, D> for DataRepositoryIn
fn save(&mut self, entity: &mut EntityHandle<T>) -> MaybeError {
let original_state = entity.clone();
if entity.real {
if entity.real() {
let data = self.get_ref(entity).unwrap();
self.data_layer
.write_entity(data, &self.connection.lock())?;
@@ -372,9 +330,9 @@ impl<T: EntityData + Clone, D: DbLayer<T>> Repository<T, D> for DataRepositoryIn
let mut data = self.temporal.remove(index);
self.data_layer
.add_entity(&mut data, &self.connection.lock())?;
entity.real = true;
entity.set_real(true);
entity.id = data.id();
entity.index = self.cache.len() as u32;
entity.set_index(self.cache.len());
self.query_manger.handle_save(original_state, entity, &data);
self.cache.push(data);
@@ -384,7 +342,7 @@ impl<T: EntityData + Clone, D: DbLayer<T>> Repository<T, D> for DataRepositoryIn
}
fn delete(&mut self, mut handle: EntityHandle<T>) -> MaybeError {
let vec = if handle.real {
let vec = if handle.real() {
self.data_layer
.delete_entity(handle.id, &self.connection.lock())?;
&mut self.cache
@@ -404,6 +362,7 @@ impl<T: EntityData + Clone, D: DbLayer<T>> Repository<T, D> for DataRepositoryIn
fn init(&mut self) -> MaybeError {
self.data_layer
.load_all(&mut self.cache, &self.connection.lock())?;
self.version += 1;
Ok(())
}
@@ -411,7 +370,6 @@ impl<T: EntityData + Clone, D: DbLayer<T>> Repository<T, D> for DataRepositoryIn
self.cache.clear();
self.temporal.clear();
self.init()?;
Ok(())
}
}
@@ -423,7 +381,7 @@ impl<T: EntityData + Clone, D: BatchedDbLayer<T> + DbLayer<T>> BatchedRepository
let mut cached = Vec::with_capacity(handles.len() / 2);
handles.sort_by_key(|a| a.id);
handles.iter_mut().for_each(|handle| {
if handle.real {
if handle.real() {
cached.push(handle)
} else {
temp.push(handle)
@@ -455,15 +413,13 @@ impl<T: EntityData + Clone, D: BatchedDbLayer<T> + DbLayer<T>> BatchedRepository
let old = handle.clone();
let h = handle;
h.id = self.cache[start + i].id();
h.index = (start + i) as u32;
h.real = true;
h.set_index(start + i);
h.set_real(true);
self.query_manger.handle_save(old, h, data);
}
self.cache.extend(values);
for handle in cached.into_iter() {
let h = handle;
let idx = fast_position_of(self.cache.as_slice(), h).unwrap();
@@ -519,7 +475,7 @@ where
let mut cached = Vec::with_capacity(handles.len() / 2);
handles.sort_by(|a, b| a.id.cmp(&b.id));
handles.iter().for_each(|handle| {
if handle.real {
if handle.real() {
cached.push(getter(handle))
} else {
temp.push(getter(handle))
@@ -537,11 +493,11 @@ pub fn fast_position_of<E: EntityData>(
}
let max_idx = storage.len() - 1;
let upper = (handle.index as usize).min(max_idx);
let upper = (handle.index()).min(max_idx);
let peek = storage[upper].id();
if peek == handle.id {
handle.index = upper as u32;
handle.set_index(upper);
return Some(upper);
}
@@ -556,7 +512,7 @@ pub fn fast_position_of<E: EntityData>(
let new_index = (upper as i64 - delta).max(0) as usize;
if storage[new_index].id() == handle.id {
handle.index = new_index as u32;
handle.set_index(new_index);
return Some(new_index);
}
@@ -569,6 +525,6 @@ pub fn fast_position_of<E: EntityData>(
.ok()?
+ new_index;
handle.index = index as u32;
handle.set_index(index);
Some(index)
}
+55 -24
View File
@@ -29,12 +29,7 @@ mod mod_tests {
#[test]
fn search_direct() {
let mut entity = EntityHandle {
_phantom: Default::default(),
id: 8.into(),
real: true,
index: 3,
};
let mut entity = EntityHandle::new(8.into(), 3, true);
assert_eq!(
fast_position_of(&[1, 2, 3, 8, 9, 12].map(ProtoEntity::new), &mut entity),
Some(3)
@@ -43,12 +38,7 @@ mod mod_tests {
#[test]
fn search_0() {
let mut entity = EntityHandle {
_phantom: Default::default(),
id: 8.into(),
real: true,
index: 4,
};
let mut entity = EntityHandle::new(8.into(), 4, true);
assert_eq!(
fast_position_of(&[1, 2, 3, 8, 9, 12].map(ProtoEntity::new), &mut entity),
Some(3)
@@ -57,12 +47,7 @@ mod mod_tests {
#[test]
fn search_1() {
let mut entity = EntityHandle {
_phantom: Default::default(),
id: 9.into(),
real: true,
index: 5,
};
let mut entity = EntityHandle::new(9.into(), 5, true);
assert_eq!(
fast_position_of(&[1, 2, 3, 8, 9, 12].map(ProtoEntity::new), &mut entity),
Some(4)
@@ -71,12 +56,7 @@ mod mod_tests {
#[test]
fn search_2() {
let mut entity = EntityHandle {
_phantom: Default::default(),
id: 106.into(),
real: true,
index: 25,
};
let mut entity = EntityHandle::new(106.into(), 25, true);
assert_eq!(
fast_position_of(
&[
@@ -89,4 +69,55 @@ mod mod_tests {
Some(18)
);
}
#[test]
fn id_0() {
let entity: EntityHandle<ProtoEntity> = EntityHandle::new(8.into(), 25, true);
assert_eq!(entity.real(), true)
}
#[test]
fn id_1() {
let entity: EntityHandle<ProtoEntity> = EntityHandle::new(8.into(), 25, false);
assert_eq!(entity.real(), false)
}
#[test]
fn id_3() {
let entity: EntityHandle<ProtoEntity> = EntityHandle::new(8.into(), 25, true);
assert_eq!(entity.index(), 25)
}
#[test]
fn id_4() {
let entity: EntityHandle<ProtoEntity> = EntityHandle::new(8.into(), 25, false);
assert_eq!(entity.index(), 25)
}
#[test]
fn id_5() {
let mut entity: EntityHandle<ProtoEntity> = EntityHandle::new(8.into(), 25, true);
entity.set_real(true);
assert_eq!(entity.real(), true)
}
#[test]
fn id_6() {
let mut entity: EntityHandle<ProtoEntity> = EntityHandle::new(8.into(), 25, false);
entity.set_real(true);
assert_eq!(entity.real(), true)
}
#[test]
fn id_7() {
let mut entity: EntityHandle<ProtoEntity> = EntityHandle::new(8.into(), 25, true);
entity.set_index(0);
assert_eq!(entity.index(), 0)
}
#[test]
fn id_8() {
let mut entity: EntityHandle<ProtoEntity> = EntityHandle::new(8.into(), 25, false);
entity.set_index(0);
assert_eq!(entity.index(), 0)
}
}