From f6f72171fbfe66ce549bb8ecb536818c4452fc3d Mon Sep 17 00:00:00 2001 From: William Wen Date: Tue, 14 May 2024 18:13:01 +0800 Subject: [PATCH 1/3] feat: support into_inner for Arc --- src/sync/arc.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/sync/arc.rs b/src/sync/arc.rs index 2348291..1d00076 100644 --- a/src/sync/arc.rs +++ b/src/sync/arc.rs @@ -54,6 +54,27 @@ impl Arc { Err(_) => unreachable!(), } } + + /// Returns the inner value, if the `Arc` has exactly one strong reference. + #[track_caller] + pub fn into_inner(this: Arc) -> Option { + // work around our inability to destruct the object normally, + // because of the `Drop` presense. + this.obj.ref_dec(location!()); + this.unregister(); + + let (obj, value) = unsafe { + let obj = ptr::read(&this.obj); + let value = ptr::read(&this.value); + + mem::forget(this); + + (obj, value) + }; + + let _ = std::sync::Arc::into_inner(obj); + std::sync::Arc::into_inner(value) + } } impl Arc { From 3293c50bd5a5b9f27abc9af03f7a3c40f548e1aa Mon Sep 17 00:00:00 2001 From: William Wen Date: Tue, 14 May 2024 18:24:06 +0800 Subject: [PATCH 2/3] fix --- src/sync/arc.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/sync/arc.rs b/src/sync/arc.rs index 1d00076..881075f 100644 --- a/src/sync/arc.rs +++ b/src/sync/arc.rs @@ -60,9 +60,6 @@ impl Arc { pub fn into_inner(this: Arc) -> Option { // work around our inability to destruct the object normally, // because of the `Drop` presense. - this.obj.ref_dec(location!()); - this.unregister(); - let (obj, value) = unsafe { let obj = ptr::read(&this.obj); let value = ptr::read(&this.value); @@ -72,8 +69,19 @@ impl Arc { (obj, value) }; - let _ = std::sync::Arc::into_inner(obj); - std::sync::Arc::into_inner(value) + obj.ref_dec(location!()); + + if std::sync::Arc::into_inner(obj).is_some() { + // unregister + rt::execution(|e| { + e.arc_objs + .remove(&std::sync::Arc::as_ptr(&value).cast()) + .expect("Arc object was removed before dropping last Arc"); + }); + Some(std::sync::Arc::into_inner(value).unwrap()) + } else { + None + } } } From 4edf9435cc50c9c1e913c8dea9c0e0e0fb3cb974 Mon Sep 17 00:00:00 2001 From: William Wen Date: Tue, 14 May 2024 19:21:42 +0800 Subject: [PATCH 3/3] use ref_dec to sync --- src/sync/arc.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/sync/arc.rs b/src/sync/arc.rs index 881075f..a5171da 100644 --- a/src/sync/arc.rs +++ b/src/sync/arc.rs @@ -69,9 +69,7 @@ impl Arc { (obj, value) }; - obj.ref_dec(location!()); - - if std::sync::Arc::into_inner(obj).is_some() { + if obj.ref_dec(location!()) { // unregister rt::execution(|e| { e.arc_objs