@@ -8,7 +8,7 @@ use crate::{
88 bindings,
99 error:: { Error , Result } ,
1010 str:: CStr ,
11- types:: { ARef , Opaque } ,
11+ types:: { ARef , NotThreadSafe , Opaque } ,
1212} ;
1313use core:: { fmt, marker:: PhantomData , ptr} ;
1414
@@ -256,6 +256,35 @@ impl<Ctx: DeviceContext> Device<Ctx> {
256256 // SAFETY: By the invariant of `CStr`, `name` is null-terminated.
257257 unsafe { bindings:: device_property_present ( self . as_raw ( ) . cast_const ( ) , name. as_char_ptr ( ) ) }
258258 }
259+
260+ /// Locks the [`Device`] for exclusive access.
261+ pub fn lock ( & self ) -> Guard < ' _ , Ctx > {
262+ // SAFETY: `self` is always valid by the type invariant.
263+ unsafe { bindings:: device_lock ( self . as_raw ( ) ) } ;
264+
265+ Guard {
266+ dev : self ,
267+ _not_send : NotThreadSafe ,
268+ }
269+ }
270+ }
271+
272+ /// A lock guard.
273+ ///
274+ /// The lock is unlocked when the guard goes out of scope.
275+ #[ must_use = "the lock unlocks immediately when the guard is unused" ]
276+ pub struct Guard < ' a , Ctx : DeviceContext = Normal > {
277+ dev : & ' a Device < Ctx > ,
278+ _not_send : NotThreadSafe ,
279+ }
280+
281+ impl < Ctx : DeviceContext > Drop for Guard < ' _ , Ctx > {
282+ fn drop ( & mut self ) {
283+ // SAFETY:
284+ // - `self.xa.xa` is always valid by the type invariant.
285+ // - The caller holds the lock, so it is safe to unlock it.
286+ unsafe { bindings:: device_unlock ( self . dev . as_raw ( ) ) } ;
287+ }
259288}
260289
261290// SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic
0 commit comments