twizzler/ptr/resolved/
resolved_tx.rs1use 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}