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
//! An executor to run futures in the idle cycles of a Glib/Gtk application.
//!
//! This crate provides a function that programs a future to be run using the
//! _idle_ time of the main loop, as provided by [`glib::idle_add`](../glib/source/fn.idle_add.html).
//!
//! It works by registering an idle function to poll the future once, and whenever the future is
//! awoken, it will register another idle function to be continued, and so on.
//!
//! The main advantage of this approach is that the future is run in the main loop.
//! As such, it does not need to be `Send`, it does not require any kind of synchronization
//! to access shared state, and it can even manipulate GUI objects directly.
//!
//! Naturally, you still need to be careful, because if you set up several idle futures at the same
//! time they will be run intermixed.
//!
//! # What can it be used for?
//!
//! You can use this crate to implement async I/O that handles the GUI without the need of
//! synchronization. For example you can download assets or updates from the internet, or provide
//! an API for automating your GUI.
//!
//! You can also use async functions to implement background tasks that run when the program is
//! idle. They can be interrupted at any time and they can update the GUI directly. A similar
//! technique can be used to easily build a progress bar for a long-running process. Just add
//! something like this call here and there:
//! ```
//! async_std::task::yield_now().await;
//! ```
//!
//! # Working with other async frameworks
//!
//! You can run almost any future as an idle future, but if it uses functionality from any async
//! framework (`async_std`, `smol`, `tokio`...) it will most likely need to be initialized first,
//! or else your futures will not advance. This is because these frameworks usually work by creating
//! a background thread that does the actual polling and wakes up the other futures. If this
//! background thread is not created, nothing will be polled and your futures will stall forever.
//!
//! You may think that interacting with other fraworks is going to be difficult. But actually it is
//! super easy, barely an inconvenience:
//!
//! ## `async_std`
//!
//! Spawning any async task will bootstrap the runtime, so just this from your `main` is enough:
//! ```
//! async_std::task::spawn(async {});
//! ```
//!
//! ## `smol`
//!
//! There must be at least one thread runing an async job, and it will do that and poll all the
//! futures. So the code would be something like this, that will spawn a never-ending future:
//! ```
//! std::thread::spawn(|| smol::run(futures::future::pending::<()>()));
//! ```
//! If you also use `async_std`, since it uses `smol` under the hood, you just need one of these.
//!
//! ## `tokio`
//!
//! In `tokio` futures need to be spawn from a tokio reactor. It is enough if you run your main loop from there:
//! ```
//! let mut rt = tokio::runtime::Builder::new()
//! .threaded_scheduler()
//! .enable_all()
//! .build()
//! .unwrap();
//! rt.block_on(async { gtk::main() });
//!```
//!
//!Or you can decorate your `main` function with:
//!```
//!#[tokio::main]
//!async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! //...
//!}
//!```
use *;
use ;
//The raw pointer in the RawWaker will be a pointer to an Arc-allocated GIdleTask
unsafe
unsafe
unsafe
unsafe
unsafe
unsafe
static GWAKER_VTABLE: RawWakerVTable = new;
//Actually the inner future is not Send, but GIdleTask is private to this module, so if
//we are careful we can move it between threads, as long as we only use the future in the
//main thread.
unsafe
unsafe
//poll_idle() can be called from an arbitrary thread, because Waker is Send,
//but once we are in the glib::source::idle_add() callback we are in the main loop.
//When it ends, Waker::drop decrements the counter for the Arc<GIdleTask>.
/// Spawns an idle future.
///
/// This function registers the given future to be run in the idle time of the main Glib loop.
///
/// It must be called from the main Glib loop or it will panic. Since the future will be run in the
/// same thread, it does not need to be `Send`.
///
/// The future can return any value, but it is discarded.
///
/// Currently there is no way to cancel a future. If you need that you can use `futures::future::AbortHandle`.
///
/// A handle to a running idle future.
///
/// You can use this handle to cancel the future and to retrieve the return
/// value of a future that has finished.
///
/// If the Handle is dropped, the future will keep on running, and there will
/// be no way to cancel it or get the return value.