Skip to content

Commit

Permalink
rust: types: extend Opaque documentation
Browse files Browse the repository at this point in the history
Update the `Opaque` documentation and add an example as proposed by
Miguel Ojeda in [1]. The documentation update is mainly taken from
Benno Lossin's description [2].

Cc: Nell Shamrell-Harrington <[email protected]>
Suggested-by: Miguel Ojeda <[email protected]>
Link: https://rust-for-linux.zulipchat.com/#narrow/stream/291565/topic/x/near/467478085 [1]
Link: https://rust-for-linux.zulipchat.com/#narrow/stream/291565/topic/x/near/470498289 [2]
Co-developed-by: Benno Lossin <[email protected]>
Signed-off-by: Benno Lossin <[email protected]>
Signed-off-by: Dirk Behme <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ Used `expect`. Rewrapped docs. Added intra-doc link. Formatted
  example. Reworded to fix tag typo/order. Fixed `&mut` formatting
  as discussed. Added Benno's SOB and CDB as discussed. Shortened
  links. - Miguel ]
Signed-off-by: Miguel Ojeda <[email protected]>
  • Loading branch information
dirkbehme authored and ojeda committed Oct 24, 2024
1 parent 28e8483 commit 718c406
Showing 1 changed file with 52 additions and 1 deletion.
53 changes: 52 additions & 1 deletion rust/kernel/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,58 @@ impl<T, F: FnOnce(T)> Drop for ScopeGuard<T, F> {

/// Stores an opaque value.
///
/// This is meant to be used with FFI objects that are never interpreted by Rust code.
/// `Opaque<T>` is meant to be used with FFI objects that are never interpreted by Rust code.
///
/// It is used to wrap structs from the C side, like for example `Opaque<bindings::mutex>`.
/// It gets rid of all the usual assumptions that Rust has for a value:
///
/// * The value is allowed to be uninitialized (for example have invalid bit patterns: `3` for a
/// [`bool`]).
/// * The value is allowed to be mutated, when a `&Opaque<T>` exists on the Rust side.
/// * No uniqueness for mutable references: it is fine to have multiple `&mut Opaque<T>` point to
/// the same value.
/// * The value is not allowed to be shared with other threads (i.e. it is `!Sync`).
///
/// This has to be used for all values that the C side has access to, because it can't be ensured
/// that the C side is adhering to the usual constraints that Rust needs.
///
/// Using `Opaque<T>` allows to continue to use references on the Rust side even for values shared
/// with C.
///
/// # Examples
///
/// ```
/// # #![expect(unreachable_pub, clippy::disallowed_names)]
/// use kernel::types::Opaque;
/// # // Emulate a C struct binding which is from C, maybe uninitialized or not, only the C side
/// # // knows.
/// # mod bindings {
/// # pub struct Foo {
/// # pub val: u8,
/// # }
/// # }
///
/// // `foo.val` is assumed to be handled on the C side, so we use `Opaque` to wrap it.
/// pub struct Foo {
/// foo: Opaque<bindings::Foo>,
/// }
///
/// impl Foo {
/// pub fn get_val(&self) -> u8 {
/// let ptr = Opaque::get(&self.foo);
///
/// // SAFETY: `Self` is valid from C side.
/// unsafe { (*ptr).val }
/// }
/// }
///
/// // Create an instance of `Foo` with the `Opaque` wrapper.
/// let foo = Foo {
/// foo: Opaque::new(bindings::Foo { val: 0xdb }),
/// };
///
/// assert_eq!(foo.get_val(), 0xdb);
/// ```
#[repr(transparent)]
pub struct Opaque<T> {
value: UnsafeCell<MaybeUninit<T>>,
Expand Down

0 comments on commit 718c406

Please sign in to comment.