Skip to main content

fory_core/serializer/
weak.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Weak pointer serialization support for `Rc` and `Arc`.
19//!
20//! This module provides [`RcWeak<T>`] and [`ArcWeak<T>`] wrapper types that integrate
21//! Rust's `std::rc::Weak` / `std::sync::Weak` into the Fory serialization framework,
22//! with full support for:
23//
24//! - **Reference identity tracking** — weak pointers serialize as references to their
25//!   corresponding strong pointers, ensuring shared and circular references in the graph
26//!   are preserved without duplication.
27//! - **Null weak pointers** — if the strong pointer has been dropped or was never set,
28//!   the weak will serialize as a `Null` flag.
29//! - **Forward references during deserialization** — if the strong pointer appears later
30//!   in the serialized data, the weak will be resolved after deserialization using
31//!   `RefReader` callbacks.
32//!
33//! ## When to use
34//!
35//! Use these wrappers when your graph structure contains parent/child relationships
36//! or other shared edges where a strong pointer would cause a reference cycle.
37//! Storing a weak pointer avoids owning the target strongly, but serialization
38//! will preserve the link by reference ID.
39//!
40//! ## Example — Parent/Child Graph
41//!
42//! ```rust,ignore
43//! use fory_core::RcWeak;
44//! use fory_core::Fory;
45//! use std::cell::RefCell;
46//! use std::rc::Rc;
47//! use fory_derive::ForyObject;
48//!
49//! #[derive(ForyObject)]
50//! struct Node {
51//!     value: i32,
52//!     parent: RcWeak<RefCell<Node>>,
53//!     children: Vec<Rc<RefCell<Node>>>,
54//! }
55//!
56//! let mut fory = Fory::default();
57//! fory.register::<Node>(2000);
58//!
59//! let parent = Rc::new(RefCell::new(Node {
60//!     value: 1,
61//!     parent: RcWeak::new(),
62//!     children: vec![],
63//! }));
64//!
65//! let child1 = Rc::new(RefCell::new(Node {
66//!     value: 2,
67//!     parent: RcWeak::from(&parent),
68//!     children: vec![],
69//! }));
70//!
71//! let child2 = Rc::new(RefCell::new(Node {
72//!     value: 3,
73//!     parent: RcWeak::from(&parent),
74//!     children: vec![],
75//! }));
76//!
77//! parent.borrow_mut().children.push(child1);
78//! parent.borrow_mut().children.push(child2);
79//!
80//! let serialized = fory.serialize(&parent);
81//! let deserialized: Rc<RefCell<Node>> = fory.deserialize(&serialized).unwrap();
82//!
83//! assert_eq!(deserialized.borrow().children.len(), 2);
84//! for child in &deserialized.borrow().children {
85//!     let upgraded_parent = child.borrow().parent.upgrade().unwrap();
86//!     assert!(Rc::ptr_eq(&deserialized, &upgraded_parent));
87//! }
88//! ```
89//!
90//! ## Example — Arc for Multi-Threaded Graphs
91//!
92//! ```rust,ignore
93//! use fory_core::ArcWeak;
94//! use fory_core::Fory;
95//! use std::sync::{Arc, Mutex};
96//! use fory_derive::ForyObject;
97//!
98//! #[derive(ForyObject)]
99//! struct Node {
100//!     value: i32,
101//!     parent: ArcWeak<Mutex<Node>>,
102//! }
103//!
104//! let mut fory = Fory::default();
105//! fory.register::<Node>(2001);
106//!
107//! let parent = Arc::new(Mutex::new(Node { value: 1, parent: ArcWeak::new() }));
108//! let child = Arc::new(Mutex::new(Node { value: 2, parent: ArcWeak::from(&parent) }));
109//!
110//! let serialized = fory.serialize(&child);
111//! let deserialized: Arc<Mutex<Node>> = fory.deserialize(&serialized).unwrap();
112//! assert_eq!(deserialized.lock().unwrap().value, 2);
113//! ```
114//!
115//! ## Notes
116//!
117//! - These types share the same `UnsafeCell` across clones, so updating a weak in one clone
118//!   will update all of them.
119//! - During serialization, weak pointers **never serialize the target object's data directly**
120//!   — they only emit a reference to the already-serialized strong pointer, or `Null`.
121//! - During deserialization, unresolved references will be patched up by `RefReader::add_callback`
122//!   once the strong pointer becomes available.
123
124use crate::error::Error;
125use crate::resolver::context::{ReadContext, WriteContext};
126use crate::resolver::type_resolver::{TypeInfo, TypeResolver};
127use crate::serializer::{ForyDefault, Serializer};
128use crate::types::{RefFlag, RefMode, TypeId};
129use std::cell::UnsafeCell;
130use std::rc::Rc;
131use std::sync::Arc;
132
133/// A serializable wrapper around `std::rc::Weak<T>`.
134///
135/// `RcWeak<T>` is designed for use in graph-like structures where nodes may need to hold
136/// non-owning references to other nodes (e.g., parent pointers), and you still want them
137/// to round-trip through serialization while preserving reference identity.
138///
139/// Unlike a raw `Weak<T>`, cloning `RcWeak` keeps all clones pointing to the same
140/// internal `UnsafeCell`, so updates via deserialization callbacks affect all copies.
141///
142/// # Example
143/// See module-level docs for a complete graph example.
144///
145/// # Null handling
146/// If the target `Rc<T>` has been dropped or never assigned, `upgrade()` returns `None`
147/// and serialization will write a `RefFlag::Null` instead of a reference ID.
148pub struct RcWeak<T: ?Sized> {
149    // Use Rc<UnsafeCell> so that clones share the same cell
150    inner: Rc<UnsafeCell<std::rc::Weak<T>>>,
151}
152
153impl<T: ?Sized> std::fmt::Debug for RcWeak<T> {
154    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
155        f.debug_struct("RcWeak")
156            .field("strong_count", &self.strong_count())
157            .field("weak_count", &self.weak_count())
158            .finish()
159    }
160}
161
162impl<T> RcWeak<T> {
163    pub fn new() -> Self {
164        RcWeak {
165            inner: Rc::new(UnsafeCell::new(std::rc::Weak::new())),
166        }
167    }
168}
169
170impl<T: ?Sized> RcWeak<T> {
171    pub fn upgrade(&self) -> Option<Rc<T>> {
172        unsafe { (*self.inner.get()).upgrade() }
173    }
174
175    pub fn strong_count(&self) -> usize {
176        unsafe { (*self.inner.get()).strong_count() }
177    }
178
179    pub fn weak_count(&self) -> usize {
180        unsafe { (*self.inner.get()).weak_count() }
181    }
182
183    pub fn ptr_eq(&self, other: &Self) -> bool {
184        unsafe { std::rc::Weak::ptr_eq(&*self.inner.get(), &*other.inner.get()) }
185    }
186
187    pub fn update(&self, weak: std::rc::Weak<T>) {
188        unsafe {
189            *self.inner.get() = weak;
190        }
191    }
192
193    pub fn from_std(weak: std::rc::Weak<T>) -> Self {
194        RcWeak {
195            inner: Rc::new(UnsafeCell::new(weak)),
196        }
197    }
198}
199
200impl<T: ?Sized> PartialEq for RcWeak<T> {
201    fn eq(&self, other: &Self) -> bool {
202        self.ptr_eq(other)
203    }
204}
205
206impl<T: ?Sized> Eq for RcWeak<T> {}
207
208impl<T> Default for RcWeak<T> {
209    fn default() -> Self {
210        Self::new()
211    }
212}
213
214impl<T: ?Sized> Clone for RcWeak<T> {
215    fn clone(&self) -> Self {
216        // Clone the Rc, not the inner Weak - this way clones share the same cell!
217        RcWeak {
218            inner: self.inner.clone(),
219        }
220    }
221}
222
223impl<T: ?Sized> From<&Rc<T>> for RcWeak<T> {
224    fn from(rc: &Rc<T>) -> Self {
225        RcWeak::from_std(Rc::downgrade(rc))
226    }
227}
228
229unsafe impl<T: ?Sized> Send for RcWeak<T> where std::rc::Weak<T>: Send {}
230unsafe impl<T: ?Sized> Sync for RcWeak<T> where std::rc::Weak<T>: Sync {}
231
232/// A serializable wrapper around `std::sync::Weak<T>` (thread-safe).
233///
234/// `ArcWeak<T>` works exactly like [`RcWeak<T>`] but is intended for use with
235/// multi-threaded shared graphs where strong pointers are `Arc<T>`.
236///
237/// All clones of an `ArcWeak<T>` share the same `UnsafeCell` so deserialization
238/// updates propagate to all copies.
239///
240/// # Example
241/// See module-level docs for an `Arc<Mutex<Node>>` usage example.
242pub struct ArcWeak<T: ?Sized> {
243    // Use Arc<UnsafeCell> so that clones share the same cell
244    inner: Arc<UnsafeCell<std::sync::Weak<T>>>,
245}
246
247impl<T: ?Sized> std::fmt::Debug for ArcWeak<T> {
248    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
249        f.debug_struct("ArcWeak")
250            .field("strong_count", &self.strong_count())
251            .field("weak_count", &self.weak_count())
252            .finish()
253    }
254}
255
256impl<T> ArcWeak<T> {
257    pub fn new() -> Self {
258        ArcWeak {
259            inner: Arc::new(UnsafeCell::new(std::sync::Weak::new())),
260        }
261    }
262}
263
264impl<T: ?Sized> ArcWeak<T> {
265    pub fn upgrade(&self) -> Option<Arc<T>> {
266        unsafe { (*self.inner.get()).upgrade() }
267    }
268
269    pub fn strong_count(&self) -> usize {
270        unsafe { (*self.inner.get()).strong_count() }
271    }
272
273    pub fn weak_count(&self) -> usize {
274        unsafe { (*self.inner.get()).weak_count() }
275    }
276
277    pub fn ptr_eq(&self, other: &Self) -> bool {
278        unsafe { std::sync::Weak::ptr_eq(&*self.inner.get(), &*other.inner.get()) }
279    }
280
281    pub fn update(&self, weak: std::sync::Weak<T>) {
282        unsafe {
283            *self.inner.get() = weak;
284        }
285    }
286
287    pub fn from_std(weak: std::sync::Weak<T>) -> Self {
288        ArcWeak {
289            inner: Arc::new(UnsafeCell::new(weak)),
290        }
291    }
292}
293
294impl<T: ?Sized> PartialEq for ArcWeak<T> {
295    fn eq(&self, other: &Self) -> bool {
296        self.ptr_eq(other)
297    }
298}
299
300impl<T: ?Sized> Eq for ArcWeak<T> {}
301
302impl<T> Default for ArcWeak<T> {
303    fn default() -> Self {
304        Self::new()
305    }
306}
307
308impl<T: ?Sized> Clone for ArcWeak<T> {
309    fn clone(&self) -> Self {
310        // Clone the Arc, not the inner Weak - this way clones share the same cell!
311        ArcWeak {
312            inner: self.inner.clone(),
313        }
314    }
315}
316
317impl<T: ?Sized> From<&Arc<T>> for ArcWeak<T> {
318    fn from(arc: &Arc<T>) -> Self {
319        ArcWeak::from_std(Arc::downgrade(arc))
320    }
321}
322
323unsafe impl<T: ?Sized + Send + Sync> Send for ArcWeak<T> {}
324unsafe impl<T: ?Sized + Send + Sync> Sync for ArcWeak<T> {}
325
326impl<T: Serializer + ForyDefault + 'static> Serializer for RcWeak<T> {
327    fn fory_is_shared_ref() -> bool {
328        true
329    }
330
331    fn fory_write(
332        &self,
333        context: &mut WriteContext,
334        ref_mode: RefMode,
335        write_type_info: bool,
336        has_generics: bool,
337    ) -> Result<(), Error> {
338        // Weak pointers require track_ref to be enabled on the Fory instance
339        if !context.is_track_ref() {
340            return Err(Error::invalid_ref(
341                "RcWeak requires track_ref to be enabled. Use Fory::default().track_ref(true)",
342            ));
343        }
344        // Weak MUST use ref tracking - otherwise read value will be lost
345        if ref_mode != RefMode::Tracking {
346            return Err(Error::invalid_ref(
347                "RcWeak requires RefMode::Tracking for serialization",
348            ));
349        }
350        if let Some(rc) = self.upgrade() {
351            if !context
352                .ref_writer
353                .try_write_rc_ref(&mut context.writer, &rc)
354            {
355                if write_type_info {
356                    T::fory_write_type_info(context)?;
357                }
358                T::fory_write_data_generic(&*rc, context, has_generics)?;
359            }
360        } else {
361            context.writer.write_i8(RefFlag::Null as i8);
362        }
363        Ok(())
364    }
365
366    fn fory_write_data_generic(&self, _: &mut WriteContext, _: bool) -> Result<(), Error> {
367        Err(Error::not_allowed(
368            "RcWeak<T> should be written using `fory_write` to handle reference tracking properly",
369        ))
370    }
371
372    fn fory_write_data(&self, _: &mut WriteContext) -> Result<(), Error> {
373        Err(Error::not_allowed(
374            "RcWeak<T> should be written using `fory_write` to handle reference tracking properly",
375        ))
376    }
377
378    fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
379        T::fory_write_type_info(context)
380    }
381
382    fn fory_read(
383        context: &mut ReadContext,
384        ref_mode: RefMode,
385        read_type_info: bool,
386    ) -> Result<Self, Error> {
387        // Weak MUST track refs
388        debug_assert!(
389            ref_mode == RefMode::Tracking,
390            "RcWeak requires RefMode::Tracking"
391        );
392        read_rc_weak::<T>(context, read_type_info, None)
393    }
394
395    fn fory_read_with_type_info(
396        context: &mut ReadContext,
397        ref_mode: RefMode,
398        typeinfo: Rc<TypeInfo>,
399    ) -> Result<Self, Error> {
400        debug_assert!(
401            ref_mode == RefMode::Tracking,
402            "RcWeak requires RefMode::Tracking"
403        );
404        read_rc_weak::<T>(context, false, Some(typeinfo))
405    }
406
407    fn fory_read_data(_: &mut ReadContext) -> Result<Self, Error> {
408        Err(Error::not_allowed("RcWeak<T> should be written using `fory_read/fory_read_with_type_info` to handle reference tracking properly"))
409    }
410
411    fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
412        T::fory_read_type_info(context)
413    }
414
415    fn fory_reserved_space() -> usize {
416        // RcWeak is a shared ref, return a const to avoid infinite recursion
417        4
418    }
419
420    fn fory_get_type_id(type_resolver: &TypeResolver) -> Result<TypeId, Error> {
421        T::fory_get_type_id(type_resolver)
422    }
423
424    fn fory_get_type_info(type_resolver: &TypeResolver) -> Result<Rc<TypeInfo>, Error> {
425        match type_resolver.get_type_info(&std::any::TypeId::of::<T>()) {
426            Ok(info) => Ok(info),
427            Err(e) => Err(Error::enhance_type_error::<T>(e)),
428        }
429    }
430
431    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<TypeId, Error> {
432        if let Some(rc) = self.upgrade() {
433            (*rc).fory_type_id_dyn(type_resolver)
434        } else {
435            T::fory_get_type_id(type_resolver)
436        }
437    }
438
439    fn fory_static_type_id() -> TypeId {
440        T::fory_static_type_id()
441    }
442
443    fn as_any(&self) -> &dyn std::any::Any {
444        self
445    }
446}
447
448fn read_rc_weak<T: Serializer + ForyDefault + 'static>(
449    context: &mut ReadContext,
450    read_type_info: bool,
451    type_info: Option<Rc<TypeInfo>>,
452) -> Result<RcWeak<T>, Error> {
453    // Always read ref flag - Weak requires tracking
454    let ref_flag = context.ref_reader.read_ref_flag(&mut context.reader)?;
455    match ref_flag {
456        RefFlag::Null => Ok(RcWeak::new()),
457        RefFlag::RefValue => {
458            context.inc_depth()?;
459            let data = if let Some(type_info) = type_info {
460                T::fory_read_with_type_info(context, RefMode::None, type_info)?
461            } else {
462                if read_type_info {
463                    context.read_any_type_info()?;
464                }
465                T::fory_read_data(context)?
466            };
467            context.dec_depth();
468            let rc = Rc::new(data);
469            let ref_id = context.ref_reader.store_rc_ref(rc);
470            let rc = context.ref_reader.get_rc_ref::<T>(ref_id).unwrap();
471            Ok(RcWeak::from(&rc))
472        }
473        RefFlag::Ref => {
474            let ref_id = context.ref_reader.read_ref_id(&mut context.reader)?;
475            if let Some(rc) = context.ref_reader.get_rc_ref::<T>(ref_id) {
476                Ok(RcWeak::from(&rc))
477            } else {
478                let result_weak = RcWeak::new();
479                let callback_weak = result_weak.clone();
480                context.ref_reader.add_callback(Box::new(move |ref_reader| {
481                    if let Some(rc) = ref_reader.get_rc_ref::<T>(ref_id) {
482                        callback_weak.update(Rc::downgrade(&rc));
483                    }
484                }));
485
486                Ok(result_weak)
487            }
488        }
489        RefFlag::NotNullValue => Err(Error::invalid_ref("RcWeak can't hold a strong ref value")),
490    }
491}
492
493impl<T: ForyDefault> ForyDefault for RcWeak<T> {
494    fn fory_default() -> Self {
495        RcWeak::new()
496    }
497}
498
499impl<T: Serializer + ForyDefault + Send + Sync + 'static> Serializer for ArcWeak<T> {
500    fn fory_is_shared_ref() -> bool {
501        true
502    }
503
504    fn fory_write(
505        &self,
506        context: &mut WriteContext,
507        ref_mode: RefMode,
508        write_type_info: bool,
509        has_generics: bool,
510    ) -> Result<(), Error> {
511        // Weak pointers require track_ref to be enabled on the Fory instance
512        if !context.is_track_ref() {
513            return Err(Error::invalid_ref(
514                "ArcWeak requires track_ref to be enabled. Use Fory::default().track_ref(true)",
515            ));
516        }
517        // Weak MUST use ref tracking - otherwise read value will be lost
518        if ref_mode != RefMode::Tracking {
519            return Err(Error::invalid_ref(
520                "ArcWeak requires RefMode::Tracking for serialization",
521            ));
522        }
523        if let Some(arc) = self.upgrade() {
524            if !context
525                .ref_writer
526                .try_write_arc_ref(&mut context.writer, &arc)
527            {
528                if write_type_info {
529                    T::fory_write_type_info(context)?;
530                }
531                T::fory_write_data_generic(&*arc, context, has_generics)?;
532            }
533        } else {
534            context.writer.write_i8(RefFlag::Null as i8);
535        }
536        Ok(())
537    }
538
539    fn fory_write_data_generic(&self, _: &mut WriteContext, _: bool) -> Result<(), Error> {
540        Err(Error::not_allowed(
541            "ArcWeak<T> should be written using `fory_write` to handle reference tracking properly",
542        ))
543    }
544
545    fn fory_write_data(&self, _: &mut WriteContext) -> Result<(), Error> {
546        Err(Error::not_allowed(
547            "ArcWeak<T> should be written using `fory_write` to handle reference tracking properly",
548        ))
549    }
550
551    fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
552        T::fory_write_type_info(context)
553    }
554
555    fn fory_read(
556        context: &mut ReadContext,
557        ref_mode: RefMode,
558        read_type_info: bool,
559    ) -> Result<Self, Error> {
560        // Weak MUST track refs
561        debug_assert!(
562            ref_mode == RefMode::Tracking,
563            "ArcWeak requires RefMode::Tracking"
564        );
565        read_arc_weak(context, read_type_info, None)
566    }
567
568    fn fory_read_with_type_info(
569        context: &mut ReadContext,
570        ref_mode: RefMode,
571        typeinfo: Rc<TypeInfo>,
572    ) -> Result<Self, Error> {
573        debug_assert!(
574            ref_mode == RefMode::Tracking,
575            "ArcWeak requires RefMode::Tracking"
576        );
577        read_arc_weak::<T>(context, false, Some(typeinfo))
578    }
579
580    fn fory_read_data(_: &mut ReadContext) -> Result<Self, Error> {
581        Err(Error::not_allowed("ArcWeak<T> should be written using `fory_read/fory_read_with_type_info` to handle reference tracking properly"))
582    }
583
584    fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
585        T::fory_read_type_info(context)
586    }
587
588    fn fory_reserved_space() -> usize {
589        // ArcWeak is a shared ref, return a const to avoid infinite recursion
590        4
591    }
592
593    fn fory_get_type_id(type_resolver: &TypeResolver) -> Result<TypeId, Error> {
594        T::fory_get_type_id(type_resolver)
595    }
596
597    fn fory_get_type_info(type_resolver: &TypeResolver) -> Result<Rc<TypeInfo>, Error> {
598        match type_resolver.get_type_info(&std::any::TypeId::of::<T>()) {
599            Ok(info) => Ok(info),
600            Err(e) => Err(Error::enhance_type_error::<T>(e)),
601        }
602    }
603
604    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<TypeId, Error> {
605        if let Some(arc) = self.upgrade() {
606            (*arc).fory_type_id_dyn(type_resolver)
607        } else {
608            T::fory_get_type_id(type_resolver)
609        }
610    }
611
612    fn fory_static_type_id() -> TypeId {
613        T::fory_static_type_id()
614    }
615
616    fn as_any(&self) -> &dyn std::any::Any {
617        self
618    }
619}
620
621fn read_arc_weak<T: Serializer + ForyDefault + 'static>(
622    context: &mut ReadContext,
623    read_type_info: bool,
624    type_info: Option<Rc<TypeInfo>>,
625) -> Result<ArcWeak<T>, Error> {
626    // Always read ref flag - Weak requires tracking
627    let ref_flag = context.ref_reader.read_ref_flag(&mut context.reader)?;
628    match ref_flag {
629        RefFlag::Null => Ok(ArcWeak::new()),
630        RefFlag::RefValue => {
631            context.inc_depth()?;
632            let data = if let Some(type_info) = type_info {
633                T::fory_read_with_type_info(context, RefMode::None, type_info)?
634            } else {
635                if read_type_info {
636                    context.read_any_type_info()?;
637                }
638                T::fory_read_data(context)?
639            };
640            context.dec_depth();
641            let arc = Arc::new(data);
642            let ref_id = context.ref_reader.store_arc_ref(arc);
643            let arc = context.ref_reader.get_arc_ref::<T>(ref_id).unwrap();
644            let weak = ArcWeak::from(&arc);
645            Ok(weak)
646        }
647        RefFlag::Ref => {
648            let ref_id = context.ref_reader.read_ref_id(&mut context.reader)?;
649            let weak = ArcWeak::new();
650
651            if let Some(arc) = context.ref_reader.get_arc_ref::<T>(ref_id) {
652                weak.update(Arc::downgrade(&arc));
653            } else {
654                // Capture the raw pointer to the UnsafeCell so we can update it in the callback
655                let weak_ptr = weak.inner.get();
656                context.ref_reader.add_callback(Box::new(move |ref_reader| {
657                    if let Some(arc) = ref_reader.get_arc_ref::<T>(ref_id) {
658                        unsafe {
659                            *weak_ptr = Arc::downgrade(&arc);
660                        }
661                    }
662                }));
663            }
664            Ok(weak)
665        }
666        RefFlag::NotNullValue => Err(Error::invalid_ref("ArcWeak can't hold a strong ref value")),
667    }
668}
669
670impl<T: ForyDefault> ForyDefault for ArcWeak<T> {
671    fn fory_default() -> Self {
672        ArcWeak::new()
673    }
674}