| 1 | |
| 2 |
|
| 3 | |
| 4 |
|
| 5 | |
| 6 |
|
| 7 | use crate::alloc::{AllocError, Flags};
|
| 8 | use crate::prelude::*;
|
| 9 | use crate::sync::atomic::{ordering, AtomicFlag};
|
| 10 | use crate::sync::{Arc, ArcBorrow, UniqueArc};
|
| 11 | use core::marker::PhantomPinned;
|
| 12 | use core::ops::Deref;
|
| 13 | use core::pin::Pin;
|
| 14 |
|
| 15 | |
| 16 | |
| 17 | |
| 18 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 | |
| 26 | |
| 27 | |
| 28 | |
| 29 | |
| 30 | |
| 31 | |
| 32 | |
| 33 | pub trait ListArcSafe<const ID: u64 = 0> {
|
| 34 | |
| 35 | |
| 36 | |
| 37 | |
| 38 | |
| 39 | |
| 40 | |
| 41 | |
| 42 | unsafe fn on_create_list_arc_from_unique(self: Pin<&mut Self>);
|
| 43 |
|
| 44 | |
| 45 | |
| 46 | |
| 47 | |
| 48 | |
| 49 | unsafe fn on_drop_list_arc(&self);
|
| 50 | }
|
| 51 |
|
| 52 | |
| 53 | |
| 54 | |
| 55 | |
| 56 | |
| 57 | pub unsafe trait TryNewListArc<const ID: u64 = 0>: ListArcSafe<ID> {
|
| 58 | |
| 59 | |
| 60 | |
| 61 | |
| 62 | |
| 63 | |
| 64 | |
| 65 | |
| 66 | |
| 67 | |
| 68 | fn try_new_list_arc(&self) -> bool;
|
| 69 | }
|
| 70 |
|
| 71 | |
| 72 | |
| 73 | |
| 74 | |
| 75 | |
| 76 | |
| 77 | |
| 78 | |
| 79 | |
| 80 | |
| 81 | |
| 82 | |
| 83 | |
| 84 | #[macro_export]
|
| 85 | #[doc(hidden)]
|
| 86 | macro_rules! impl_list_arc_safe {
|
| 87 | (impl$({$($generics:tt)*})? ListArcSafe<$num:tt> for $t:ty { untracked; } $($rest:tt)*) => {
|
| 88 | impl$(<$($generics)*>)? $crate::list::ListArcSafe<$num> for $t {
|
| 89 | unsafe fn on_create_list_arc_from_unique(self: ::core::pin::Pin<&mut Self>) {}
|
| 90 | unsafe fn on_drop_list_arc(&self) {}
|
| 91 | }
|
| 92 | $crate::list::impl_list_arc_safe! { $($rest)* }
|
| 93 | };
|
| 94 |
|
| 95 | (impl$({$($generics:tt)*})? ListArcSafe<$num:tt> for $t:ty {
|
| 96 | tracked_by $field:ident : $fty:ty;
|
| 97 | } $($rest:tt)*) => {
|
| 98 | impl$(<$($generics)*>)? $crate::list::ListArcSafe<$num> for $t {
|
| 99 | unsafe fn on_create_list_arc_from_unique(self: ::core::pin::Pin<&mut Self>) {
|
| 100 | ::pin_init::assert_pinned!($t, $field, $fty, inline);
|
| 101 |
|
| 102 | |
| 103 | let field = unsafe {
|
| 104 | ::core::pin::Pin::map_unchecked_mut(self, |me| &mut me.$field)
|
| 105 | };
|
| 106 | |
| 107 | unsafe {
|
| 108 | <$fty as $crate::list::ListArcSafe<$num>>::on_create_list_arc_from_unique(field)
|
| 109 | };
|
| 110 | }
|
| 111 | unsafe fn on_drop_list_arc(&self) {
|
| 112 | |
| 113 | |
| 114 | unsafe { <$fty as $crate::list::ListArcSafe<$num>>::on_drop_list_arc(&self.$field) };
|
| 115 | }
|
| 116 | }
|
| 117 | unsafe impl$(<$($generics)*>)? $crate::list::TryNewListArc<$num> for $t
|
| 118 | where
|
| 119 | $fty: TryNewListArc<$num>,
|
| 120 | {
|
| 121 | fn try_new_list_arc(&self) -> bool {
|
| 122 | <$fty as $crate::list::TryNewListArc<$num>>::try_new_list_arc(&self.$field)
|
| 123 | }
|
| 124 | }
|
| 125 | $crate::list::impl_list_arc_safe! { $($rest)* }
|
| 126 | };
|
| 127 |
|
| 128 | () => {};
|
| 129 | }
|
| 130 | pub use impl_list_arc_safe;
|
| 131 |
|
| 132 | |
| 133 | |
| 134 | |
| 135 | |
| 136 | |
| 137 | |
| 138 | |
| 139 | |
| 140 | |
| 141 | |
| 142 | |
| 143 | |
| 144 | |
| 145 | |
| 146 | |
| 147 | |
| 148 | |
| 149 | |
| 150 | |
| 151 | |
| 152 | |
| 153 | |
| 154 | |
| 155 | |
| 156 | |
| 157 | |
| 158 | |
| 159 | |
| 160 | |
| 161 | |
| 162 | #[repr(transparent)]
|
| 163 | #[derive(core::marker::CoercePointee)]
|
| 164 | pub struct ListArc<T, const ID: u64 = 0>
|
| 165 | where
|
| 166 | T: ListArcSafe<ID> + ?Sized,
|
| 167 | {
|
| 168 | arc: Arc<T>,
|
| 169 | }
|
| 170 |
|
| 171 | impl<T: ListArcSafe<ID>, const ID: u64> ListArc<T, ID> {
|
| 172 | |
| 173 | #[inline]
|
| 174 | pub fn new(contents: T, flags: Flags) -> Result<Self, AllocError> {
|
| 175 | Ok(Self::from(UniqueArc::new(contents, flags)?))
|
| 176 | }
|
| 177 |
|
| 178 | |
| 179 | |
| 180 | |
| 181 | |
| 182 | |
| 183 | #[inline]
|
| 184 | pub fn pin_init<E>(init: impl PinInit<T, E>, flags: Flags) -> Result<Self, E>
|
| 185 | where
|
| 186 | E: From<AllocError>,
|
| 187 | {
|
| 188 | Ok(Self::from(UniqueArc::try_pin_init(init, flags)?))
|
| 189 | }
|
| 190 |
|
| 191 | |
| 192 | |
| 193 | |
| 194 | #[inline]
|
| 195 | pub fn init<E>(init: impl Init<T, E>, flags: Flags) -> Result<Self, E>
|
| 196 | where
|
| 197 | E: From<AllocError>,
|
| 198 | {
|
| 199 | Ok(Self::from(UniqueArc::try_init(init, flags)?))
|
| 200 | }
|
| 201 | }
|
| 202 |
|
| 203 | impl<T, const ID: u64> From<UniqueArc<T>> for ListArc<T, ID>
|
| 204 | where
|
| 205 | T: ListArcSafe<ID> + ?Sized,
|
| 206 | {
|
| 207 | |
| 208 | #[inline]
|
| 209 | fn from(unique: UniqueArc<T>) -> Self {
|
| 210 | Self::from(Pin::from(unique))
|
| 211 | }
|
| 212 | }
|
| 213 |
|
| 214 | impl<T, const ID: u64> From<Pin<UniqueArc<T>>> for ListArc<T, ID>
|
| 215 | where
|
| 216 | T: ListArcSafe<ID> + ?Sized,
|
| 217 | {
|
| 218 | |
| 219 | #[inline]
|
| 220 | fn from(mut unique: Pin<UniqueArc<T>>) -> Self {
|
| 221 | |
| 222 | unsafe { T::on_create_list_arc_from_unique(unique.as_mut()) };
|
| 223 | let arc = Arc::from(unique);
|
| 224 | |
| 225 | |
| 226 | unsafe { Self::transmute_from_arc(arc) }
|
| 227 | }
|
| 228 | }
|
| 229 |
|
| 230 | impl<T, const ID: u64> ListArc<T, ID>
|
| 231 | where
|
| 232 | T: ListArcSafe<ID> + ?Sized,
|
| 233 | {
|
| 234 | |
| 235 | |
| 236 | |
| 237 | #[inline]
|
| 238 | pub fn pair_from_unique<const ID2: u64>(unique: UniqueArc<T>) -> (Self, ListArc<T, ID2>)
|
| 239 | where
|
| 240 | T: ListArcSafe<ID2>,
|
| 241 | {
|
| 242 | Self::pair_from_pin_unique(Pin::from(unique))
|
| 243 | }
|
| 244 |
|
| 245 | |
| 246 | |
| 247 | |
| 248 | #[inline]
|
| 249 | pub fn pair_from_pin_unique<const ID2: u64>(
|
| 250 | mut unique: Pin<UniqueArc<T>>,
|
| 251 | ) -> (Self, ListArc<T, ID2>)
|
| 252 | where
|
| 253 | T: ListArcSafe<ID2>,
|
| 254 | {
|
| 255 | build_assert!(ID != ID2);
|
| 256 |
|
| 257 | |
| 258 | unsafe { <T as ListArcSafe<ID>>::on_create_list_arc_from_unique(unique.as_mut()) };
|
| 259 | |
| 260 | unsafe { <T as ListArcSafe<ID2>>::on_create_list_arc_from_unique(unique.as_mut()) };
|
| 261 |
|
| 262 | let arc1 = Arc::from(unique);
|
| 263 | let arc2 = Arc::clone(&arc1);
|
| 264 |
|
| 265 | |
| 266 | |
| 267 | unsafe {
|
| 268 | (
|
| 269 | Self::transmute_from_arc(arc1),
|
| 270 | ListArc::transmute_from_arc(arc2),
|
| 271 | )
|
| 272 | }
|
| 273 | }
|
| 274 |
|
| 275 | |
| 276 | |
| 277 | |
| 278 | pub fn try_from_arc(arc: Arc<T>) -> Result<Self, Arc<T>>
|
| 279 | where
|
| 280 | T: TryNewListArc<ID>,
|
| 281 | {
|
| 282 | if arc.try_new_list_arc() {
|
| 283 | |
| 284 | |
| 285 | Ok(unsafe { Self::transmute_from_arc(arc) })
|
| 286 | } else {
|
| 287 | Err(arc)
|
| 288 | }
|
| 289 | }
|
| 290 |
|
| 291 | |
| 292 | |
| 293 | |
| 294 | pub fn try_from_arc_borrow(arc: ArcBorrow<'_, T>) -> Option<Self>
|
| 295 | where
|
| 296 | T: TryNewListArc<ID>,
|
| 297 | {
|
| 298 | if arc.try_new_list_arc() {
|
| 299 | |
| 300 | |
| 301 | Some(unsafe { Self::transmute_from_arc(Arc::from(arc)) })
|
| 302 | } else {
|
| 303 | None
|
| 304 | }
|
| 305 | }
|
| 306 |
|
| 307 | |
| 308 | |
| 309 | |
| 310 | |
| 311 | pub fn try_from_arc_or_drop(arc: Arc<T>) -> Option<Self>
|
| 312 | where
|
| 313 | T: TryNewListArc<ID>,
|
| 314 | {
|
| 315 | match Self::try_from_arc(arc) {
|
| 316 | Ok(list_arc) => Some(list_arc),
|
| 317 | Err(arc) => Arc::into_unique_or_drop(arc).map(Self::from),
|
| 318 | }
|
| 319 | }
|
| 320 |
|
| 321 | |
| 322 | |
| 323 | |
| 324 | |
| 325 | |
| 326 | |
| 327 | #[inline]
|
| 328 | unsafe fn transmute_from_arc(arc: Arc<T>) -> Self {
|
| 329 | |
| 330 | Self { arc }
|
| 331 | }
|
| 332 |
|
| 333 | |
| 334 | |
| 335 | |
| 336 | |
| 337 | #[inline]
|
| 338 | fn transmute_to_arc(self) -> Arc<T> {
|
| 339 | |
| 340 | |
| 341 | |
| 342 | unsafe { core::mem::transmute(self) }
|
| 343 | }
|
| 344 |
|
| 345 | |
| 346 | |
| 347 | |
| 348 | |
| 349 | #[inline]
|
| 350 | pub fn into_raw(self) -> *const T {
|
| 351 | Arc::into_raw(Self::transmute_to_arc(self))
|
| 352 | }
|
| 353 |
|
| 354 | |
| 355 | |
| 356 | |
| 357 | |
| 358 | |
| 359 | |
| 360 | |
| 361 | #[inline]
|
| 362 | pub unsafe fn from_raw(ptr: *const T) -> Self {
|
| 363 | |
| 364 | let arc = unsafe { Arc::from_raw(ptr) };
|
| 365 | |
| 366 | |
| 367 | unsafe { Self::transmute_from_arc(arc) }
|
| 368 | }
|
| 369 |
|
| 370 | |
| 371 | #[inline]
|
| 372 | pub fn into_arc(self) -> Arc<T> {
|
| 373 | let arc = Self::transmute_to_arc(self);
|
| 374 | |
| 375 | unsafe { T::on_drop_list_arc(&arc) };
|
| 376 | arc
|
| 377 | }
|
| 378 |
|
| 379 | |
| 380 | #[inline]
|
| 381 | pub fn clone_arc(&self) -> Arc<T> {
|
| 382 | self.arc.clone()
|
| 383 | }
|
| 384 |
|
| 385 | |
| 386 | |
| 387 | |
| 388 | |
| 389 | |
| 390 | |
| 391 | #[inline]
|
| 392 | pub fn as_arc(&self) -> &Arc<T> {
|
| 393 | &self.arc
|
| 394 | }
|
| 395 |
|
| 396 | |
| 397 | |
| 398 | |
| 399 | |
| 400 | #[inline]
|
| 401 | pub fn as_arc_borrow(&self) -> ArcBorrow<'_, T> {
|
| 402 | self.arc.as_arc_borrow()
|
| 403 | }
|
| 404 |
|
| 405 | |
| 406 | #[inline]
|
| 407 | pub fn ptr_eq(this: &Self, other: &Self) -> bool {
|
| 408 | Arc::ptr_eq(&this.arc, &other.arc)
|
| 409 | }
|
| 410 | }
|
| 411 |
|
| 412 | impl<T, const ID: u64> Deref for ListArc<T, ID>
|
| 413 | where
|
| 414 | T: ListArcSafe<ID> + ?Sized,
|
| 415 | {
|
| 416 | type Target = T;
|
| 417 |
|
| 418 | #[inline]
|
| 419 | fn deref(&self) -> &Self::Target {
|
| 420 | self.arc.deref()
|
| 421 | }
|
| 422 | }
|
| 423 |
|
| 424 | impl<T, const ID: u64> Drop for ListArc<T, ID>
|
| 425 | where
|
| 426 | T: ListArcSafe<ID> + ?Sized,
|
| 427 | {
|
| 428 | #[inline]
|
| 429 | fn drop(&mut self) {
|
| 430 | |
| 431 | |
| 432 | unsafe { T::on_drop_list_arc(&self.arc) };
|
| 433 | }
|
| 434 | }
|
| 435 |
|
| 436 | impl<T, const ID: u64> AsRef<Arc<T>> for ListArc<T, ID>
|
| 437 | where
|
| 438 | T: ListArcSafe<ID> + ?Sized,
|
| 439 | {
|
| 440 | #[inline]
|
| 441 | fn as_ref(&self) -> &Arc<T> {
|
| 442 | self.as_arc()
|
| 443 | }
|
| 444 | }
|
| 445 |
|
| 446 | |
| 447 | |
| 448 | |
| 449 | |
| 450 | |
| 451 | #[repr(transparent)]
|
| 452 | pub struct AtomicTracker<const ID: u64 = 0> {
|
| 453 | inner: AtomicFlag,
|
| 454 | |
| 455 | _pin: PhantomPinned,
|
| 456 | }
|
| 457 |
|
| 458 | impl<const ID: u64> AtomicTracker<ID> {
|
| 459 | |
| 460 | pub fn new() -> impl PinInit<Self> {
|
| 461 | |
| 462 | |
| 463 | Self {
|
| 464 | inner: AtomicFlag::new(false),
|
| 465 | _pin: PhantomPinned,
|
| 466 | }
|
| 467 | }
|
| 468 |
|
| 469 | fn project_inner(self: Pin<&mut Self>) -> &mut AtomicFlag {
|
| 470 | |
| 471 | |
| 472 | unsafe { &mut Pin::into_inner_unchecked(self).inner }
|
| 473 | }
|
| 474 | }
|
| 475 |
|
| 476 | impl<const ID: u64> ListArcSafe<ID> for AtomicTracker<ID> {
|
| 477 | unsafe fn on_create_list_arc_from_unique(self: Pin<&mut Self>) {
|
| 478 | |
| 479 | *self.project_inner().get_mut() = true;
|
| 480 | }
|
| 481 |
|
| 482 | unsafe fn on_drop_list_arc(&self) {
|
| 483 | |
| 484 | self.inner.store(false, ordering::Release);
|
| 485 | }
|
| 486 | }
|
| 487 |
|
| 488 | |
| 489 | |
| 490 | |
| 491 | |
| 492 | |
| 493 | |
| 494 | unsafe impl<const ID: u64> TryNewListArc<ID> for AtomicTracker<ID> {
|
| 495 | fn try_new_list_arc(&self) -> bool {
|
| 496 | |
| 497 | |
| 498 | self.inner.cmpxchg(false, true, ordering::Acquire).is_ok()
|
| 499 | }
|
| 500 | }
|