1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
//! # Overview
//! An util crate to complete futures through a handle. Its main purpose is to bridge async Rust and callback-based APIs.
//!
//! Inspired on the `future_handles` crate.
//!
//! The `susync` crate uses standard library channels under the hood. It uses thread-safe primitives but expects low contention,
//! so it uses a single [`SpinMutex`] for shared state. It should also work on `no_std` environments but it is not tested.
//! By design handles are allowed to race to complete the future so it is ok to call complete on handle of a completed future. More info [here][`SuspendHandle::clone`].
//!
//! ## Examples
//!
//! Channel-like API:
//! ```rust
//! async fn func() -> Option<u32> {
//! let (future, handle) = susync::create();
//!
//! func_with_callback(|res| {
//! handle.complete(res);
//! });
//!
//! future.await.ok()
//! }
//! # fn func_with_callback(func: impl FnOnce(u32)) {
//! # func(1);
//! # }
//! ```
//!
//! Scoped API:
//! ```rust
//! async fn func() -> Option<u32> {
//! let future = susync::suspend(|handle| {
//! func_with_callback(|res| {
//! handle.complete(res);
//! });
//! });
//!
//! future.await.ok()
//! }
//! # fn func_with_callback(func: impl FnOnce(u32)) {
//! # func(1);
//! # }
//! ```
//!
//! ## Thread safety
//!
//! Currently it uses thread safe primitives so keep in mind that overhead.
//!
//! # Danger!
//!
//! Do **NOT** do this, it will block forever!
//! ```rust
//! async fn func() {
//! let (future, handle) = susync::create();
//! // Start awaiting here...
//! future.await.unwrap();
//! // Now we'll never be able set the result!
//! handle.complete(1);
//! }
//! ```
//! Awaiting a [`SuspendFuture`] before setting the result with
//! [`SuspendHandle`] will cause a **deadlock**!
//!
//! # Macro shortcuts
//!
//! If your use case is to simply to call `complete` on the [`SuspendHandle`] with the arguments of a callback, the [`sus`] macro is an option.
//!
//! ```rust
//! # use susync::sus;
//! # async fn func() {
//! // With one closure argument
//! fn func_one_arg(func: impl FnOnce(u32)) {
//! func(42);
//! }
//! // Here the arguments of the closure will be passed to `complete`
//! let result = sus!(func_one_arg(|x| {})).await.unwrap();
//! assert_eq!(result, 42);
//!
//! // With two closure arguments
//! fn func_two_args(func: impl FnOnce(u32, f32)) {
//! func(42, 69.0);
//! }
//! // Here the arguments of the closure will be passed to `complete`
//! let result = sus!(func_two_args(|x, y| {})).await.unwrap();
//! assert_eq!(result, (42, 69.0));
//! # }
//! ```
//!
//! The [`SuspendFuture`] will hold the arguments in a tuple or just a type in case it's just one argument.
//! You can ignore arguments by using the wildcard `_` token.
//!
//! ```rust
//! # use susync::sus;
//! # async fn func() {
//! fn func_with_callback(func: impl FnOnce(u32, &str)) {
//! func(42, "ignored :(");
//! }
//! // Here the second argument gets ignored
//! let result = sus!(func_with_callback(|x, _| {})).await.unwrap();
//! assert_eq!(result, 42);
//! # }
//! ```
//!
//! ## Macro invariants
//!
//! The callback argument must be a closure.
//! This macro implementation revolves around generating a new closure that runs the original and also forwards the arguments to [`SuspendHandle::complete`].
//! The logic is wrapped in a [`suspend`] that returns a future.
//! For this reason it's not possible to accept anything else other than a closure because it's not possible to infer the future output type.
//!
//! The [`sus`] macro calls `to_owned` on all arguments so all arguments in the callback must implement [`ToOwned`] trait.
//! This is to allow reference arguments like `&str` and any other reference of a type that implements [`Clone`] (check `ToOwned` [implementors]).
//!
//! [implementors]: https://doc.rust-lang.org/std/borrow/trait.ToOwned.html#implementors
//!
//! Still looking for ways to overcome this limitation and give the user the freedom to choose how to complete the future.
//!
//! ```rust, compile_fail
//! # use susync::sus;
//! # async fn func() {
//! // Does *NOT* implement `ToOwned`
//! struct RefArg(i32);
//! fn func(f: impl FnOnce(&RefArg)) {
//! f(&RefArg(42));
//! }
//! // *ILLEGAL*: Here the argument will clone a reference and try to outlive the scope
//! let RefArg(result) = sus!(func(|arg| {})).await.unwrap();
//! # }
//! ```
//!
//! Unfortunately the error message is not very friendly because the error is trait bounds but they are implicit to the macro.
//! So if you ever get an error message like below it is likely a reference is being passed to complete instead of an owned value.
//!
//! ```text
//! error[E0521]: borrowed data escapes outside of closure
//! --> susync/src/lib.rs:127:22
//! |
//! 13 | let RefArg(result) = sus!(func(|arg| {})).await.unwrap();
//! | ^^^^^^^^^^^---^^^^^^
//! | | |
//! | | `arg` is a reference that is only valid in the closure body
//! | `handle` declared here, outside of the closure body
//! | `arg` escapes the closure body here
//! |
//! = note: this error originates in the macro `sus`
//! ```
//!
//! In case there are more than one callback argument the macro only generates the boilerplate for the last one in the argument list.
//! For no particular reason, just vague assumption that result callbacks come last.
//!
//! ```rust
//! # use susync::sus;
//! # async fn func() {
//! fn func_with_callback(func1: impl FnOnce(i32), func2: impl FnOnce(f32)) {
//! func1(42);
//! func2(69.0);
//! }
//! // Here the macro only applies to the last closure
//! let result = sus!(func_with_callback(|_i| {}, |f| {})).await.unwrap();
//! assert_eq!(result, 69.0);
//! # }
//! ```
pub use sus;
use SpinMutex;
use ;
/// Future to suspend execution until [`SuspendHandle`] completes.
/// Handle to signal a [`SuspendFuture`] that a result is ready.
use Error;
/// The error returned by [`SuspendFuture`] in the case of the error variant.
/// An ergonomic `Result` type to wrap standard `Result` with error [`SuspendError`].
pub type SuspendResult<T> = ;
/// Creates a channel-like pair of [`SuspendFuture`] and [`SuspendHandle`].
///
/// ```rust
/// async fn func() {
/// // create future and handle pair
/// let (future, handle) = susync::create();
/// // set a result
/// handle.complete(1);
/// // await the result
/// let res = future.await.unwrap();
/// assert_eq!(res, 1);
/// }
/// ```
/// Creates a [`SuspendFuture`] from a closure.
///
/// ```rust
/// async fn func() {
/// // create future
/// let future = susync::suspend(|handle| {
/// func_with_callback(|res| {
/// // set a result
/// handle.complete(res);
/// });
/// });
/// // await the result
/// let res = future.await.unwrap();
/// }
///
/// # fn func_with_callback(func: impl FnOnce(u32)) {
/// # func(1);
/// # }
/// ```