pub struct Ptr<'scope, T: 'scope> { /* private fields */ }
Expand description
A pointer to an object protected by the epoch GC.
The pointer is valid for use only within 'scope
.
The pointer must be properly aligned. Since it is aligned, a tag can be stored into the unused least significant bits of the address.
Implementations§
Source§impl<'scope, T> Ptr<'scope, T>
impl<'scope, T> Ptr<'scope, T>
pub unsafe fn destroy(self)
Sourcepub fn null() -> Self
pub fn null() -> Self
Returns a new null pointer.
§Examples
use coco::epoch::Ptr;
let p = Ptr::<i32>::null();
assert!(p.is_null());
Sourcepub fn is_null(&self) -> bool
pub fn is_null(&self) -> bool
Returns true
if the pointer is null.
§Examples
use coco::epoch::{self, Atomic, Owned};
use std::sync::atomic::Ordering::SeqCst;
let a = Atomic::null();
epoch::pin(|scope| {
assert!(a.load(SeqCst, scope).is_null());
a.store_owned(Owned::new(1234), SeqCst);
assert!(!a.load(SeqCst, scope).is_null());
});
Sourcepub fn as_raw(&self) -> *const T
pub fn as_raw(&self) -> *const T
Converts the pointer to a raw pointer (without the tag).
§Examples
use coco::epoch::{self, Atomic, Owned};
use std::sync::atomic::Ordering::SeqCst;
let o = Owned::new(1234);
let raw = &*o as *const _;
let a = Atomic::from_owned(o);
epoch::pin(|scope| {
let p = a.load(SeqCst, scope);
assert_eq!(p.as_raw(), raw);
});
Sourcepub unsafe fn deref(&self) -> &'scope T
pub unsafe fn deref(&self) -> &'scope T
Dereferences the pointer.
Returns a reference to the pointee that is valid in 'scope
.
§Safety
Dereferencing a pointer to an invalid object is not a concern, since invalid Ptr
s
can only be constructed via other unsafe functions.
However, this method doesn’t check whether the pointer is null, so dereferencing a null pointer is unsafe.
Another source of unsafety is the possibility of unsynchronized reads to the objects. For example, the following scenario is unsafe:
- A thread stores a new object:
a.store_owned(Owned::new(10), Relaxed)
- Another thread reads it:
*a.load(Relaxed, scope).as_ref().unwrap()
The problem is that relaxed orderings don’t synchronize initialization of the object with
the read from the second thread. This is a data race. A possible solution would be to use
Release
and Acquire
orderings (or stronger).
§Examples
use coco::epoch::{self, Atomic};
use std::sync::atomic::Ordering::SeqCst;
let a = Atomic::new(1234);
epoch::pin(|scope| {
let p = a.load(SeqCst, scope);
unsafe {
assert_eq!(p.deref(), &1234);
}
});
Sourcepub unsafe fn as_ref(&self) -> Option<&'scope T>
pub unsafe fn as_ref(&self) -> Option<&'scope T>
Converts the pointer to a reference.
Returns None
if the pointer is null, or else a reference to the object wrapped in Some
.
§Safety
This method checks whether the pointer is null, and if not, assumes that it’s pointing to a
valid object. However, this is not considered a source of unsafety because invalid Ptr
s
can only be constructed via other unsafe functions.
The only source of unsafety is the possibility of unsynchronized reads to the objects. For example, the following scenario is unsafe:
- A thread stores a new object:
a.store_owned(Owned::new(10), Relaxed)
- Another thread reads it:
*a.load(Relaxed, scope).as_ref().unwrap()
The problem is that relaxed orderings don’t synchronize initialization of the object with
the read from the second thread. This is a data race. A possible solution would be to use
Release
and Acquire
orderings (or stronger).
§Examples
use coco::epoch::{self, Atomic};
use std::sync::atomic::Ordering::SeqCst;
let a = Atomic::new(1234);
epoch::pin(|scope| {
let p = a.load(SeqCst, scope);
unsafe {
assert_eq!(p.as_ref(), Some(&1234));
}
});
Sourcepub fn tag(&self) -> usize
pub fn tag(&self) -> usize
Returns the tag stored within the pointer.
§Examples
use coco::epoch::{self, Atomic, Owned};
use std::sync::atomic::Ordering::SeqCst;
let a = Atomic::from_owned(Owned::new(0u32).with_tag(3));
epoch::pin(|scope| {
let p = a.load(SeqCst, scope);
assert_eq!(p.tag(), 3);
});
Sourcepub fn with_tag(&self, tag: usize) -> Self
pub fn with_tag(&self, tag: usize) -> Self
Returns the same pointer, but tagged with tag
.
§Examples
use coco::epoch::{self, Atomic};
use std::sync::atomic::Ordering::SeqCst;
let a = Atomic::new(0u32);
epoch::pin(|scope| {
let p1 = a.load(SeqCst, scope);
let p2 = p1.with_tag(3);
assert_eq!(p1.tag(), 0);
assert_eq!(p2.tag(), 3);
assert_eq!(p1.as_raw(), p2.as_raw());
});
Trait Implementations§
impl<'scope, T> Copy for Ptr<'scope, T>
Auto Trait Implementations§
impl<'scope, T> Freeze for Ptr<'scope, T>
impl<'scope, T> RefUnwindSafe for Ptr<'scope, T>where
T: RefUnwindSafe,
impl<'scope, T> Send for Ptr<'scope, T>where
T: Sync,
impl<'scope, T> Sync for Ptr<'scope, T>where
T: Sync,
impl<'scope, T> Unpin for Ptr<'scope, T>
impl<'scope, T> UnwindSafe for Ptr<'scope, T>where
T: RefUnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more