log4rs 0.4.0

A highly configurable multi-output logging implementation for the `log` facade
Documentation
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::mem;
use std::marker::PhantomData;

pub struct AtomicReference<T>(AtomicUsize, PhantomData<Arc<T>>);

impl<T> Drop for AtomicReference<T> {
    fn drop(&mut self) {
        self.take();
    }
}

impl<T> AtomicReference<T> {
    pub fn new(t: Arc<T>) -> AtomicReference<T> {
        unsafe { AtomicReference(AtomicUsize::new(mem::transmute(t)), PhantomData) }
    }

    fn take(&self) -> Arc<T> {
        loop {
            match self.0.swap(0, Ordering::Acquire) {
                0 => {}
                r => return unsafe { mem::transmute(r) },
            }
        }
    }

    fn put(&self, t: Arc<T>) {
        debug_assert_eq!(0, self.0.load(Ordering::SeqCst));
        self.0.store(unsafe { mem::transmute(t) }, Ordering::Release);
    }

    pub fn set(&self, t: Arc<T>) -> Arc<T> {
        let old = self.take();
        self.put(t);
        old
    }

    pub fn get(&self) -> Arc<T> {
        let t = self.take();
        self.put(t.clone());
        t
    }
}

#[cfg(test)]
mod test {
    use std::sync::Arc;

    use super::*;

    #[test]
    fn basic() {
        let r = AtomicReference::new(Arc::new(0));
        assert_eq!(*r.get(), 0);
        assert_eq!(*r.set(Arc::new(1)), 0);
        assert_eq!(*r.get(), 1);
    }
}