shareable 0.1.1

Thread shareable objects using the minimal amount of synchronization.
Documentation
/* Copyright 2016 Joshua Gentry
 *
 * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 * http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 * <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 * option. This file may not be copied, modified, or distributed
 * except according to those terms.
 */
use std::mem::transmute;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};

//*************************************************************************************************
/// Stores a f32 element inside an atomic element so it can be accessed by multiple threads.
///
/// # Examples
///
/// ```
/// use std::sync::mpsc;
/// use std::thread;
/// use shareable::SharedF32;
///
/// let value1 = SharedF32::new(63.23);
/// let value2 = value1.clone();
///
/// let (tx, rx) = mpsc::channel();
///
/// let thread = thread::spawn(move || {
///     rx.recv();
///     assert_eq!(value2.get(), 31.83);
/// });
///
/// value1.set(31.83);
///
/// tx.send(());
/// thread.join().unwrap();
/// ```
#[derive(Clone)]
pub struct SharedF32
{
    //---------------------------------------------------------------------------------------------
    /// The internal data element.
    data : Arc<AtomicUsize>
}

impl SharedF32
{
    //********************************************************************************************
    /// Construct a new instance of the object.
    pub fn new(
        value : f32
        ) -> SharedF32
    {
        unsafe {
            SharedF32 {
                data : Arc::new(AtomicUsize::new(transmute::<f32, u32>(value) as usize))
            }
        }
    }

    //********************************************************************************************
    /// Set the value of the object.
    pub fn set(
        &self,
        val : f32
        )
    {
        unsafe {
            self.data.store(
                transmute::<f32, u32>(val) as usize,
                Ordering::Relaxed
                );
        }
    }

    //********************************************************************************************
    /// Returns the value of the object.
    pub fn get(&self) -> f32
    {
        unsafe {
            transmute(self.data.load(Ordering::Relaxed) as u32)
        }
    }
}

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

impl Debug for SharedF32
{
    //*********************************************************************************************
    /// Implementation of Debug.
    fn fmt(
        &self,
        f : &mut Formatter
        ) -> Result<(), Error>
    {
        write!(f, "{:?}", self.get())
    }
}

impl Display for SharedF32
{
    //*********************************************************************************************
    /// Implementation of Display.
    fn fmt(
        &self,
        f : &mut Formatter
        ) -> Result<(), Error>
    {
        write!(f, "{}", self.get())
    }
}

#[cfg(test)]
mod tests
{

    //*********************************************************************************************
    /// Test that get/set work with only 1 instance.
    #[test]
    fn test_single()
    {
        let test = super::SharedF32::new(-79.23);

        assert_eq!(test.get(), -79.23);
        test.set(41.78);
        assert_eq!(test.get(), 41.78);
    }

    //*********************************************************************************************
    /// Test that get/set work with multiple instances.
    #[test]
    fn test_multiple()
    {
        let test1 = super::SharedF32::new(-79.6);
        let test2 = test1.clone();
        let test3 = test2.clone();

        assert_eq!(test1.get(), -79.6);
        assert_eq!(test2.get(), -79.6);
        assert_eq!(test3.get(), -79.6);

        test1.set(51.98);

        assert_eq!(test1.get(), 51.98);
        assert_eq!(test2.get(), 51.98);
        assert_eq!(test3.get(), 51.98);

        test2.set(31.77);

        assert_eq!(test1.get(), 31.77);
        assert_eq!(test2.get(), 31.77);
        assert_eq!(test3.get(), 31.77);

        test3.set(-11.101);

        assert_eq!(test1.get(), -11.101);
        assert_eq!(test2.get(), -11.101);
        assert_eq!(test3.get(), -11.101);
    }
}