@@ -63,10 +63,22 @@ use core::ops::{DerefMut, Sub};
63
63
use core:: time:: Duration ;
64
64
use io:: { self , Read } ; use sync:: { Mutex , MutexGuard } ;
65
65
66
+ /// We define Score ever-so-slightly differently based on whether we are being built 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 other languages downstream of the C bindings (e.g. Java) can't even do that.
75
+ /// Instead, we really want `Score` and `LockableScore` to implement `Writeable` directly, which we
76
+ /// do here by defining `Score` differently for `cfg(c_bindings)`.
77
+ macro_rules! define_score { ( $( $supertrait: path) * ) => {
66
78
/// An interface used to score payment channels for path finding.
67
79
///
68
80
/// 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 ) * {
70
82
/// Returns the fee in msats willing to be paid to avoid routing `send_amt_msat` through the
71
83
/// given channel in the direction from `source` to `target`.
72
84
///
@@ -85,6 +97,22 @@ pub trait Score {
85
97
fn payment_path_failed( & mut self , path: & [ & RouteHop ] , short_channel_id: u64 ) ;
86
98
}
87
99
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
+
88
116
/// A scorer that is accessed under a lock.
89
117
///
90
118
/// Needed so that calls to [`Score::channel_penalty_msat`] in [`find_route`] can be made while
@@ -101,6 +129,7 @@ pub trait LockableScore<'a> {
101
129
fn lock ( & ' a self ) -> Self :: Locked ;
102
130
}
103
131
132
+ /// (C-not exported)
104
133
impl < ' a , T : ' a + Score > LockableScore < ' a > for Mutex < T > {
105
134
type Locked = MutexGuard < ' a , T > ;
106
135
@@ -117,13 +146,34 @@ impl<'a, T: 'a + Score> LockableScore<'a> for RefCell<T> {
117
146
}
118
147
}
119
148
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 MultiThreadedLockableScore < S : Score > {
152
+ score : Mutex < S > ,
153
+ }
154
+ #[ cfg( c_bindings) ]
155
+ /// (C-not exported)
156
+ impl < ' a , T : Score + ' a > LockableScore < ' a > for MultiThreadedLockableScore < T > {
157
+ type Locked = MutexGuard < ' a , T > ;
158
+
159
+ fn lock ( & ' a self ) -> MutexGuard < ' a , T > {
160
+ Mutex :: lock ( & self . score ) . unwrap ( )
123
161
}
162
+ }
124
163
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)
127
177
}
128
178
}
129
179
0 commit comments