Don't let the PubSub internal offsets overflow + fix some warnings.

This commit is contained in:
Crozet Sébastien
2020-10-06 15:23:48 +02:00
parent 7c92848383
commit 682ff61f94
11 changed files with 73 additions and 37 deletions

View File

@@ -3,16 +3,28 @@
use serde::export::PhantomData; use serde::export::PhantomData;
use std::collections::VecDeque; use std::collections::VecDeque;
/// The position of a subscriber on a pub-sub queue. /// A permanent subscription to a pub-sub queue.
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
pub struct PubSubCursor<T> { pub struct Subscription<T> {
// Index of the next message to read. // Position on the cursor array.
id: u32, id: u32,
next: u32,
_phantom: PhantomData<T>, _phantom: PhantomData<T>,
} }
impl<T> PubSubCursor<T> { #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
struct PubSubCursor {
// Position on the offset array.
id: u32,
// Index of the next message to read.
// NOTE: Having this here is not actually necessary because
// this value is supposed to be equal to `offsets[self.id]`.
// However, we keep it because it lets us avoid one lookup
// on the `offsets` array inside of message-polling loops
// based on `read_ith`.
next: u32,
}
impl PubSubCursor {
fn id(&self, num_deleted: u32) -> usize { fn id(&self, num_deleted: u32) -> usize {
(self.id - num_deleted) as usize (self.id - num_deleted) as usize
} }
@@ -29,6 +41,7 @@ pub struct PubSub<T> {
deleted_offsets: u32, deleted_offsets: u32,
messages: VecDeque<T>, messages: VecDeque<T>,
offsets: VecDeque<u32>, offsets: VecDeque<u32>,
cursors: Vec<PubSubCursor>,
} }
impl<T> PubSub<T> { impl<T> PubSub<T> {
@@ -39,9 +52,24 @@ impl<T> PubSub<T> {
deleted_messages: 0, deleted_messages: 0,
messages: VecDeque::new(), messages: VecDeque::new(),
offsets: VecDeque::new(), offsets: VecDeque::new(),
cursors: Vec::new(),
} }
} }
fn reset_shifts(&mut self) {
for offset in &mut self.offsets {
*offset -= self.deleted_messages;
}
for cursor in &mut self.cursors {
cursor.id -= self.deleted_offsets;
cursor.next -= self.deleted_messages;
}
self.deleted_offsets = 0;
self.deleted_messages = 0;
}
/// Publish a new message. /// Publish a new message.
pub fn publish(&mut self, message: T) { pub fn publish(&mut self, message: T) {
if self.offsets.is_empty() { if self.offsets.is_empty() {
@@ -55,25 +83,33 @@ impl<T> PubSub<T> {
/// Subscribe to the queue. /// Subscribe to the queue.
/// ///
/// A subscription cannot be cancelled. /// A subscription cannot be cancelled.
pub fn subscribe(&mut self) -> PubSubCursor<T> { #[must_use]
pub fn subscribe(&mut self) -> Subscription<T> {
let cursor = PubSubCursor { let cursor = PubSubCursor {
next: self.messages.len() as u32 + self.deleted_messages, next: self.messages.len() as u32 + self.deleted_messages,
id: self.offsets.len() as u32 + self.deleted_offsets, id: self.offsets.len() as u32 + self.deleted_offsets,
};
let subscription = Subscription {
id: self.cursors.len() as u32,
_phantom: PhantomData, _phantom: PhantomData,
}; };
self.offsets.push_back(cursor.next); self.offsets.push_back(cursor.next);
cursor self.cursors.push(cursor);
subscription
} }
/// Read the i-th message not yet read by the given subsciber. /// Read the i-th message not yet read by the given subsciber.
pub fn read_ith(&self, cursor: &PubSubCursor<T>, i: usize) -> Option<&T> { pub fn read_ith(&self, sub: &Subscription<T>, i: usize) -> Option<&T> {
let cursor = &self.cursors[sub.id as usize];
self.messages self.messages
.get(cursor.next(self.deleted_messages) as usize + i) .get(cursor.next(self.deleted_messages) as usize + i)
} }
/// Get the messages not yet read by the given subscriber. /// Get the messages not yet read by the given subscriber.
pub fn read(&self, cursor: &PubSubCursor<T>) -> impl Iterator<Item = &T> { pub fn read(&self, sub: &Subscription<T>) -> impl Iterator<Item = &T> {
let cursor = &self.cursors[sub.id as usize];
let next = cursor.next(self.deleted_messages); let next = cursor.next(self.deleted_messages);
// TODO: use self.queue.range(next..) once it is stabilised. // TODO: use self.queue.range(next..) once it is stabilised.
@@ -86,11 +122,14 @@ impl<T> PubSub<T> {
/// Makes the given subscribe acknowledge all the messages in the queue. /// Makes the given subscribe acknowledge all the messages in the queue.
/// ///
/// A subscriber cannot read acknowledged messages any more. /// A subscriber cannot read acknowledged messages any more.
pub fn ack(&mut self, cursor: &mut PubSubCursor<T>) { pub fn ack(&mut self, sub: &Subscription<T>) {
// Update the cursor. // Update the cursor.
cursor.next = self.messages.len() as u32 + self.deleted_messages; let cursor = &mut self.cursors[sub.id as usize];
self.offsets[cursor.id(self.deleted_offsets)] = u32::MAX; self.offsets[cursor.id(self.deleted_offsets)] = u32::MAX;
cursor.id = self.offsets.len() as u32 + self.deleted_offsets; cursor.id = self.offsets.len() as u32 + self.deleted_offsets;
cursor.next = self.messages.len() as u32 + self.deleted_messages;
self.offsets.push_back(cursor.next); self.offsets.push_back(cursor.next);
// Now clear the messages we don't need to // Now clear the messages we don't need to
@@ -110,6 +149,12 @@ impl<T> PubSub<T> {
} }
self.deleted_messages += num_to_delete; self.deleted_messages += num_to_delete;
if self.deleted_messages > u32::MAX / 2 || self.deleted_offsets > u32::MAX / 2 {
// Don't let the deleted_* shifts grow indefinitely otherwise
// they will end up overflowing, breaking everything.
self.reset_shifts();
}
} }
} }

View File

@@ -2,11 +2,9 @@
use rayon::prelude::*; use rayon::prelude::*;
use crate::data::arena::Arena; use crate::data::arena::Arena;
use crate::data::pubsub::PubSub;
use crate::dynamics::{BodyStatus, Joint, JointSet, RigidBody}; use crate::dynamics::{BodyStatus, Joint, JointSet, RigidBody};
use crate::geometry::{ColliderHandle, ColliderSet, ContactPair, InteractionGraph}; use crate::geometry::{ColliderHandle, ColliderSet, ContactPair, InteractionGraph};
use crossbeam::channel::{Receiver, Sender}; use crossbeam::channel::{Receiver, Sender};
use num::Zero;
use std::ops::{Deref, DerefMut, Index, IndexMut}; use std::ops::{Deref, DerefMut, Index, IndexMut};
/// A mutable reference to a rigid-body. /// A mutable reference to a rigid-body.

View File

@@ -1,6 +1,6 @@
use crate::data::pubsub::PubSubCursor; use crate::data::pubsub::Subscription;
use crate::dynamics::RigidBodySet; use crate::dynamics::RigidBodySet;
use crate::geometry::{Collider, ColliderHandle, ColliderSet, RemovedCollider}; use crate::geometry::{ColliderHandle, ColliderSet, RemovedCollider};
use crate::math::{Point, Vector, DIM}; use crate::math::{Point, Vector, DIM};
#[cfg(feature = "enhanced-determinism")] #[cfg(feature = "enhanced-determinism")]
use crate::utils::FxHashMap32 as HashMap; use crate::utils::FxHashMap32 as HashMap;
@@ -417,7 +417,7 @@ impl SAPRegion {
pub struct BroadPhase { pub struct BroadPhase {
proxies: Proxies, proxies: Proxies,
regions: HashMap<Point<i32>, SAPRegion>, regions: HashMap<Point<i32>, SAPRegion>,
removed_colliders: Option<PubSubCursor<RemovedCollider>>, removed_colliders: Option<Subscription<RemovedCollider>>,
deleted_any: bool, deleted_any: bool,
// We could think serializing this workspace is useless. // We could think serializing this workspace is useless.
// It turns out is is important to serialize at least its capacity // It turns out is is important to serialize at least its capacity

View File

@@ -83,7 +83,7 @@ impl ColliderSet {
/* /*
* Delete the collider from its parent body. * Delete the collider from its parent body.
*/ */
if let Some(mut parent) = bodies.get_mut_internal(collider.parent) { if let Some(parent) = bodies.get_mut_internal(collider.parent) {
parent.remove_collider_internal(handle, &collider); parent.remove_collider_internal(handle, &collider);
bodies.wake_up(collider.parent, true); bodies.wake_up(collider.parent, true);
} }

View File

@@ -14,13 +14,13 @@ use crate::geometry::proximity_detector::{
// proximity_detector::ProximityDetectionContextSimd, WBall, // proximity_detector::ProximityDetectionContextSimd, WBall,
//}; //};
use crate::geometry::{ use crate::geometry::{
BroadPhasePairEvent, Collider, ColliderGraphIndex, ColliderHandle, ContactEvent, BroadPhasePairEvent, ColliderGraphIndex, ColliderHandle, ContactEvent, ProximityEvent,
ProximityEvent, ProximityPair, RemovedCollider, ProximityPair, RemovedCollider,
}; };
use crate::geometry::{ColliderSet, ContactManifold, ContactPair, InteractionGraph}; use crate::geometry::{ColliderSet, ContactManifold, ContactPair, InteractionGraph};
//#[cfg(feature = "simd-is-enabled")] //#[cfg(feature = "simd-is-enabled")]
//use crate::math::{SimdFloat, SIMD_WIDTH}; //use crate::math::{SimdFloat, SIMD_WIDTH};
use crate::data::pubsub::PubSubCursor; use crate::data::pubsub::Subscription;
use crate::ncollide::query::Proximity; use crate::ncollide::query::Proximity;
use crate::pipeline::EventHandler; use crate::pipeline::EventHandler;
use std::collections::HashMap; use std::collections::HashMap;
@@ -31,7 +31,7 @@ use std::collections::HashMap;
pub struct NarrowPhase { pub struct NarrowPhase {
contact_graph: InteractionGraph<ContactPair>, contact_graph: InteractionGraph<ContactPair>,
proximity_graph: InteractionGraph<ProximityPair>, proximity_graph: InteractionGraph<ProximityPair>,
removed_colliders: Option<PubSubCursor<RemovedCollider>>, removed_colliders: Option<Subscription<RemovedCollider>>,
// ball_ball: Vec<usize>, // Workspace: Vec<*mut ContactPair>, // ball_ball: Vec<usize>, // Workspace: Vec<*mut ContactPair>,
// shape_shape: Vec<usize>, // Workspace: Vec<*mut ContactPair>, // shape_shape: Vec<usize>, // Workspace: Vec<*mut ContactPair>,
// ball_ball_prox: Vec<usize>, // Workspace: Vec<*mut ProximityPair>, // ball_ball_prox: Vec<usize>, // Workspace: Vec<*mut ProximityPair>,

View File

@@ -93,10 +93,6 @@ impl<'de> serde::Deserialize<'de> for WAABB {
} }
impl WAABB { impl WAABB {
pub fn new(mins: Point<SimdFloat>, maxs: Point<SimdFloat>) -> Self {
Self { mins, maxs }
}
pub fn new_invalid() -> Self { pub fn new_invalid() -> Self {
Self::splat(AABB::new_invalid()) Self::splat(AABB::new_invalid())
} }
@@ -132,7 +128,7 @@ impl WAABB {
for i in 0usize..DIM { for i in 0usize..DIM {
let is_not_zero = ray.dir[i].simd_ne(_0); let is_not_zero = ray.dir[i].simd_ne(_0);
let is_zero_test = let is_zero_test =
(ray.origin[i].simd_ge(self.mins[i]) & ray.origin[i].simd_le(self.maxs[i])); ray.origin[i].simd_ge(self.mins[i]) & ray.origin[i].simd_le(self.maxs[i]);
let is_not_zero_test = { let is_not_zero_test = {
let denom = _1 / ray.dir[i]; let denom = _1 / ray.dir[i];
let mut inter_with_near_plane = let mut inter_with_near_plane =

View File

@@ -379,11 +379,13 @@ impl<T: IndexedData> WQuadtree<T> {
} }
} }
#[allow(dead_code)]
struct WQuadtreeIncrementalBuilderStep { struct WQuadtreeIncrementalBuilderStep {
range: Range<usize>, range: Range<usize>,
parent: NodeIndex, parent: NodeIndex,
} }
#[allow(dead_code)]
struct WQuadtreeIncrementalBuilder<T> { struct WQuadtreeIncrementalBuilder<T> {
quadtree: WQuadtree<T>, quadtree: WQuadtree<T>,
to_insert: Vec<WQuadtreeIncrementalBuilderStep>, to_insert: Vec<WQuadtreeIncrementalBuilderStep>,
@@ -391,6 +393,7 @@ struct WQuadtreeIncrementalBuilder<T> {
indices: Vec<usize>, indices: Vec<usize>,
} }
#[allow(dead_code)]
impl<T: IndexedData> WQuadtreeIncrementalBuilder<T> { impl<T: IndexedData> WQuadtreeIncrementalBuilder<T> {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {

View File

@@ -1,6 +1,6 @@
//! Physics pipeline structures. //! Physics pipeline structures.
use crate::dynamics::{JointSet, RigidBody, RigidBodyHandle, RigidBodySet}; use crate::dynamics::{JointSet, RigidBodySet};
use crate::geometry::{BroadPhase, BroadPhasePairEvent, ColliderPair, ColliderSet, NarrowPhase}; use crate::geometry::{BroadPhase, BroadPhasePairEvent, ColliderPair, ColliderSet, NarrowPhase};
use crate::pipeline::EventHandler; use crate::pipeline::EventHandler;

View File

@@ -1,15 +1,13 @@
//! Physics pipeline structures. //! Physics pipeline structures.
use crate::counters::Counters; use crate::counters::Counters;
use crate::data::pubsub::PubSubCursor;
#[cfg(not(feature = "parallel"))] #[cfg(not(feature = "parallel"))]
use crate::dynamics::IslandSolver; use crate::dynamics::IslandSolver;
use crate::dynamics::{IntegrationParameters, JointSet, RigidBody, RigidBodyHandle, RigidBodySet}; use crate::dynamics::{IntegrationParameters, JointSet, RigidBodySet};
#[cfg(feature = "parallel")] #[cfg(feature = "parallel")]
use crate::dynamics::{JointGraphEdge, ParallelIslandSolver as IslandSolver}; use crate::dynamics::{JointGraphEdge, ParallelIslandSolver as IslandSolver};
use crate::geometry::{ use crate::geometry::{
BroadPhase, BroadPhasePairEvent, Collider, ColliderHandle, ColliderPair, ColliderSet, BroadPhase, BroadPhasePairEvent, ColliderPair, ColliderSet, ContactManifoldIndex, NarrowPhase,
ContactManifoldIndex, NarrowPhase, RemovedCollider,
}; };
use crate::math::Vector; use crate::math::Vector;
use crate::pipeline::EventHandler; use crate::pipeline::EventHandler;

View File

@@ -1,9 +1,5 @@
use crate::dynamics::RigidBodySet; use crate::dynamics::RigidBodySet;
use crate::geometry::{ use crate::geometry::{Collider, ColliderHandle, ColliderSet, Ray, RayIntersection, WQuadtree};
Collider, ColliderHandle, ColliderSet, Ray, RayIntersection, WQuadtree, AABB, WAABB,
};
use crate::math::{Point, Vector};
use ncollide::bounding_volume::BoundingVolume;
/// A pipeline for performing queries on all the colliders of a scene. /// A pipeline for performing queries on all the colliders of a scene.
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]

View File

@@ -609,7 +609,7 @@ impl GraphicsManager {
} }
} }
pub fn draw(&mut self, bodies: &RigidBodySet, colliders: &ColliderSet, window: &mut Window) { pub fn draw(&mut self, _bodies: &RigidBodySet, colliders: &ColliderSet, window: &mut Window) {
// use kiss3d::camera::Camera; // use kiss3d::camera::Camera;
// println!( // println!(
// "camera eye {:?}, at: {:?}", // "camera eye {:?}, at: {:?}",