twizzler/ptr/resolved/
resolved_tx.rs

1use std::{
2    borrow::{Borrow, BorrowMut},
3    mem::MaybeUninit,
4    ops::{Deref, DerefMut},
5};
6
7use twizzler_rt_abi::object::ObjectHandle;
8
9use super::RefMut;
10use crate::{
11    object::{RawObject, TxObject},
12    ptr::GlobalPtr,
13};
14
15pub struct TxRef<T> {
16    ptr: *mut T,
17    tx: Option<TxObject<()>>,
18    sync_on_drop: bool,
19}
20
21impl<T> TxRef<T> {
22    pub fn as_mut(&mut self) -> RefMut<'_, T> {
23        let handle = self.tx.as_ref().unwrap().handle().handle();
24        unsafe { RefMut::from_raw_parts(self.ptr, handle) }
25    }
26
27    pub unsafe fn from_raw_parts<B>(tx: TxObject<B>, ptr: *mut T) -> Self {
28        Self {
29            ptr,
30            sync_on_drop: !tx.is_nosync(),
31            tx: Some(tx.into_unit()),
32        }
33    }
34
35    #[inline]
36    pub fn offset(&self) -> u64 {
37        self.handle().ptr_local(self.ptr.cast()).unwrap() as u64
38    }
39
40    pub fn tx(&self) -> &TxObject<()> {
41        self.tx.as_ref().unwrap()
42    }
43
44    pub fn tx_mut(&mut self) -> &mut TxObject<()> {
45        self.tx.as_mut().unwrap()
46    }
47
48    pub fn into_tx(mut self) -> TxObject<()> {
49        let mut txobj = self.tx.take().unwrap();
50        if !self.sync_on_drop {
51            txobj.nosync();
52        }
53        self.nosync();
54        txobj
55    }
56
57    pub fn raw(&self) -> *mut T {
58        self.ptr
59    }
60
61    pub fn handle(&self) -> &ObjectHandle {
62        self.tx().handle()
63    }
64
65    pub fn global(&self) -> GlobalPtr<T> {
66        GlobalPtr::new(self.handle().id(), self.offset())
67    }
68
69    pub unsafe fn cast<U>(mut self) -> TxRef<U> {
70        let old_sod = self.sync_on_drop;
71        self.sync_on_drop = false;
72        let ptr = self.ptr.cast::<U>();
73        let mut new = TxRef::from_raw_parts(self.into_tx(), ptr);
74        if !old_sod {
75            new.nosync();
76        }
77        new
78    }
79
80    pub(crate) fn nosync(&mut self) {
81        self.sync_on_drop = false;
82    }
83
84    #[allow(dead_code)]
85    pub(crate) fn is_nosync(&self) -> bool {
86        !self.sync_on_drop
87    }
88}
89
90impl<T> TxRef<MaybeUninit<T>> {
91    pub fn write(mut self, val: T) -> crate::Result<TxRef<T>> {
92        unsafe {
93            let ptr = self.ptr.as_mut().unwrap_unchecked();
94            let tx = self.tx.take().unwrap();
95            let mut new = TxRef::<T>::from_raw_parts(tx, ptr.write(val));
96            if !self.sync_on_drop {
97                new.nosync();
98            }
99            self.sync_on_drop = false;
100            Ok(new)
101        }
102    }
103}
104
105impl<T> From<TxRef<T>> for GlobalPtr<T> {
106    fn from(value: TxRef<T>) -> Self {
107        GlobalPtr::new(value.handle().id(), value.offset())
108    }
109}
110
111impl<T> Deref for TxRef<T> {
112    type Target = T;
113
114    fn deref(&self) -> &Self::Target {
115        unsafe { self.ptr.as_ref().unwrap_unchecked() }
116    }
117}
118
119impl<T> DerefMut for TxRef<T> {
120    fn deref_mut(&mut self) -> &mut Self::Target {
121        unsafe { self.ptr.as_mut().unwrap_unchecked() }
122    }
123}
124
125impl<T> AsMut<T> for TxRef<T> {
126    fn as_mut(&mut self) -> &mut T {
127        &mut *self
128    }
129}
130
131impl<T> Borrow<T> for TxRef<T> {
132    fn borrow(&self) -> &T {
133        &*self
134    }
135}
136
137impl<T> BorrowMut<T> for TxRef<T> {
138    fn borrow_mut(&mut self) -> &mut T {
139        &mut *self
140    }
141}
142
143impl<T> Drop for TxRef<T> {
144    #[track_caller]
145    fn drop(&mut self) {
146        tracing::trace!(
147            "TxRef {:?} drop from {}: {} {}",
148            self.tx.as_ref().map(|t| t.id()),
149            core::panic::Location::caller(),
150            self.sync_on_drop,
151            self.tx.is_some()
152        );
153        let _ = self.tx.take().map(|mut tx| {
154            if self.sync_on_drop {
155                tx.commit()
156            } else {
157                Ok(())
158            }
159        });
160    }
161}
162
163impl<T> Into<ObjectHandle> for TxRef<T> {
164    fn into(self) -> ObjectHandle {
165        self.tx().handle().clone()
166    }
167}
168
169impl<T> Into<ObjectHandle> for &TxRef<T> {
170    fn into(self) -> ObjectHandle {
171        self.tx().handle().clone()
172    }
173}
174
175impl<T> AsRef<ObjectHandle> for TxRef<T> {
176    fn as_ref(&self) -> &ObjectHandle {
177        self.tx().handle()
178    }
179}