@@ -108,61 +108,96 @@ impl CassFuture {
108
108
} )
109
109
}
110
110
111
- pub fn with_waited_result < T > ( & self , f : impl FnOnce ( & mut CassFutureResult ) -> T ) -> T {
111
+ pub fn with_waited_result < T > (
112
+ self : & Arc < Self > ,
113
+ f : impl FnOnce ( & mut CassFutureResult ) -> T ,
114
+ ) -> T {
112
115
self . with_waited_state ( |s| f ( s. value . as_mut ( ) . unwrap ( ) ) )
113
116
}
114
117
115
- fn with_waited_state < T > ( & self , f : impl FnOnce ( & mut CassFutureState ) -> T ) -> T {
118
+ fn with_waited_state < T > ( self : & Arc < Self > , f : impl FnOnce ( & mut CassFutureState ) -> T ) -> T {
116
119
let mut guard = self . state . lock ( ) . unwrap ( ) ;
117
120
let handle = guard. join_handle . take ( ) ;
121
+ mem:: drop ( guard) ;
122
+
118
123
if let Some ( handle) = handle {
119
- mem:: drop ( guard) ;
120
124
// unwrap: JoinError appears only when future either panic'ed or canceled.
121
125
RUNTIME . block_on ( handle) . unwrap ( ) ;
122
126
guard = self . state . lock ( ) . unwrap ( ) ;
123
127
} else {
124
- guard = self
125
- . wait_for_value
126
- . wait_while ( guard, |state| state. value . is_none ( ) )
127
- // unwrap: Error appears only when mutex is poisoned.
128
- . unwrap ( ) ;
128
+ // We need to spawn a thread that will be responsible for waiting
129
+ // on a cond variable (this operation blocks the thread).
130
+ // If we don't do that, this won't work for `current-thread` tokio runtime..
131
+ let self_clone = Arc :: clone ( self ) ;
132
+ let wait_for_value = async {
133
+ RUNTIME
134
+ . spawn_blocking ( move || {
135
+ let mut guard = self_clone. state . lock ( ) . unwrap ( ) ;
136
+ guard = self_clone
137
+ . wait_for_value
138
+ . wait_while ( guard, |state| state. value . is_none ( ) )
139
+ // unwrap: Error appears only when mutex is poisoned.
140
+ . unwrap ( ) ;
141
+ mem:: drop ( guard) ;
142
+ } )
143
+ . await
144
+ } ;
145
+ RUNTIME . block_on ( wait_for_value) . unwrap ( ) ;
146
+ guard = self . state . lock ( ) . unwrap ( ) ;
129
147
}
130
148
f ( & mut guard)
131
149
}
132
150
133
151
fn with_waited_result_timed < T > (
134
- & self ,
152
+ self : & Arc < Self > ,
135
153
f : impl FnOnce ( & mut CassFutureResult ) -> T ,
136
154
timeout_duration : Duration ,
137
155
) -> Result < T , TimeoutError > {
138
156
self . with_waited_state_timed ( |s| f ( s. value . as_mut ( ) . unwrap ( ) ) , timeout_duration)
139
157
}
140
158
141
159
pub ( self ) fn with_waited_state_timed < T > (
142
- & self ,
160
+ self : & Arc < Self > ,
143
161
f : impl FnOnce ( & mut CassFutureState ) -> T ,
144
162
timeout_duration : Duration ,
145
163
) -> Result < T , TimeoutError > {
146
164
let mut guard = self . state . lock ( ) . unwrap ( ) ;
147
165
let handle = guard. join_handle . take ( ) ;
166
+ mem:: drop ( guard) ;
167
+
148
168
if let Some ( handle) = handle {
149
- mem:: drop ( guard) ;
150
169
// Need to wrap it with async{} block, so the timeout is lazily executed inside the runtime.
151
170
// See mention about panics: https://docs.rs/tokio/latest/tokio/time/fn.timeout.html.
152
171
let timed = async { tokio:: time:: timeout ( timeout_duration, handle) . await } ;
153
172
// unwrap: JoinError appears only when future either panic'ed or canceled.
154
173
RUNTIME . block_on ( timed) . map_err ( |_| TimeoutError ) ?. unwrap ( ) ;
155
174
guard = self . state . lock ( ) . unwrap ( ) ;
156
175
} else {
157
- let ( guard_result, timeout_result) = self
158
- . wait_for_value
159
- . wait_timeout_while ( guard, timeout_duration, |state| state. value . is_none ( ) )
160
- // unwrap: Error appears only when mutex is poisoned.
161
- . unwrap ( ) ;
176
+ // We need to spawn a thread that will be responsible for waiting
177
+ // on a cond variable (this operation blocks the thread).
178
+ // If we don't do that, this won't work for `current-thread` tokio runtime..
179
+ let self_clone = Arc :: clone ( self ) ;
180
+ let wait_for_value = async {
181
+ RUNTIME
182
+ . spawn_blocking ( move || {
183
+ let guard = self_clone. state . lock ( ) . unwrap ( ) ;
184
+ let ( guard_result, timeout_result) = self_clone
185
+ . wait_for_value
186
+ . wait_timeout_while ( guard, timeout_duration, |state| {
187
+ state. value . is_none ( )
188
+ } )
189
+ // unwrap: Error appears only when mutex is poisoned.
190
+ . unwrap ( ) ;
191
+ mem:: drop ( guard_result) ;
192
+ timeout_result
193
+ } )
194
+ . await
195
+ } ;
196
+ let timeout_result = RUNTIME . block_on ( wait_for_value) . unwrap ( ) ;
162
197
if timeout_result. timed_out ( ) {
163
198
return Err ( TimeoutError ) ;
164
199
}
165
- guard = guard_result ;
200
+ guard = self . state . lock ( ) . unwrap ( ) ;
166
201
}
167
202
168
203
Ok ( f ( & mut guard) )
@@ -208,15 +243,15 @@ pub unsafe extern "C" fn cass_future_set_callback(
208
243
209
244
#[ no_mangle]
210
245
pub unsafe extern "C" fn cass_future_wait ( future_raw : * const CassFuture ) {
211
- ptr_to_ref ( future_raw) . with_waited_result ( |_| ( ) ) ;
246
+ clone_arced ( future_raw) . with_waited_result ( |_| ( ) ) ;
212
247
}
213
248
214
249
#[ no_mangle]
215
250
pub unsafe extern "C" fn cass_future_wait_timed (
216
251
future_raw : * const CassFuture ,
217
252
timeout_us : cass_duration_t ,
218
253
) -> cass_bool_t {
219
- ptr_to_ref ( future_raw)
254
+ clone_arced ( future_raw)
220
255
. with_waited_result_timed ( |_| ( ) , Duration :: from_micros ( timeout_us) )
221
256
. is_ok ( ) as cass_bool_t
222
257
}
@@ -232,7 +267,7 @@ pub unsafe extern "C" fn cass_future_ready(future_raw: *const CassFuture) -> cas
232
267
233
268
#[ no_mangle]
234
269
pub unsafe extern "C" fn cass_future_error_code ( future_raw : * const CassFuture ) -> CassError {
235
- ptr_to_ref ( future_raw) . with_waited_result ( |r : & mut CassFutureResult | match r {
270
+ clone_arced ( future_raw) . with_waited_result ( |r : & mut CassFutureResult | match r {
236
271
Ok ( CassResultValue :: QueryError ( err) ) => CassError :: from ( err. as_ref ( ) ) ,
237
272
Err ( ( err, _) ) => * err,
238
273
_ => CassError :: CASS_OK ,
@@ -245,7 +280,7 @@ pub unsafe extern "C" fn cass_future_error_message(
245
280
message : * mut * const :: std:: os:: raw:: c_char ,
246
281
message_length : * mut size_t ,
247
282
) {
248
- ptr_to_ref ( future) . with_waited_state ( |state : & mut CassFutureState | {
283
+ clone_arced ( future) . with_waited_state ( |state : & mut CassFutureState | {
249
284
let value = & state. value ;
250
285
let msg = state
251
286
. err_string
@@ -267,7 +302,7 @@ pub unsafe extern "C" fn cass_future_free(future_raw: *const CassFuture) {
267
302
pub unsafe extern "C" fn cass_future_get_result (
268
303
future_raw : * const CassFuture ,
269
304
) -> * const CassResult {
270
- ptr_to_ref ( future_raw)
305
+ clone_arced ( future_raw)
271
306
. with_waited_result ( |r : & mut CassFutureResult | -> Option < Arc < CassResult > > {
272
307
match r. as_ref ( ) . ok ( ) ? {
273
308
CassResultValue :: QueryResult ( qr) => Some ( qr. clone ( ) ) ,
@@ -281,7 +316,7 @@ pub unsafe extern "C" fn cass_future_get_result(
281
316
pub unsafe extern "C" fn cass_future_get_error_result (
282
317
future_raw : * const CassFuture ,
283
318
) -> * const CassErrorResult {
284
- ptr_to_ref ( future_raw)
319
+ clone_arced ( future_raw)
285
320
. with_waited_result ( |r : & mut CassFutureResult | -> Option < Arc < CassErrorResult > > {
286
321
match r. as_ref ( ) . ok ( ) ? {
287
322
CassResultValue :: QueryError ( qr) => Some ( qr. clone ( ) ) ,
@@ -295,7 +330,7 @@ pub unsafe extern "C" fn cass_future_get_error_result(
295
330
pub unsafe extern "C" fn cass_future_get_prepared (
296
331
future_raw : * mut CassFuture ,
297
332
) -> * const CassPrepared {
298
- ptr_to_ref ( future_raw)
333
+ clone_arced ( future_raw)
299
334
. with_waited_result ( |r : & mut CassFutureResult | -> Option < Arc < CassPrepared > > {
300
335
match r. as_ref ( ) . ok ( ) ? {
301
336
CassResultValue :: Prepared ( p) => Some ( p. clone ( ) ) ,
@@ -310,7 +345,7 @@ pub unsafe extern "C" fn cass_future_tracing_id(
310
345
future : * const CassFuture ,
311
346
tracing_id : * mut CassUuid ,
312
347
) -> CassError {
313
- ptr_to_ref ( future) . with_waited_result ( |r : & mut CassFutureResult | match r {
348
+ clone_arced ( future) . with_waited_result ( |r : & mut CassFutureResult | match r {
314
349
Ok ( CassResultValue :: QueryResult ( result) ) => match result. metadata . tracing_id {
315
350
Some ( id) => {
316
351
* tracing_id = CassUuid :: from ( id) ;
0 commit comments