@@ -63,10 +63,22 @@ use core::ops::{DerefMut, Sub};
6363use core:: time:: Duration ;
6464use io:: { self , Read } ; use sync:: { Mutex , MutexGuard } ;
6565
66+ /// We define Score ever-so-slightly differently based on whether we are being build for C bindings
67+ /// or not. For users, `LockableScore` must somehow be writeable to disk. For Rust users, this is
68+ /// no problem - you move a `Score` that implements `Writeable` into a `Mutex`, lock it, and now
69+ /// you have the original, concrete, `Score` type, which presumably implements `Writeable`.
70+ ///
71+ /// For C users, once you've moved the `Score` into a `LockableScore` all you have after locking it
72+ /// is an opaque trait object with an opaque pointer with no type info. Users could take the unsafe
73+ /// approach of blindly casting that opaque pointer to a concrete type and calling `Writeable` from
74+ /// there, but downstream bindings users (e.g. Java users) can't even do that. Instead, we really
75+ /// want `Score` and `LockableScore` to implement `Writeable` directly, which we do here by
76+ /// defining `Score` differently for `cfg(c_bindings)`.
77+ macro_rules! define_score { ( $( $supertrait: path) * ) => {
6678/// An interface used to score payment channels for path finding.
6779///
6880/// Scoring is in terms of fees willing to be paid in order to avoid routing through a channel.
69- pub trait Score {
81+ pub trait Score $ ( : $supertrait ) * {
7082 /// Returns the fee in msats willing to be paid to avoid routing `send_amt_msat` through the
7183 /// given channel in the direction from `source` to `target`.
7284 ///
@@ -85,6 +97,22 @@ pub trait Score {
8597 fn payment_path_failed( & mut self , path: & [ & RouteHop ] , short_channel_id: u64 ) ;
8698}
8799
100+ impl <S : Score , T : DerefMut <Target =S > $( + $supertrait) * > Score for T {
101+ fn channel_penalty_msat( & self , short_channel_id: u64 , send_amt_msat: u64 , channel_capacity_msat: Option <u64 >, source: & NodeId , target: & NodeId ) -> u64 {
102+ self . deref( ) . channel_penalty_msat( short_channel_id, send_amt_msat, channel_capacity_msat, source, target)
103+ }
104+
105+ fn payment_path_failed( & mut self , path: & [ & RouteHop ] , short_channel_id: u64 ) {
106+ self . deref_mut( ) . payment_path_failed( path, short_channel_id)
107+ }
108+ }
109+ } }
110+
111+ #[ cfg( c_bindings) ]
112+ define_score ! ( Writeable ) ;
113+ #[ cfg( not( c_bindings) ) ]
114+ define_score ! ( ) ;
115+
88116/// A scorer that is accessed under a lock.
89117///
90118/// Needed so that calls to [`Score::channel_penalty_msat`] in [`find_route`] can be made while
@@ -101,6 +129,7 @@ pub trait LockableScore<'a> {
101129 fn lock ( & ' a self ) -> Self :: Locked ;
102130}
103131
132+ /// (C-not exported)
104133impl < ' a , T : ' a + Score > LockableScore < ' a > for Mutex < T > {
105134 type Locked = MutexGuard < ' a , T > ;
106135
@@ -117,13 +146,34 @@ impl<'a, T: 'a + Score> LockableScore<'a> for RefCell<T> {
117146 }
118147}
119148
120- impl < S : Score , T : DerefMut < Target =S > > Score for T {
121- fn channel_penalty_msat ( & self , short_channel_id : u64 , send_amt_msat : u64 , channel_capacity_msat : Option < u64 > , source : & NodeId , target : & NodeId ) -> u64 {
122- self . deref ( ) . channel_penalty_msat ( short_channel_id, send_amt_msat, channel_capacity_msat, source, target)
149+ #[ cfg( c_bindings) ]
150+ /// A concrete implementation of [`LockableScore`] which supports multi-threading.
151+ pub struct ScoreHolder < S : Score > { // TODO(jkczyz): Name this better
152+ score : Mutex < S > ,
153+ }
154+ #[ cfg( c_bindings) ]
155+ /// (C-not exported)
156+ impl < ' a , T : Score + ' a > LockableScore < ' a > for ScoreHolder < T > {
157+ type Locked = MutexGuard < ' a , T > ;
158+
159+ fn lock ( & ' a self ) -> MutexGuard < ' a , T > {
160+ Mutex :: lock ( & self . score ) . unwrap ( )
123161 }
162+ }
124163
125- fn payment_path_failed ( & mut self , path : & [ & RouteHop ] , short_channel_id : u64 ) {
126- self . deref_mut ( ) . payment_path_failed ( path, short_channel_id)
164+ #[ cfg( c_bindings) ]
165+ /// (C-not exported)
166+ impl < ' a , T : Writeable > Writeable for RefMut < ' a , T > {
167+ fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , io:: Error > {
168+ T :: write ( & * * self , writer)
169+ }
170+ }
171+
172+ #[ cfg( c_bindings) ]
173+ /// (C-not exported)
174+ impl < ' a , S : Writeable > Writeable for MutexGuard < ' a , S > {
175+ fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , io:: Error > {
176+ S :: write ( & * * self , writer)
127177 }
128178}
129179
0 commit comments