1#![allow(dead_code)]
2
3use std::{
4 fmt::{self, Debug},
5 hash::Hash,
6 io,
7 mem::{self, ManuallyDrop},
8 ops::{Deref, DerefMut},
9 pin::Pin,
10 task::Waker,
11};
12
13use compio_buf::BufResult;
14use thin_cell::unsync::{Ref, ThinCell};
15
16use crate::{Extra, OpCode, PushEntry};
17
18#[repr(C)]
23pub(crate) struct RawOp<T: ?Sized> {
24 extra: Extra,
33 cancelled: bool,
35 result: PushEntry<Option<Waker>, io::Result<usize>>,
36 pub(crate) op: T,
37}
38
39impl<T: ?Sized> RawOp<T> {
40 pub fn extra(&self) -> &Extra {
41 &self.extra
42 }
43
44 pub fn extra_mut(&mut self) -> &mut Extra {
45 &mut self.extra
46 }
47
48 fn pinned_op(&mut self) -> Pin<&mut T> {
49 unsafe { Pin::new_unchecked(&mut self.op) }
51 }
52
53 #[cfg(io_uring)]
54 pub fn wake_by_ref(&mut self) {
55 if let PushEntry::Pending(Some(w)) = &self.result {
56 w.wake_by_ref();
57 }
58 }
59}
60
61#[cfg(windows)]
62impl<T: OpCode + ?Sized> RawOp<T> {
63 pub fn operate_blocking(&mut self) -> io::Result<usize> {
68 use std::task::Poll;
69
70 let optr = self.extra_mut().optr();
71 let op = self.pinned_op();
72 let res = unsafe { op.operate(optr.cast()) };
73 match res {
74 Poll::Pending => unreachable!("this operation is not overlapped"),
75 Poll::Ready(res) => res,
76 }
77 }
78}
79
80impl<T: ?Sized> Debug for RawOp<T> {
81 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
82 f.debug_struct("RawOp")
83 .field("extra", &self.extra)
84 .field("cancelled", &self.cancelled)
85 .field("result", &self.result)
86 .field("op", &"<...>")
87 .finish()
88 }
89}
90
91#[repr(transparent)]
93pub struct Key<T> {
94 erased: ErasedKey,
95 _p: std::marker::PhantomData<T>,
96}
97
98impl<T> Unpin for Key<T> {}
99
100impl<T> Clone for Key<T> {
101 fn clone(&self) -> Self {
102 Self {
103 erased: self.erased.clone(),
104 _p: std::marker::PhantomData,
105 }
106 }
107}
108
109impl<T> Debug for Key<T> {
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 write!(f, "Key({})", self.erased.inner.as_ptr() as usize)
112 }
113}
114
115impl<T> Key<T> {
116 pub(crate) fn into_raw(self) -> usize {
117 self.erased.into_raw()
118 }
119
120 pub(crate) fn erase(self) -> ErasedKey {
121 self.erased
122 }
123
124 pub(crate) fn take_result(self) -> BufResult<usize, T> {
131 unsafe { self.erased.take_result::<T>() }
133 }
134}
135
136impl<T: OpCode + 'static> Key<T> {
137 pub(crate) fn new(op: T, extra: impl Into<Extra>) -> Self {
139 let erased = ErasedKey::new(op, extra.into());
140
141 Self {
142 erased,
143 _p: std::marker::PhantomData,
144 }
145 }
146
147 pub(crate) fn set_extra(&self, extra: impl Into<Extra>) {
148 self.borrow().extra = extra.into();
149 }
150}
151
152impl<T> Deref for Key<T> {
153 type Target = ErasedKey;
154
155 fn deref(&self) -> &Self::Target {
156 &self.erased
157 }
158}
159
160impl<T> DerefMut for Key<T> {
161 fn deref_mut(&mut self) -> &mut Self::Target {
162 &mut self.erased
163 }
164}
165
166#[derive(Clone)]
172#[repr(transparent)]
173pub struct ErasedKey {
174 inner: ThinCell<RawOp<dyn OpCode>>,
175}
176
177impl PartialEq for ErasedKey {
178 fn eq(&self, other: &Self) -> bool {
179 self.inner.ptr_eq(&other.inner)
180 }
181}
182
183impl Eq for ErasedKey {}
184
185impl Hash for ErasedKey {
186 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
187 (self.inner.as_ptr() as usize).hash(state)
188 }
189}
190
191impl Unpin for ErasedKey {}
192
193impl std::borrow::Borrow<usize> for ErasedKey {
194 fn borrow(&self) -> &usize {
195 unsafe { std::mem::transmute(&self.inner) }
197 }
198}
199
200impl ErasedKey {
201 pub(crate) fn new<T: OpCode + 'static>(op: T, extra: Extra) -> Self {
203 let raw_op = RawOp {
204 extra,
205 cancelled: false,
206 result: PushEntry::Pending(None),
207 op,
208 };
209 let inner = unsafe { ThinCell::new_unsize(raw_op, |p| p as _) };
211 Self { inner }
212 }
213
214 pub(crate) unsafe fn from_raw(user_data: usize) -> Self {
221 let inner = unsafe { ThinCell::from_raw(user_data as *mut ()) };
222 Self { inner }
223 }
224
225 #[cfg(windows)]
232 pub(crate) unsafe fn from_optr(optr: *mut crate::sys::Overlapped) -> Self {
233 let ptr = unsafe { optr.cast::<usize>().offset(-2).cast() };
234 let inner = unsafe { ThinCell::from_raw(ptr) };
235 Self { inner }
236 }
237
238 #[cfg(windows)]
240 pub(crate) fn into_optr(self) -> *mut crate::sys::Overlapped {
241 unsafe { self.inner.leak().cast::<usize>().add(2).cast() }
242 }
243
244 pub(crate) fn as_raw(&self) -> usize {
249 self.inner.as_ptr() as _
250 }
251
252 pub(crate) fn into_raw(self) -> usize {
254 self.inner.leak() as _
255 }
256
257 #[inline]
258 pub(crate) fn borrow(&self) -> Ref<'_, RawOp<dyn OpCode>> {
259 self.inner.borrow()
260 }
261
262 pub(crate) fn set_cancelled(&self) -> bool {
264 let mut op = self.borrow();
265 mem::replace(&mut op.cancelled, true)
266 }
267
268 pub(crate) fn has_result(&self) -> bool {
270 self.borrow().result.is_ready()
271 }
272
273 pub(crate) fn is_unique(&self) -> bool {
275 ThinCell::count(&self.inner) == 1
276 }
277
278 pub(crate) fn set_result(&self, res: io::Result<usize>) {
280 let mut this = self.borrow();
281 #[cfg(io_uring)]
282 {
283 let this = &mut *this;
284 if this.extra.is_iour() {
285 unsafe {
286 Pin::new_unchecked(&mut this.op).set_result(&res, &this.extra);
287 }
288 }
289 }
290 if let PushEntry::Pending(Some(w)) =
291 std::mem::replace(&mut this.result, PushEntry::Ready(res))
292 {
293 w.wake();
294 }
295 }
296
297 pub(crate) fn swap_extra(&self, extra: Extra) -> Extra {
300 std::mem::replace(&mut self.borrow().extra, extra)
301 }
302
303 pub(crate) fn set_waker(&self, waker: &Waker) {
305 let PushEntry::Pending(w) = &mut self.borrow().result else {
306 return;
307 };
308
309 if w.as_ref().is_some_and(|w| w.will_wake(waker)) {
310 return;
311 }
312
313 *w = Some(waker.clone());
314 }
315
316 unsafe fn take_result<T>(self) -> BufResult<usize, T> {
327 let this = unsafe { self.inner.downcast_unchecked::<RawOp<T>>() };
329 let op = this.try_unwrap().map_err(|_| ()).expect("Key not unique");
330 let res = op.result.take_ready().expect("Result not ready");
331 BufResult(res, op.op)
332 }
333
334 pub(crate) unsafe fn freeze(self) -> FrozenKey {
345 FrozenKey {
346 inner: ManuallyDrop::new(self),
347 }
348 }
349}
350
351impl Debug for ErasedKey {
352 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
353 write!(f, "ErasedKey({})", self.inner.as_ptr() as usize)
354 }
355}
356
357#[repr(transparent)]
361pub(crate) struct FrozenKey {
362 inner: ManuallyDrop<ErasedKey>,
363}
364
365impl FrozenKey {
366 pub fn as_mut(&mut self) -> &mut RawOp<dyn OpCode> {
367 unsafe { self.inner.inner.borrow_unchecked() }
368 }
369
370 pub fn pinned_op(&mut self) -> Pin<&mut dyn OpCode> {
371 self.as_mut().pinned_op()
372 }
373
374 pub fn into_inner(self) -> ErasedKey {
375 ManuallyDrop::into_inner(self.inner)
376 }
377}
378
379unsafe impl Send for FrozenKey {}
380unsafe impl Sync for FrozenKey {}
381
382pub(crate) struct BorrowedKey(ManuallyDrop<ErasedKey>);
388
389impl BorrowedKey {
390 pub unsafe fn from_raw(user_data: usize) -> Self {
391 let key = unsafe { ErasedKey::from_raw(user_data) };
392 Self(ManuallyDrop::new(key))
393 }
394
395 pub fn upgrade(self) -> ErasedKey {
396 ManuallyDrop::into_inner(self.0)
397 }
398}
399
400impl Deref for BorrowedKey {
401 type Target = ErasedKey;
402
403 fn deref(&self) -> &Self::Target {
404 &self.0
405 }
406}
407
408pub trait RefExt {
409 fn pinned_op(&mut self) -> Pin<&mut dyn OpCode>;
410}
411
412impl RefExt for Ref<'_, RawOp<dyn OpCode>> {
413 fn pinned_op(&mut self) -> Pin<&mut dyn OpCode> {
414 self.deref_mut().pinned_op()
415 }
416}
417
418#[cfg(test)]
419mod test {
420 use std::borrow::Borrow;
421
422 use compio_buf::BufResult;
423
424 use crate::{Proactor, key::ErasedKey, op::Asyncify};
425
426 #[test]
427 fn test_key_borrow() {
428 let driver = Proactor::new().unwrap();
429 let extra = driver.default_extra();
430 let key = ErasedKey::new(Asyncify::new(|| BufResult(Ok(0), [0u8])), extra);
431 assert_eq!(&key.as_raw(), Borrow::<usize>::borrow(&key));
432 }
433}