starnix_lifecycle/
delayed_releaser.rs

1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use starnix_types::ownership::ReleaseGuard;
6use std::marker::PhantomData;
7use std::mem::ManuallyDrop;
8use std::ops::Deref;
9
10pub trait ReleaserAction<T> {
11    fn release(t: ReleaseGuard<T>);
12}
13
14/// Wrapper around `FileObject` that ensures that a unused `FileObject` is added to the current
15/// delayed releasers to be released at the next release point.
16pub struct ObjectReleaser<T, F: ReleaserAction<T>>(ManuallyDrop<ReleaseGuard<T>>, PhantomData<F>);
17
18impl<T: Default, F: ReleaserAction<T>> Default for ObjectReleaser<T, F> {
19    fn default() -> Self {
20        Self::from(T::default())
21    }
22}
23
24impl<T, F: ReleaserAction<T>> From<T> for ObjectReleaser<T, F> {
25    fn from(object: T) -> Self {
26        Self(ManuallyDrop::new(object.into()), Default::default())
27    }
28}
29
30impl<T, F: ReleaserAction<T>> Drop for ObjectReleaser<T, F> {
31    fn drop(&mut self) {
32        // SAFETY
33        // The `ManuallyDrop` is only ever extracted in this `drop` method, so it is guaranteed
34        // that it still exists.
35        #[allow(
36            clippy::undocumented_unsafe_blocks,
37            reason = "Force documented unsafe blocks in Starnix"
38        )]
39        let object = unsafe { ManuallyDrop::take(&mut self.0) };
40        F::release(object);
41    }
42}
43
44impl<T: std::fmt::Debug, F: ReleaserAction<T>> std::fmt::Debug for ObjectReleaser<T, F> {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        self.deref().fmt(f)
47    }
48}
49
50impl<T, F: ReleaserAction<T>> std::ops::Deref for ObjectReleaser<T, F> {
51    type Target = T;
52
53    fn deref(&self) -> &Self::Target {
54        self.0.deref()
55    }
56}
57
58impl<T, F: ReleaserAction<T>> std::borrow::Borrow<T> for ObjectReleaser<T, F> {
59    fn borrow(&self) -> &T {
60        self.deref()
61    }
62}
63
64impl<T, F: ReleaserAction<T>> std::convert::AsRef<T> for ObjectReleaser<T, F> {
65    fn as_ref(&self) -> &T {
66        self.deref()
67    }
68}