odem_rs_core/continuation/
adapter.rs1use core::{marker::PhantomData, mem::offset_of, ptr::NonNull};
2
3use intrusive_collections::{DefaultLinkOps, LinkOps};
4
5use super::{Continuation, Link};
6
7use crate::{
8 config::Config,
9 ptr::{IntrusivelyCounted, Irc},
10};
11
12pub struct Adapter<C: ?Sized + Config, P = Irc<Continuation<'static, C>>> {
18 link_ops: <Link as DefaultLinkOps>::Ops,
20 pointer_ops: PointerOps<Continuation<'static, C>, P>,
25}
26
27impl<C: ?Sized + Config, P> Adapter<C, P> {
28 pub const NEW: Self = Adapter {
32 link_ops: <Link as DefaultLinkOps>::NEW,
33 pointer_ops: PointerOps(PhantomData),
34 };
35}
36
37impl<C: ?Sized + Config, P> Default for Adapter<C, P> {
38 fn default() -> Self {
39 Self::NEW
40 }
41}
42
43impl<C: ?Sized + Config, P> Clone for Adapter<C, P> {
44 fn clone(&self) -> Self {
45 *self
46 }
47}
48
49impl<C: ?Sized + Config, P> Copy for Adapter<C, P> {}
50
51unsafe impl<C, P> intrusive_collections::Adapter for Adapter<C, P>
52where
53 C: ?Sized + Config,
54 P: From<Irc<Continuation<'static, C>>> + Into<Irc<Continuation<'static, C>>>,
55{
56 type LinkOps = <Link as DefaultLinkOps>::Ops;
57 type PointerOps = PointerOps<Continuation<'static, C>, P>;
58
59 unsafe fn get_value(
60 &self,
61 link: <Self::LinkOps as LinkOps>::LinkPtr,
62 ) -> *const Continuation<'static, C> {
63 intrusive_collections::container_of!(link.as_ptr(), Continuation<'static, C>, hook)
64 }
65
66 unsafe fn get_link(
67 &self,
68 value: *const Continuation<'static, C>,
69 ) -> <Self::LinkOps as LinkOps>::LinkPtr {
70 unsafe {
71 let ptr = (value as *const u8).add(offset_of!(Continuation<'static, C>, hook));
72 NonNull::new_unchecked(ptr as *mut _)
73 }
74 }
75
76 fn link_ops(&self) -> &Self::LinkOps {
77 &self.link_ops
78 }
79
80 fn link_ops_mut(&mut self) -> &mut Self::LinkOps {
81 &mut self.link_ops
82 }
83
84 fn pointer_ops(&self) -> &Self::PointerOps {
85 &self.pointer_ops
86 }
87}
88
89pub struct PointerOps<V, P>(PhantomData<(V, P)>);
92
93impl<V, P> PointerOps<V, P> {
94 pub const NEW: Self = PointerOps(PhantomData);
96}
97
98impl<V, P> Clone for PointerOps<V, P> {
99 fn clone(&self) -> Self {
100 *self
101 }
102}
103
104impl<V, P> Copy for PointerOps<V, P> {}
105
106unsafe impl<V, P> intrusive_collections::PointerOps for PointerOps<V, P>
107where
108 V: IntrusivelyCounted,
109 P: From<Irc<V>> + Into<Irc<V>>,
110{
111 type Value = V;
112 type Pointer = P;
113
114 unsafe fn from_raw(&self, value: *const V) -> P {
115 unsafe { P::from(Irc::from_raw(NonNull::new_unchecked(value as *mut V))) }
116 }
117
118 fn into_raw(&self, ptr: P) -> *const V {
119 Irc::into_raw(P::into(ptr)).as_ptr() as *const V
120 }
121}
122
123#[macro_export]
129#[doc(hidden)]
130macro_rules! intrusive_adapter_newtype {
131 () => {};
132
133 ($name:ident) => {
134 unsafe impl<C: ?Sized + Config> ::intrusive_collections::Adapter for $name<C> {
135 type LinkOps = <$crate::continuation::Adapter<C, $crate::calendar::IdleOnDrop<C>> as ::intrusive_collections::Adapter>::LinkOps;
136 type PointerOps = <$crate::continuation::Adapter<C, $crate::calendar::IdleOnDrop<C>> as ::intrusive_collections::Adapter>::PointerOps;
137
138 #[inline]
139 unsafe fn get_value(&self, link: <Self::LinkOps as ::intrusive_collections::LinkOps>::LinkPtr) -> *const <Self::PointerOps as ::intrusive_collections::PointerOps>::Value {
140 unsafe { self.0.get_value(link) }
141 }
142
143 #[inline]
144 unsafe fn get_link(&self, value: *const <Self::PointerOps as ::intrusive_collections::PointerOps>::Value) -> <Self::LinkOps as ::intrusive_collections::LinkOps>::LinkPtr {
145 unsafe { self.0.get_link(value) }
146 }
147
148 #[inline]
149 fn link_ops(&self) -> &Self::LinkOps {
150 self.0.link_ops()
151 }
152
153 #[inline]
154 fn link_ops_mut(&mut self) -> &mut Self::LinkOps {
155 self.0.link_ops_mut()
156 }
157
158 #[inline]
159 fn pointer_ops(&self) -> &Self::PointerOps {
160 self.0.pointer_ops()
161 }
162 }
163 };
164
165 ($name:ident, $($tail:ident),*) => {
166 $crate::intrusive_adapter_newtype!($name);
167 $crate::intrusive_adapter_newtype!($($tail),*);
168 };
169
170 ($($name:ident,)+) => {
171 $crate::intrusive_adapter_newtype!($($name),*);
172 };
173}