Skip to main content

COpaque

Struct COpaque 

Source
pub struct COpaque<T> {
    inner: UnsafePinned<MaybeUninit<T>>,
}
Expand description

A wrapper for an opaque C object.

Some libraries like UNIX’s pthread have data types that must be treated as entirely opaque. Soundly wrapping these types is very hard since Rust’s operational semantics are much stricter when it comes to e.g. the initialization state of data types and pointer aliasing. For instance, a function like pthread_mutexattr_init might not fully initialize the libc::pthread_mutexattr_t passed to it, so doing e.g.

let mut attr = MaybeUninit::uninit();
pthread_mutexattr_init(attr.as_mut_ptr());
let attr = attr.assume_init();

is unsound. Another example: on platforms like macOS a pthread_mutex_t cannot be moved because the implementation will dynamically align some inner fields to a higher alignment than required by the definition. And furthermore, some implementations (e.g. AIX) of pthread_cond_t use intrinsically linked lists, and hence doing

pub struct Condvar(UnsafeCell<libc::pthread_cont_t>);

/* initialization and usage omitted for brevity */

impl Drop for Condvar {
    fn drop(&mut self) {
        unsafe { libc::pthread_cond_destroy(self.0.get()) };
    }
}

results in undefined behaviour (even when utilizing Pin to ensure immovability) because the creation of the &mut Condvar passed to drop invalidates other pointers in the linked list.

COpaque helps with avoiding all these caveats:

  • it wraps the inner value in MaybeUninit and thus is entirely oblivious of its initialization state.
  • COpaque::get takes a Pin and thus prevents accidental moves.
  • it utilizes UnsafePinned to relax the aliasing guarantees of mutable references to the COpaque.

The only way to access the inner value is via COpaque::get. It returns a pointer which should be directly passed to the platform functions.

In effect, a pinned instance of this wrapper acts very much like a C variable.

Fields§

§inner: UnsafePinned<MaybeUninit<T>>

Implementations§

Source§

impl<T> COpaque<T>

Source

pub fn uninit() -> COpaque<T>

Creates an uninitialized C-like storage for T.

If you’d write

T var;

in C, the equivalent Rust code is

let var = pin!(COpaque::uninit());
Source

pub fn zeroed() -> COpaque<T>

Creates a zero-initialized C-like storage for T.

If you’d write

T var = {};

in C, the equivalent Rust code is

let var = pin!(COpaque::zeroed());
Source

pub fn new(initializer: T) -> COpaque<T>

Creates a pre-initialized C-like storage for T.

If you’d write

T var = T_INITIALIZER;

in C, the equivalent Rust code is

let var = pin!(COpaque::new(T_INITIALIZER));
Source

pub fn get(self: Pin<&Self>) -> *mut T

Gets a pointer to the value.

Use this as a replacement for C’s ampersand operator.

Auto Trait Implementations§

§

impl<T> !Freeze for COpaque<T>

§

impl<T> !RefUnwindSafe for COpaque<T>

§

impl<T> !Unpin for COpaque<T>

§

impl<T> !UnsafeUnpin for COpaque<T>

§

impl<T> Send for COpaque<T>

§

impl<T> Sync for COpaque<T>

§

impl<T> UnwindSafe for COpaque<T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> SizeHint for T
where T: ?Sized,

Source§

default fn lower_bound(&self) -> usize

🔬This is a nightly-only experimental API. (core_io_internals)
Returns a lower bound on the number of elements this container-like item contains. For example, an array [u8; 12] could return any value between 0 and 12 inclusively as a correct implementation. Read more
Source§

default fn upper_bound(&self) -> Option<usize>

🔬This is a nightly-only experimental API. (core_io_internals)
Returns an upper bound on the number of elements this container-like item contains if it can be determined, otherwise None. Read more
Source§

final fn size_hint(&self) -> (usize, Option<usize>)

🔬This is a nightly-only experimental API. (core_io_internals)
Returns an estimate for the number of elements this container like type contains. Read more
Source§

impl<T> SizedTypeProperties for T

Source§

#[doc(hidden)]
const SIZE: usize = _

🔬This is a nightly-only experimental API. (sized_type_properties)
Source§

#[doc(hidden)]
const ALIGN: usize = _

🔬This is a nightly-only experimental API. (sized_type_properties)
Source§

#[doc(hidden)]
const ALIGNMENT: Alignment = _

🔬This is a nightly-only experimental API. (ptr_alignment_type #102070)
Source§

#[doc(hidden)]
const IS_ZST: bool = _

🔬This is a nightly-only experimental API. (sized_type_properties)
true if this type requires no storage. false if its size is greater than zero. Read more
Source§

#[doc(hidden)]
const LAYOUT: Layout = _

🔬This is a nightly-only experimental API. (sized_type_properties)
Source§

#[doc(hidden)]
const MAX_SLICE_LEN: usize = _

🔬This is a nightly-only experimental API. (sized_type_properties)
The largest safe length for a [Self]. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.