Skip to content

Commit

Permalink
use pointer cast instead of transmuting
Browse files Browse the repository at this point in the history
  • Loading branch information
vertexclique committed Jan 18, 2020
1 parent 75985f4 commit cabba1e
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 4 deletions.
9 changes: 5 additions & 4 deletions lightproc/src/proc_stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use super::proc_state::*;

use std::fmt::{self, Debug, Formatter};
use std::mem;

use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
Expand Down Expand Up @@ -180,7 +179,7 @@ impl ProcStack {
S: State + Copy + 'static,
{
let state = self.state.clone();
let s = unsafe { mem::transmute::<&ProcState, &Arc<Mutex<S>>>(&state) };
let s = unsafe { &*(&state as *const ProcState as *const Arc<Mutex<S>>) };
*s.lock().unwrap()
}

Expand All @@ -197,18 +196,20 @@ impl ProcStack {
C: Fn(&mut S) + Send + Sync + 'static,
{
let wrapped = move |s: ProcState| {
let x = unsafe { mem::transmute::<&ProcState, &Arc<Mutex<S>>>(&s) };
let x = unsafe { &*(&s as *const ProcState as *const Arc<Mutex<S>>) };
let mut mg = x.lock().unwrap();
callback(&mut *mg);
};
Arc::new(wrapped)
}
}

///
/// Default implementation for the ProcStack
impl Default for ProcStack {
fn default() -> Self {
ProcStack {
pid: AtomicUsize::new(0xDEADBEEF),
pid: AtomicUsize::new(0xDEAD_BEEF),
state: Arc::new(Mutex::new(EmptyState)),
before_start: None,
after_complete: None,
Expand Down
56 changes: 56 additions & 0 deletions lightproc/src/proc_state.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,85 @@
//!
//! State layer for lightproc implementation
//!
//! Contains trait bounds and state wrapping code
//!
//! # Example
//! ```rust
//! use lightproc::proc_state::State;
//! use crate::lightproc::proc_state::AsAny;
//!
//! #[derive(Clone)]
//! pub struct SharedState {
//! name: String,
//! surname: String,
//! id: u64,
//! }
//!
//!
//! let mut s = SharedState {
//! name: "Riemann".to_string(),
//! surname: "Sum".to_string(),
//! id: 123
//! };
//!
//! s.as_any();
//! ```
use std::any::Any;

use std::fmt::{Error, Formatter};

use std::fmt;
use std::sync::{Arc, Mutex};

///
/// State trait to implement a state for Bastion
pub trait State: Send + Sync + AsAny + 'static {}

///
/// Blanket implementation for the state when rules apply
impl<T> State for T where T: Send + Sync + 'static {}

///
/// Default debug implementation for dynamically dispatched state
impl fmt::Debug for dyn State {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
f.write_fmt(format_args!("State :: {:?}", self.type_id()))
}
}

///
/// Generic protection type where state is stored as is.
/// This allows us to share the state between the threads (both by ref and by value).
/// All state implementors bound to use this.
pub type ProcState = Arc<Mutex<dyn State>>;

///
/// Generic dynamic programming construct which allows us to downcast to the typeless level.
/// And do costly conversion between types if possible.
pub trait AsAny {
///
/// Downcast implemented type to Any.
fn as_any(&mut self) -> &mut dyn Any;
}

///
/// Blanket implementation for Any conversion if type is implementing Any.
impl<T: Any> AsAny for T {
fn as_any(&mut self) -> &mut dyn Any {
self
}
}

// ------------------------------------------------------
// State related types are below
// ------------------------------------------------------

///
/// Empty proc state which is an heap allocated empty struct.
pub type EmptyProcState = Box<EmptyState>;

///
/// Base construct for empty state struct.
#[derive(Debug)]
pub struct EmptyState;

0 comments on commit cabba1e

Please sign in to comment.