use std::marker::PhantomData;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering;
use epoch::Scope;
#[inline]
fn strongest_failure_ordering(ord: Ordering) -> Ordering {
use std::sync::atomic::Ordering::*;
match ord {
Relaxed => Relaxed,
Release => Relaxed,
Acquire => Acquire,
AcqRel => Acquire,
_ => SeqCst,
}
}
#[inline]
fn ensure_aligned<T>(raw: *const T) {
assert!(raw as usize & low_bits::<T>() == 0, "unaligned pointer");
}
#[inline]
fn low_bits<T>() -> usize {
(1 << mem::align_of::<T>().trailing_zeros()) - 1
}
#[inline]
fn data_with_tag<T>(data: usize, tag: usize) -> usize {
let mask = low_bits::<T>();
validate_tag::<T>(tag);
(data & !mask) | tag
}
#[derive(Debug)]
pub struct Atomic<T> {
data: AtomicUsize,
_marker: PhantomData<*mut T>,
}
unsafe impl<T: Send + Sync> Send for Atomic<T> {}
unsafe impl<T: Send + Sync> Sync for Atomic<T> {}
#[inline]
fn validate_tag<T>(tag: usize) {
let mask = low_bits::<T>();
assert!(
tag <= mask,
"tag too large to fit into the unused bits: {} > {}",
tag,
mask
);
}
impl<T> Atomic<T> {
fn from_data(data: usize) -> Self {
Atomic {
data: AtomicUsize::new(data),
_marker: PhantomData,
}
}
pub fn null() -> Self {
Atomic {
data: AtomicUsize::new(0),
_marker: PhantomData,
}
}
pub fn new(value: T) -> Self {
Self::from_owned(Owned::new(value))
}
pub fn from_owned(owned: Owned<T>) -> Self {
let data = owned.data;
mem::forget(owned);
Self::from_data(data)
}
pub fn from_ptr(ptr: Ptr<T>) -> Self {
Self::from_data(ptr.data)
}
pub fn load<'scope>(&self, ord: Ordering, _: &'scope Scope) -> Ptr<'scope, T> {
Ptr::from_data(self.data.load(ord))
}
pub fn store(&self, new: Ptr<T>, ord: Ordering) {
self.data.store(new.data, ord);
}
pub fn store_owned(&self, new: Owned<T>, ord: Ordering) {
let data = new.data;
mem::forget(new);
self.data.store(data, ord);
}
pub fn swap<'scope>(&self, new: Ptr<T>, ord: Ordering, _: &'scope Scope) -> Ptr<'scope, T> {
Ptr::from_data(self.data.swap(new.data, ord))
}
pub fn compare_and_swap<'scope>(
&self,
current: Ptr<T>,
new: Ptr<T>,
ord: Ordering,
_: &'scope Scope,
) -> Result<(), Ptr<'scope, T>> {
let fail_ord = strongest_failure_ordering(ord);
match self.data.compare_exchange(current.data, new.data, ord, fail_ord) {
Ok(_) => Ok(()),
Err(previous) => Err(Ptr::from_data(previous)),
}
}
pub fn compare_and_swap_weak<'scope>(
&self,
current: Ptr<T>,
new: Ptr<T>,
ord: Ordering,
_: &'scope Scope,
) -> Result<(), Ptr<'scope, T>> {
let fail_ord = strongest_failure_ordering(ord);
match self.data.compare_exchange_weak(current.data, new.data, ord, fail_ord) {
Ok(_) => Ok(()),
Err(previous) => Err(Ptr::from_data(previous)),
}
}
pub fn compare_and_swap_owned<'scope>(
&self,
current: Ptr<T>,
new: Owned<T>,
ord: Ordering,
_: &'scope Scope,
) -> Result<Ptr<'scope, T>, (Ptr<'scope, T>, Owned<T>)> {
let fail_ord = strongest_failure_ordering(ord);
match self.data.compare_exchange(current.data, new.data, ord, fail_ord) {
Ok(_) => {
let data = new.data;
mem::forget(new);
Ok(Ptr::from_data(data))
}
Err(previous) => Err((Ptr::from_data(previous), new)),
}
}
pub fn compare_and_swap_weak_owned<'scope>(
&self,
current: Ptr<T>,
new: Owned<T>,
ord: Ordering,
_: &'scope Scope,
) -> Result<Ptr<'scope, T>, (Ptr<'scope, T>, Owned<T>)> {
let fail_ord = strongest_failure_ordering(ord);
match self.data.compare_exchange_weak(current.data, new.data, ord, fail_ord) {
Ok(_) => {
let data = new.data;
mem::forget(new);
Ok(Ptr::from_data(data))
}
Err(previous) => Err((Ptr::from_data(previous), new)),
}
}
pub fn fetch_and<'scope>(&self, val: usize, ord: Ordering, _: &'scope Scope) -> Ptr<'scope, T> {
Ptr::from_data(self.data.fetch_and(val | !low_bits::<T>(), ord))
}
pub fn fetch_or<'scope>(&self, val: usize, ord: Ordering, _: &'scope Scope) -> Ptr<'scope, T> {
Ptr::from_data(self.data.fetch_or(val & low_bits::<T>(), ord))
}
pub fn fetch_xor<'scope>(&self, val: usize, ord: Ordering, _: &'scope Scope) -> Ptr<'scope, T> {
Ptr::from_data(self.data.fetch_xor(val & low_bits::<T>(), ord))
}
}
impl<T> Default for Atomic<T> {
fn default() -> Self {
Atomic::null()
}
}
#[derive(Debug)]
pub struct Owned<T> {
data: usize,
_marker: PhantomData<Box<T>>,
}
impl<T> Owned<T> {
fn from_data(data: usize) -> Self {
Owned {
data: data,
_marker: PhantomData,
}
}
pub fn new(value: T) -> Self {
Self::from_box(Box::new(value))
}
pub fn from_box(b: Box<T>) -> Self {
unsafe { Self::from_raw(Box::into_raw(b)) }
}
pub unsafe fn from_raw(raw: *mut T) -> Self {
ensure_aligned(raw);
Self::from_data(raw as usize)
}
pub fn into_ptr<'scope>(self, _: &'scope Scope) -> Ptr<'scope, T> {
let data = self.data;
mem::forget(self);
Ptr::from_data(data)
}
pub fn tag(&self) -> usize {
self.data & low_bits::<T>()
}
pub fn with_tag(self, tag: usize) -> Self {
let data = self.data;
mem::forget(self);
Self::from_data(data_with_tag::<T>(data, tag))
}
}
impl<T> Drop for Owned<T> {
fn drop(&mut self) {
let raw = (self.data & !low_bits::<T>()) as *mut T;
unsafe {
drop(Box::from_raw(raw));
}
}
}
impl<T> Deref for Owned<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*((self.data & !low_bits::<T>()) as *const T) }
}
}
impl<T> DerefMut for Owned<T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *((self.data & !low_bits::<T>()) as *mut T) }
}
}
#[derive(Debug)]
pub struct Ptr<'scope, T: 'scope> {
data: usize,
_marker: PhantomData<&'scope T>,
}
impl<'scope, T> Clone for Ptr<'scope, T> {
fn clone(&self) -> Self {
Ptr {
data: self.data,
_marker: PhantomData,
}
}
}
impl<'scope, T> Copy for Ptr<'scope, T> {}
impl<'scope, T> Ptr<'scope, T> {
pub unsafe fn destroy(self) {
drop(Box::from_raw(self.as_raw() as *mut T));
}
fn from_data(data: usize) -> Self {
Ptr {
data: data,
_marker: PhantomData,
}
}
pub fn null() -> Self {
Ptr {
data: 0,
_marker: PhantomData,
}
}
pub unsafe fn from_raw(raw: *const T) -> Self {
ensure_aligned(raw);
Ptr {
data: raw as usize,
_marker: PhantomData,
}
}
pub fn is_null(&self) -> bool {
self.as_raw().is_null()
}
pub fn as_raw(&self) -> *const T {
(self.data & !low_bits::<T>()) as *const T
}
pub unsafe fn deref(&self) -> &'scope T {
&*self.as_raw()
}
pub unsafe fn as_ref(&self) -> Option<&'scope T> {
self.as_raw().as_ref()
}
pub fn tag(&self) -> usize {
self.data & low_bits::<T>()
}
pub fn with_tag(&self, tag: usize) -> Self {
Self::from_data(data_with_tag::<T>(self.data, tag))
}
}
impl<'scope, T> Default for Ptr<'scope, T> {
fn default() -> Self {
Ptr::null()
}
}