Jelajahi Sumber

net: replace LazyWeak with Arc::new_cyclic() and delete system::LazyWeak

Also update arch/services.md with the new usage.
draoi 2 tahun lalu
induk
melakukan
0c8b274505

+ 6 - 10
doc/src/arch/services.md

@@ -118,7 +118,7 @@ stop_sub.unsubscribe().await;
 
 
 In the async context we are forced to use `Arc<Self>`, but often times we want a parent-child
 In the async context we are forced to use `Arc<Self>`, but often times we want a parent-child
 relationship where if both parties contain an Arc reference to the other it creates a
 relationship where if both parties contain an Arc reference to the other it creates a
-circular loop. For this case, there is a handy helper called `LazyWeak`.
+circular loop. For this case, we can use `std::sync::Weak` and `std::sync::Arc::new_cyclic()`.
 
 
 ```rust
 ```rust
 pub struct Parent {
 pub struct Parent {
@@ -128,14 +128,10 @@ pub struct Parent {
 
 
 impl Parent {
 impl Parent {
     pub async fn new(/* ... */) -> Arc<Self> {
     pub async fn new(/* ... */) -> Arc<Self> {
-        let self_ = Arc::new(Self {
-            child: Child::new(),
+        Arc::new_cyclic(|parent| Self {
+            child: Child::new(parent.clone())
             // ...
             // ...
         });
         });
-
-        self_.child.parent.init(self_.clone());
-        // ...
-        self_
     }
     }
 
 
     // ...
     // ...
@@ -143,14 +139,14 @@ impl Parent {
 
 
 
 
 pub struct Child {
 pub struct Child {
-    pub parent: LazyWeak<Parent>,
+    pub parent: Weak<Parent>,
     // ...
     // ...
 }
 }
 
 
 impl Child {
 impl Child {
-    pub fn new() -> Arc<Self> {
+    pub fn new(parent: Weak<Parent>) -> Arc<Self> {
         Arc::new(Self {
         Arc::new(Self {
-            parent: LazyWeak::new(),
+            parent: Weak::new(),
             // ...
             // ...
         })
         })
     }
     }

+ 6 - 13
src/net/p2p.rs

@@ -101,27 +101,20 @@ impl P2p {
         // Wrap the Settings into an Arc<RwLock>
         // Wrap the Settings into an Arc<RwLock>
         let settings = Arc::new(AsyncRwLock::new(settings));
         let settings = Arc::new(AsyncRwLock::new(settings));
 
 
-        let self_ = Arc::new(Self {
+        let self_ = Arc::new_cyclic(|p2p| Self {
             executor,
             executor,
             hosts: Hosts::new(Arc::clone(&settings)),
             hosts: Hosts::new(Arc::clone(&settings)),
             protocol_registry: ProtocolRegistry::new(),
             protocol_registry: ProtocolRegistry::new(),
             settings,
             settings,
-            session_manual: ManualSession::new(),
-            session_inbound: InboundSession::new(),
-            session_outbound: OutboundSession::new(),
-            session_refine: RefineSession::new(),
-            session_seedsync: SeedSyncSession::new(),
-
+            session_manual: ManualSession::new(p2p.clone()),
+            session_inbound: InboundSession::new(p2p.clone()),
+            session_outbound: OutboundSession::new(p2p.clone()),
+            session_refine: RefineSession::new(p2p.clone()),
+            session_seedsync: SeedSyncSession::new(p2p.clone()),
             dnet_enabled: AtomicBool::new(false),
             dnet_enabled: AtomicBool::new(false),
             dnet_publisher: Publisher::new(),
             dnet_publisher: Publisher::new(),
         });
         });
 
 
-        self_.session_inbound.p2p.init(self_.clone());
-        self_.session_manual.p2p.init(self_.clone());
-        self_.session_seedsync.p2p.init(self_.clone());
-        self_.session_outbound.p2p.init(self_.clone());
-        self_.session_refine.p2p.init(self_.clone());
-
         register_default_protocols(self_.clone()).await;
         register_default_protocols(self_.clone()).await;
 
 
         Ok(self_)
         Ok(self_)

+ 6 - 6
src/net/session/inbound_session.rs

@@ -23,7 +23,7 @@
 //! an acceptor pointer, and a stoppable task pointer. Using a weak pointer
 //! an acceptor pointer, and a stoppable task pointer. Using a weak pointer
 //! to P2P allows us to avoid circular dependencies.
 //! to P2P allows us to avoid circular dependencies.
 
 
-use std::sync::Arc;
+use std::sync::{Arc, Weak};
 
 
 use async_trait::async_trait;
 use async_trait::async_trait;
 use log::{debug, error, info};
 use log::{debug, error, info};
@@ -40,7 +40,7 @@ use super::{
     Session, SessionBitFlag, SESSION_INBOUND,
     Session, SessionBitFlag, SESSION_INBOUND,
 };
 };
 use crate::{
 use crate::{
-    system::{LazyWeak, StoppableTask, StoppableTaskPtr, Subscription},
+    system::{StoppableTask, StoppableTaskPtr, Subscription},
     Error, Result,
     Error, Result,
 };
 };
 
 
@@ -48,16 +48,16 @@ pub type InboundSessionPtr = Arc<InboundSession>;
 
 
 /// Defines inbound connections session
 /// Defines inbound connections session
 pub struct InboundSession {
 pub struct InboundSession {
-    pub(in crate::net) p2p: LazyWeak<P2p>,
+    pub(in crate::net) p2p: Weak<P2p>,
     acceptors: Mutex<Vec<AcceptorPtr>>,
     acceptors: Mutex<Vec<AcceptorPtr>>,
     accept_tasks: Mutex<Vec<StoppableTaskPtr>>,
     accept_tasks: Mutex<Vec<StoppableTaskPtr>>,
 }
 }
 
 
 impl InboundSession {
 impl InboundSession {
     /// Create a new inbound session
     /// Create a new inbound session
-    pub fn new() -> InboundSessionPtr {
+    pub fn new(p2p: Weak<P2p>) -> InboundSessionPtr {
         Arc::new(Self {
         Arc::new(Self {
-            p2p: LazyWeak::new(),
+            p2p,
             acceptors: Mutex::new(Vec::new()),
             acceptors: Mutex::new(Vec::new()),
             accept_tasks: Mutex::new(Vec::new()),
             accept_tasks: Mutex::new(Vec::new()),
         })
         })
@@ -206,7 +206,7 @@ impl InboundSession {
 #[async_trait]
 #[async_trait]
 impl Session for InboundSession {
 impl Session for InboundSession {
     fn p2p(&self) -> P2pPtr {
     fn p2p(&self) -> P2pPtr {
-        self.p2p.upgrade()
+        self.p2p.upgrade().unwrap()
     }
     }
 
 
     fn type_id(&self) -> SessionBitFlag {
     fn type_id(&self) -> SessionBitFlag {

+ 5 - 5
src/net/session/manual_session.rs

@@ -48,7 +48,7 @@ use super::{
 };
 };
 use crate::{
 use crate::{
     net::{hosts::HostState, settings::Settings},
     net::{hosts::HostState, settings::Settings},
-    system::{sleep, LazyWeak, StoppableTask, StoppableTaskPtr},
+    system::{sleep, StoppableTask, StoppableTaskPtr},
     Error, Result,
     Error, Result,
 };
 };
 
 
@@ -56,14 +56,14 @@ pub type ManualSessionPtr = Arc<ManualSession>;
 
 
 /// Defines manual connections session.
 /// Defines manual connections session.
 pub struct ManualSession {
 pub struct ManualSession {
-    pub(in crate::net) p2p: LazyWeak<P2p>,
+    pub(in crate::net) p2p: Weak<P2p>,
     slots: AsyncMutex<Vec<Arc<Slot>>>,
     slots: AsyncMutex<Vec<Arc<Slot>>>,
 }
 }
 
 
 impl ManualSession {
 impl ManualSession {
     /// Create a new manual session.
     /// Create a new manual session.
-    pub fn new() -> ManualSessionPtr {
-        Arc::new(Self { p2p: LazyWeak::new(), slots: AsyncMutex::new(Vec::new()) })
+    pub fn new(p2p: Weak<P2p>) -> ManualSessionPtr {
+        Arc::new(Self { p2p, slots: AsyncMutex::new(Vec::new()) })
     }
     }
 
 
     pub(crate) async fn start(self: Arc<Self>) {
     pub(crate) async fn start(self: Arc<Self>) {
@@ -101,7 +101,7 @@ impl ManualSession {
 #[async_trait]
 #[async_trait]
 impl Session for ManualSession {
 impl Session for ManualSession {
     fn p2p(&self) -> P2pPtr {
     fn p2p(&self) -> P2pPtr {
-        self.p2p.upgrade()
+        self.p2p.upgrade().unwrap()
     }
     }
 
 
     fn type_id(&self) -> SessionBitFlag {
     fn type_id(&self) -> SessionBitFlag {

+ 12 - 18
src/net/session/outbound_session.rs

@@ -52,7 +52,7 @@ use super::{
     Session, SessionBitFlag, SESSION_OUTBOUND,
     Session, SessionBitFlag, SESSION_OUTBOUND,
 };
 };
 use crate::{
 use crate::{
-    system::{sleep, timeout::timeout, CondVar, LazyWeak, StoppableTask, StoppableTaskPtr},
+    system::{sleep, timeout::timeout, CondVar, StoppableTask, StoppableTaskPtr},
     Error, Result,
     Error, Result,
 };
 };
 
 
@@ -61,7 +61,7 @@ pub type OutboundSessionPtr = Arc<OutboundSession>;
 /// Defines outbound connections session.
 /// Defines outbound connections session.
 pub struct OutboundSession {
 pub struct OutboundSession {
     /// Weak pointer to parent p2p object
     /// Weak pointer to parent p2p object
-    pub(in crate::net) p2p: LazyWeak<P2p>,
+    pub(in crate::net) p2p: Weak<P2p>,
     /// Outbound connection slots
     /// Outbound connection slots
     slots: Mutex<Vec<Arc<Slot>>>,
     slots: Mutex<Vec<Arc<Slot>>>,
     /// Peer discovery task
     /// Peer discovery task
@@ -70,14 +70,12 @@ pub struct OutboundSession {
 
 
 impl OutboundSession {
 impl OutboundSession {
     /// Create a new outbound session.
     /// Create a new outbound session.
-    pub(crate) fn new() -> OutboundSessionPtr {
-        let self_ = Arc::new(Self {
-            p2p: LazyWeak::new(),
+    pub(crate) fn new(p2p: Weak<P2p>) -> OutboundSessionPtr {
+        Arc::new_cyclic(|session| Self {
+            p2p,
             slots: Mutex::new(Vec::new()),
             slots: Mutex::new(Vec::new()),
-            peer_discovery: PeerDiscovery::new(),
-        });
-        self_.peer_discovery.session.init(self_.clone());
-        self_
+            peer_discovery: PeerDiscovery::new(session.clone()),
+        })
     }
     }
 
 
     /// Start the outbound session. Runs the channel connect loop.
     /// Start the outbound session. Runs the channel connect loop.
@@ -143,7 +141,7 @@ impl OutboundSession {
 #[async_trait]
 #[async_trait]
 impl Session for OutboundSession {
 impl Session for OutboundSession {
     fn p2p(&self) -> P2pPtr {
     fn p2p(&self) -> P2pPtr {
-        self.p2p.upgrade()
+        self.p2p.upgrade().unwrap()
     }
     }
 
 
     fn type_id(&self) -> SessionBitFlag {
     fn type_id(&self) -> SessionBitFlag {
@@ -467,16 +465,12 @@ pub trait PeerDiscoveryBase {
 struct PeerDiscovery {
 struct PeerDiscovery {
     process: StoppableTaskPtr,
     process: StoppableTaskPtr,
     wakeup_self: CondVar,
     wakeup_self: CondVar,
-    session: LazyWeak<OutboundSession>,
+    session: Weak<OutboundSession>,
 }
 }
 
 
 impl PeerDiscovery {
 impl PeerDiscovery {
-    fn new() -> Arc<Self> {
-        Arc::new(Self {
-            process: StoppableTask::new(),
-            wakeup_self: CondVar::new(),
-            session: LazyWeak::new(),
-        })
+    fn new(session: Weak<OutboundSession>) -> Arc<Self> {
+        Arc::new(Self { process: StoppableTask::new(), wakeup_self: CondVar::new(), session })
     }
     }
 }
 }
 
 
@@ -664,7 +658,7 @@ impl PeerDiscoveryBase for PeerDiscovery {
     }
     }
 
 
     fn session(&self) -> OutboundSessionPtr {
     fn session(&self) -> OutboundSessionPtr {
-        self.session.upgrade()
+        self.session.upgrade().unwrap()
     }
     }
 
 
     fn p2p(&self) -> P2pPtr {
     fn p2p(&self) -> P2pPtr {

+ 10 - 12
src/net/session/refine_session.rs

@@ -31,7 +31,7 @@ use futures::{
 };
 };
 use smol::Timer;
 use smol::Timer;
 use std::{
 use std::{
-    sync::Arc,
+    sync::{Arc, Weak},
     time::{Duration, Instant, UNIX_EPOCH},
     time::{Duration, Instant, UNIX_EPOCH},
 };
 };
 
 
@@ -48,7 +48,7 @@ use crate::{
         protocol::ProtocolVersion,
         protocol::ProtocolVersion,
         session::{Session, SessionBitFlag, SESSION_REFINE},
         session::{Session, SessionBitFlag, SESSION_REFINE},
     },
     },
-    system::{sleep, LazyWeak, StoppableTask, StoppableTaskPtr},
+    system::{sleep, StoppableTask, StoppableTaskPtr},
     Error,
     Error,
 };
 };
 
 
@@ -56,17 +56,15 @@ pub type RefineSessionPtr = Arc<RefineSession>;
 
 
 pub struct RefineSession {
 pub struct RefineSession {
     /// Weak pointer to parent p2p object
     /// Weak pointer to parent p2p object
-    pub(in crate::net) p2p: LazyWeak<P2p>,
+    pub(in crate::net) p2p: Weak<P2p>,
 
 
     /// Task that periodically checks entries in the greylist.
     /// Task that periodically checks entries in the greylist.
     pub(in crate::net) refinery: Arc<GreylistRefinery>,
     pub(in crate::net) refinery: Arc<GreylistRefinery>,
 }
 }
 
 
 impl RefineSession {
 impl RefineSession {
-    pub fn new() -> RefineSessionPtr {
-        let self_ = Arc::new(Self { p2p: LazyWeak::new(), refinery: GreylistRefinery::new() });
-        self_.refinery.session.init(self_.clone());
-        self_
+    pub fn new(p2p: Weak<P2p>) -> RefineSessionPtr {
+        Arc::new_cyclic(|session| Self { p2p, refinery: GreylistRefinery::new(session.clone()) })
     }
     }
 
 
     /// Start the refinery and self handshake processes.
     /// Start the refinery and self handshake processes.
@@ -175,7 +173,7 @@ impl RefineSession {
 #[async_trait]
 #[async_trait]
 impl Session for RefineSession {
 impl Session for RefineSession {
     fn p2p(&self) -> P2pPtr {
     fn p2p(&self) -> P2pPtr {
-        self.p2p.upgrade()
+        self.p2p.upgrade().unwrap()
     }
     }
 
 
     fn type_id(&self) -> SessionBitFlag {
     fn type_id(&self) -> SessionBitFlag {
@@ -194,13 +192,13 @@ impl Session for RefineSession {
 /// entry is removed from the greylist.
 /// entry is removed from the greylist.
 pub struct GreylistRefinery {
 pub struct GreylistRefinery {
     /// Weak pointer to parent object
     /// Weak pointer to parent object
-    session: LazyWeak<RefineSession>,
+    session: Weak<RefineSession>,
     process: StoppableTaskPtr,
     process: StoppableTaskPtr,
 }
 }
 
 
 impl GreylistRefinery {
 impl GreylistRefinery {
-    pub fn new() -> Arc<Self> {
-        Arc::new(Self { session: LazyWeak::new(), process: StoppableTask::new() })
+    pub fn new(session: Weak<RefineSession>) -> Arc<Self> {
+        Arc::new(Self { session, process: StoppableTask::new() })
     }
     }
 
 
     pub async fn start(self: Arc<Self>) {
     pub async fn start(self: Arc<Self>) {
@@ -310,7 +308,7 @@ impl GreylistRefinery {
     }
     }
 
 
     fn session(&self) -> RefineSessionPtr {
     fn session(&self) -> RefineSessionPtr {
-        self.session.upgrade()
+        self.session.upgrade().unwrap()
     }
     }
 
 
     fn p2p(&self) -> P2pPtr {
     fn p2p(&self) -> P2pPtr {

+ 5 - 5
src/net/session/seedsync_session.rs

@@ -64,7 +64,7 @@ use super::{
 };
 };
 use crate::{
 use crate::{
     net::hosts::HostState,
     net::hosts::HostState,
-    system::{CondVar, LazyWeak, StoppableTask, StoppableTaskPtr},
+    system::{CondVar, StoppableTask, StoppableTaskPtr},
     Error,
     Error,
 };
 };
 
 
@@ -72,14 +72,14 @@ pub type SeedSyncSessionPtr = Arc<SeedSyncSession>;
 
 
 /// Defines seed connections session
 /// Defines seed connections session
 pub struct SeedSyncSession {
 pub struct SeedSyncSession {
-    pub(in crate::net) p2p: LazyWeak<P2p>,
+    pub(in crate::net) p2p: Weak<P2p>,
     slots: AsyncMutex<Vec<Arc<Slot>>>,
     slots: AsyncMutex<Vec<Arc<Slot>>>,
 }
 }
 
 
 impl SeedSyncSession {
 impl SeedSyncSession {
     /// Create a new seed sync session instance
     /// Create a new seed sync session instance
-    pub(crate) fn new() -> SeedSyncSessionPtr {
-        Arc::new(Self { p2p: LazyWeak::new(), slots: AsyncMutex::new(Vec::new()) })
+    pub(crate) fn new(p2p: Weak<P2p>) -> SeedSyncSessionPtr {
+        Arc::new(Self { p2p, slots: AsyncMutex::new(Vec::new()) })
     }
     }
 
 
     /// Initialize the seedsync session. Each slot is suspended while it waits
     /// Initialize the seedsync session. Each slot is suspended while it waits
@@ -136,7 +136,7 @@ impl SeedSyncSession {
 #[async_trait]
 #[async_trait]
 impl Session for SeedSyncSession {
 impl Session for SeedSyncSession {
     fn p2p(&self) -> P2pPtr {
     fn p2p(&self) -> P2pPtr {
-        self.p2p.upgrade()
+        self.p2p.upgrade().unwrap()
     }
     }
 
 
     fn type_id(&self) -> SessionBitFlag {
     fn type_id(&self) -> SessionBitFlag {

+ 0 - 99
src/system/lazy_weak.rs

@@ -1,99 +0,0 @@
-/* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2024 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- */
-
-use std::sync::{Arc, OnceLock, Weak};
-
-/// Sometimes you need a parent-child relationship which results in code like:
-/// ```rust
-/// struct Parent {
-///     child: Mutex<Option<Arc<Child>>>
-/// }
-/// impl Parent {
-///     fn new() -> Arc<Self> {
-///         let self_ = Arc::new(Self {
-///             child: Mutex::new(None)
-///         });
-///         let parent = Arc::downgrade(&self_);
-///         *self_.child.lock().await = Some(Child::new(parent));
-///         self_
-///     }
-/// }
-/// struct Child {
-///     parent: Weak<Parent>
-/// }
-/// impl Child {
-///     fn new(parent: Weak<Parent>) -> Self {
-///         Self { parent }
-///     }
-///     fn upgrade(&self) -> Arc<Parent> {
-///         self.parent.upgrade().unwrap()
-///     }
-/// }
-/// ```
-/// This class simplifies the above code by allowing us instead to do:
-/// ```rust
-/// struct Parent {
-///     child: Arc<Child>
-/// }
-/// impl Parent {
-///     fn new() -> Arc<Self> {
-///         let self_ = Arc::new(Self {
-///             child: Child::new()
-///         });
-///         self_.child.parent.init(self_.clone());
-///         self_
-///     }
-/// }
-/// struct Child {
-///     parent: LazyWeak<Parent>
-/// }
-/// impl Child {
-///     fn new() -> Self {
-///         Self { parent: LazyWeak::new() }
-///     }
-///     fn upgrade(&self) -> Arc<Parent> {
-///         self.parent.upgrade()
-///     }
-/// }
-/// ```
-pub struct LazyWeak<Parent>(OnceLock<Weak<Parent>>);
-
-impl<Parent> LazyWeak<Parent> {
-    /// Create an empty `LazyWeak`, which must immediately be followed by `weak.init()`.
-    pub fn new() -> Self {
-        Self(OnceLock::new())
-    }
-
-    /// Must be called within the same scope as `new()`.
-    pub fn init(&self, parent: Arc<Parent>) {
-        assert!(self.0.get().is_none());
-        let parent = Arc::downgrade(&parent);
-        self.0.set(parent).unwrap();
-    }
-
-    /// Access the `Arc<Parent>` pointer
-    pub fn upgrade(&self) -> Arc<Parent> {
-        self.0.get().unwrap().upgrade().unwrap()
-    }
-}
-
-impl<Parent> Default for LazyWeak<Parent> {
-    fn default() -> Self {
-        Self::new()
-    }
-}

+ 0 - 4
src/system/mod.rs

@@ -24,10 +24,6 @@ use smol::{future::Future, Executor, Timer};
 pub mod condvar;
 pub mod condvar;
 pub use condvar::CondVar;
 pub use condvar::CondVar;
 
 
-/// Convenient late initialization of `Weak<Foo>`
-pub mod lazy_weak;
-pub use lazy_weak::LazyWeak;
-
 /// Implementation of async background task spawning which are stoppable
 /// Implementation of async background task spawning which are stoppable
 /// using channel signalling.
 /// using channel signalling.
 pub mod stoppable_task;
 pub mod stoppable_task;