Write a Guard type

Notice the use of the atomic::* operators to generate thread safe checks for when all guards have expired and the target needs to be discarded.

Pointer aliasing

Is it not undefined behavior to deference the *mut T in multiple locations?

The answer is no: Accessing and writing to data via a raw pointer is not undefined behavior due to pointer aliasing; only references trigger this, as they are marked as noalias in the LLVM byte code.

Technically a raw pointer is both based on and not marked as noalias, so it does not violate any of the pointer aliasing rules in LLVM.

However, notice that converting the raw pointer into a mutable reference is locked by a mutex, which prevents multiple mutable references being used concurrently. Since references are marked noalias, this would trigger undefined behavior.

use std::sync::Arc;
use std::mem::transmute;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use std::ops::Deref;
use std::ops::DerefMut;

// Trait box
pub struct ABox<T: ?Sized> {
  raw:*mut T,
  lock:Arc<AtomicBool>,
  count:Arc<AtomicUsize>
}

// Trait box guard
pub struct ABoxGuard<'a, T: ?Sized + 'a> {
  lock:Arc<AtomicBool>,
  raw:&'a mut T
}

impl<T: ?Sized> ABox<T> {

  /// Create a new instance
  pub fn new(value:Box<T>) -> ABox<T> {
    return ABox {
      raw: unsafe { transmute(value) },
      lock: Arc::new(AtomicBool::new(false)),
      count: Arc::new(AtomicUsize::new(1))
    };
  }

  /// Try to lock the instance and return it
  pub fn as_ref<'a, 'b>(&'a mut self) -> Option<ABoxGuard<'b, T>> {
    if !self.lock.compare_and_swap(false, true, Ordering::Acquire) {
      return Some(ABoxGuard {
        raw: unsafe { &mut *self.raw },
        lock: self.lock.clone()
      });
    }
    return None;
  }

  /// Create a clone
  pub fn clone(&mut self) -> ABox<T> {
    self.count.fetch_add(1, Ordering::SeqCst);
    return ABox {
      raw: self.raw,
      lock: self.lock.clone(),
      count: self.count.clone()
    }
  }
}

impl<'b, T: ?Sized> Deref for ABoxGuard<'b, T> {
  type Target = T;
  fn deref<'a>(&'a self) -> &'a T {
    return self.raw;
  }
}

impl<'b, T: ?Sized> DerefMut for ABoxGuard<'b, T> {
  fn deref_mut<'a>(&'a mut self) -> &'a mut T {
    return self.raw;
  }
}

impl<'a, T: ?Sized> Drop for ABoxGuard<'a, T> {
  fn drop(&mut self) {
    self.lock.compare_and_swap(true, false, Ordering::Acquire);
  }
}

impl<T: ?Sized> Drop for ABox<T> {
  fn drop(&mut self) {
    if self.count.fetch_sub(1, Ordering::SeqCst) == 1 {
      unsafe {
        let _:Box<T> = transmute(self.raw);
      }
    }
  }
}

#[cfg(test)]
mod test {

  use super::ABox;

  struct Bar;
  trait Foo {
    fn hi(&self);
    fn hi_mut(&mut self);
  }
  impl Foo for Bar {
    fn hi(&self) { println!("\n\nHi\n\n"); }
    fn hi_mut(&mut self) { println!("\n\nHi mut\n\n"); }
  }
  impl Drop for Bar {
    fn drop(&mut self) {
      println!("Bar dropped!");
    }
  }

  #[test]
  fn test_create_instance() {
    let y = Box::new(Bar) as Box<Foo>;
    let _ = ABox::<Foo>::new(y);
  }

  #[test]
  fn test_lock() {
    let y = Box::new(Bar) as Box<Foo>;
    let mut x = ABox::<Foo>::new(y);
    if let Some(mut xp) = x.as_ref() { xp.hi(); xp.hi_mut(); };
    if let Some(mut xp) = x.as_ref() { xp.hi(); xp.hi_mut(); };
  }

  #[test]
  fn test_clone() {
    let y = Box::new(Bar) as Box<Foo>;
    let mut x = ABox::<Foo>::new(y);
    let mut z = x.clone();
    if let Some(mut xp) = x.as_ref() { xp.hi(); xp.hi_mut(); };
    if let Some(mut xp) = z.as_ref() { xp.hi(); xp.hi_mut(); };
  }
}