1 use core::fmt;
2 use core::marker::PhantomData;
3
4 use {Poll, Future, Stream, Sink, StartSend};
5
6 mod atomic_task;
7 pub use self::atomic_task::AtomicTask;
8
9 mod core;
10
11 #[cfg(feature = "use_std")]
12 mod std;
13 #[cfg(feature = "use_std")]
14 pub use self::std::*;
15 #[cfg(not(feature = "use_std"))]
16 pub use self::core::*;
17
18 pub struct BorrowedTask<'a> {
19 id: usize,
20 unpark: BorrowedUnpark<'a>,
21 events: BorrowedEvents<'a>,
22 // Task-local storage
23 map: &'a LocalMap,
24 }
25
fresh_task_id() -> usize26 fn fresh_task_id() -> usize {
27 use core::sync::atomic::{AtomicUsize, Ordering};
28 #[allow(deprecated)]
29 use core::sync::atomic::ATOMIC_USIZE_INIT;
30
31 // TODO: this assert is a real bummer, need to figure out how to reuse
32 // old IDs that are no longer in use.
33 //
34 // Note, though, that it is intended that these ids go away entirely
35 // eventually, see the comment on `is_current` below.
36 #[allow(deprecated)]
37 static NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;
38 let id = NEXT_ID.fetch_add(1, Ordering::Relaxed);
39 assert!(id < usize::max_value() / 2,
40 "too many previous tasks have been allocated");
41 id
42 }
43
with<F: FnOnce(&BorrowedTask) -> R, R>(f: F) -> R44 fn with<F: FnOnce(&BorrowedTask) -> R, R>(f: F) -> R {
45 unsafe {
46 let task = get_ptr().expect("no Task is currently running");
47 assert!(!task.is_null(), "no Task is currently running");
48 f(&*(task as *const BorrowedTask))
49 }
50 }
51
52 /// A handle to a "task", which represents a single lightweight "thread" of
53 /// execution driving a future to completion.
54 ///
55 /// In general, futures are composed into large units of work, which are then
56 /// spawned as tasks onto an *executor*. The executor is responsible for polling
57 /// the future as notifications arrive, until the future terminates.
58 ///
59 /// This is obtained by the `task::current` function.
60 ///
61 /// # FAQ
62 ///
63 /// ### Why does `Task` not implement `Eq` and `Hash`?
64 ///
65 /// A valid use case for `Task` to implement these two traits has not been
66 /// encountered.
67 ///
68 /// Usually, this question is asked by someone who wants to store a `Task`
69 /// instance in a `HashSet`. This seems like an obvious way to implement a
70 /// future aware, multi-handle structure; e.g. a multi-producer channel.
71 ///
72 /// In this case, the idea is that whenever a `start_send` is called on one of
73 /// the channel's send handles, if the channel is at capacity, the current task
74 /// is stored in a set. Then, when capacity is available, a task is removed from
75 /// the set and notified.
76 ///
77 /// The problem with this strategy is that multiple `Sender` handles can be used
78 /// on the same task. In this case, when the second handle is used and the task
79 /// is stored in a set, there already is an entry. Then, when the first
80 /// handle is dropped, this entry is cleared, resulting in a dead lock.
81 ///
82 /// See [here](https://github.com/rust-lang-nursery/futures-rs/issues/670) for
83 /// more discussion.
84 ///
85 #[derive(Clone)]
86 pub struct Task {
87 id: usize,
88 unpark: TaskUnpark,
89 events: UnparkEvents,
90 }
91
92 trait AssertSend: Send {}
93 impl AssertSend for Task {}
94
95 /// Returns a handle to the current task to call `notify` at a later date.
96 ///
97 /// The returned handle implements the `Send` and `'static` bounds and may also
98 /// be cheaply cloned. This is useful for squirreling away the handle into a
99 /// location which is then later signaled that a future can make progress.
100 ///
101 /// Implementations of the `Future` trait typically use this function if they
102 /// would otherwise perform a blocking operation. When something isn't ready
103 /// yet, this `current` function is called to acquire a handle to the current
104 /// task, and then the future arranges it such that when the blocking operation
105 /// otherwise finishes (perhaps in the background) it will `notify` the
106 /// returned handle.
107 ///
108 /// It's sometimes necessary to pass extra information to the task when
109 /// unparking it, so that the task knows something about *why* it was woken.
110 /// See the `FutureQueue` documentation for details on how to do this.
111 ///
112 /// # Panics
113 ///
114 /// This function will panic if a task is not currently being executed. That
115 /// is, this method can be dangerous to call outside of an implementation of
116 /// `poll`.
current() -> Task117 pub fn current() -> Task {
118 with(|borrowed| {
119 let unpark = borrowed.unpark.to_owned();
120 let events = borrowed.events.to_owned();
121
122 Task {
123 id: borrowed.id,
124 unpark: unpark,
125 events: events,
126 }
127 })
128 }
129
130 #[doc(hidden)]
131 #[deprecated(note = "renamed to `current`")]
park() -> Task132 pub fn park() -> Task {
133 current()
134 }
135
136 impl Task {
137 /// Indicate that the task should attempt to poll its future in a timely
138 /// fashion.
139 ///
140 /// It's typically guaranteed that, after calling `notify`, `poll` will
141 /// be called at least once subsequently (unless the future has terminated).
142 /// If the task is currently polling its future when `notify` is called, it
143 /// must poll the future *again* afterwards, ensuring that all relevant
144 /// events are eventually observed by the future.
notify(&self)145 pub fn notify(&self) {
146 self.events.notify();
147 self.unpark.notify();
148 }
149
150 #[doc(hidden)]
151 #[deprecated(note = "renamed to `notify`")]
unpark(&self)152 pub fn unpark(&self) {
153 self.notify()
154 }
155
156 /// Returns `true` when called from within the context of the task.
157 ///
158 /// In other words, the task is currently running on the thread calling the
159 /// function. Note that this is currently, and has historically, been
160 /// implemented by tracking an `id` on every instance of `Spawn` created.
161 /// When a `Spawn` is being polled it stores in thread-local-storage the id
162 /// of the instance, and then `task::current` will return a `Task` that also
163 /// stores this id.
164 ///
165 /// The intention of this function was to answer questions like "if I
166 /// `notify` this task, is it equivalent to `task::current().notify()`?"
167 /// The answer "yes" may be able to avoid some extra work to block the
168 /// current task, such as sending a task along a channel or updating a
169 /// stored `Task` somewhere. An answer of "no" typically results in doing
170 /// the work anyway.
171 ///
172 /// Unfortunately this function has been somewhat buggy in the past and is
173 /// not intended to be supported in the future. By simply matching `id` the
174 /// intended question above isn't accurately taking into account, for
175 /// example, unpark events (now deprecated, but still a feature). Thus many
176 /// old users of this API weren't fully accounting for the question it was
177 /// intended they were asking.
178 ///
179 /// This API continues to be implemented but will in the future, e.g. in the
180 /// 0.1.x series of this crate, eventually return `false` unconditionally.
181 /// It is intended that this function will be removed in the next breaking
182 /// change of this crate. If you'd like to continue to be able to answer the
183 /// example question above, it's recommended you use the
184 /// `will_notify_current` method.
185 ///
186 /// If you've got questions about this though please let us know! We'd like
187 /// to learn about other use cases here that we did not consider.
188 ///
189 /// # Panics
190 ///
191 /// This function will panic if no current future is being polled.
192 #[deprecated(note = "intended to be removed, see docs for details")]
is_current(&self) -> bool193 pub fn is_current(&self) -> bool {
194 with(|current| current.id == self.id)
195 }
196
197 /// This function is intended as a performance optimization for structures
198 /// which store a `Task` internally.
199 ///
200 /// The purpose of this function is to answer the question "if I `notify`
201 /// this task is it equivalent to `task::current().notify()`". An answer
202 /// "yes" may mean that you don't actually need to call `task::current()`
203 /// and store it, but rather you can simply leave a stored task in place. An
204 /// answer of "no" typically means that you need to call `task::current()`
205 /// and store it somewhere.
206 ///
207 /// As this is purely a performance optimization a valid implementation for
208 /// this function is to always return `false`. A best effort is done to
209 /// return `true` where possible, but false negatives may happen. Note that
210 /// this function will not return a false positive, however.
211 ///
212 /// # Panics
213 ///
214 /// This function will panic if no current future is being polled.
215 #[allow(deprecated)]
will_notify_current(&self) -> bool216 pub fn will_notify_current(&self) -> bool {
217 with(|current| {
218 self.unpark.will_notify(¤t.unpark) &&
219 self.events.will_notify(¤t.events)
220 })
221 }
222 }
223
224 impl fmt::Debug for Task {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result225 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
226 f.debug_struct("Task")
227 .finish()
228 }
229 }
230
231 /// Representation of a spawned future/stream.
232 ///
233 /// This object is returned by the `spawn` function in this module. This
234 /// represents a "fused task and future", storing all necessary pieces of a task
235 /// and owning the top-level future that's being driven as well.
236 ///
237 /// A `Spawn` can be poll'd for completion or execution of the current thread
238 /// can be blocked indefinitely until a notification arrives. This can be used
239 /// with either futures or streams, with different methods being available on
240 /// `Spawn` depending which is used.
241 pub struct Spawn<T: ?Sized> {
242 id: usize,
243 data: LocalMap,
244 obj: T,
245 }
246
247 /// Spawns a future or stream, returning it and the new task responsible for
248 /// running it to completion.
249 ///
250 /// This function is the termination endpoint for running futures. This method
251 /// will conceptually allocate a new task to run the given object, which is
252 /// normally either a `Future` or `Stream`.
253 ///
254 /// This function is similar to the `thread::spawn` function but does not
255 /// attempt to run code in the background. The future will not make progress
256 /// until the methods on `Spawn` are called in turn.
spawn<T>(obj: T) -> Spawn<T>257 pub fn spawn<T>(obj: T) -> Spawn<T> {
258 Spawn {
259 id: fresh_task_id(),
260 obj: obj,
261 data: local_map(),
262 }
263 }
264
265 impl<T: ?Sized> Spawn<T> {
266 /// Get a shared reference to the object the Spawn is wrapping.
get_ref(&self) -> &T267 pub fn get_ref(&self) -> &T {
268 &self.obj
269 }
270
271 /// Get a mutable reference to the object the Spawn is wrapping.
get_mut(&mut self) -> &mut T272 pub fn get_mut(&mut self) -> &mut T {
273 &mut self.obj
274 }
275
276 /// Consume the Spawn, returning its inner object
into_inner(self) -> T where T: Sized277 pub fn into_inner(self) -> T where T: Sized {
278 self.obj
279 }
280
281 /// Calls the provided closure, scheduling notifications to be sent to the
282 /// `notify` argument.
poll_fn_notify<N, F, R>(&mut self, notify: &N, id: usize, f: F) -> R where F: FnOnce(&mut T) -> R, N: Clone + Into<NotifyHandle>,283 pub fn poll_fn_notify<N, F, R>(&mut self,
284 notify: &N,
285 id: usize,
286 f: F) -> R
287 where F: FnOnce(&mut T) -> R,
288 N: Clone + Into<NotifyHandle>,
289 {
290 let mk = || notify.clone().into();
291 self.enter(BorrowedUnpark::new(&mk, id), f)
292 }
293
294 /// Polls the internal future, scheduling notifications to be sent to the
295 /// `notify` argument.
296 ///
297 /// This method will poll the internal future, testing if it's completed
298 /// yet. The `notify` argument is used as a sink for notifications sent to
299 /// this future. That is, while the future is being polled, any call to
300 /// `task::current()` will return a handle that contains the `notify`
301 /// specified.
302 ///
303 /// If this function returns `NotReady`, then the `notify` should have been
304 /// scheduled to receive a notification when poll can be called again.
305 /// Otherwise if `Ready` or `Err` is returned, the `Spawn` task can be
306 /// safely destroyed.
307 ///
308 /// Note that `notify` itself is passed as a shared reference, and is itself
309 /// not required to be a `NotifyHandle`. The `Clone` and `Into` trait bounds
310 /// will be used to convert this `notify` to a `NotifyHandle` if necessary.
311 /// This construction can avoid an unnecessary atomic reference count bump
312 /// in some situations.
313 ///
314 /// ## Unsafety and `id`
315 ///
316 /// This function and all other `*_notify` functions on this type will treat
317 /// the `id` specified very carefully, explicitly calling functions like the
318 /// `notify` argument's `clone_id` and `drop_id` functions. It should be
319 /// safe to encode a pointer itself into the `id` specified, such as an
320 /// `Arc<N>` or a `Box<N>`. The `clone_id` and `drop_id` functions are then
321 /// intended to be sufficient for the memory management related to that
322 /// pointer.
poll_future_notify<N>(&mut self, notify: &N, id: usize) -> Poll<T::Item, T::Error> where N: Clone + Into<NotifyHandle>, T: Future,323 pub fn poll_future_notify<N>(&mut self,
324 notify: &N,
325 id: usize) -> Poll<T::Item, T::Error>
326 where N: Clone + Into<NotifyHandle>,
327 T: Future,
328 {
329 self.poll_fn_notify(notify, id, |f| f.poll())
330 }
331
332 /// Like `poll_future_notify`, except polls the underlying stream.
poll_stream_notify<N>(&mut self, notify: &N, id: usize) -> Poll<Option<T::Item>, T::Error> where N: Clone + Into<NotifyHandle>, T: Stream,333 pub fn poll_stream_notify<N>(&mut self,
334 notify: &N,
335 id: usize)
336 -> Poll<Option<T::Item>, T::Error>
337 where N: Clone + Into<NotifyHandle>,
338 T: Stream,
339 {
340 self.poll_fn_notify(notify, id, |s| s.poll())
341 }
342
343 /// Invokes the underlying `start_send` method with this task in place.
344 ///
345 /// If the underlying operation returns `NotReady` then the `notify` value
346 /// passed in will receive a notification when the operation is ready to be
347 /// attempted again.
start_send_notify<N>(&mut self, value: T::SinkItem, notify: &N, id: usize) -> StartSend<T::SinkItem, T::SinkError> where N: Clone + Into<NotifyHandle>, T: Sink,348 pub fn start_send_notify<N>(&mut self,
349 value: T::SinkItem,
350 notify: &N,
351 id: usize)
352 -> StartSend<T::SinkItem, T::SinkError>
353 where N: Clone + Into<NotifyHandle>,
354 T: Sink,
355 {
356 self.poll_fn_notify(notify, id, |s| s.start_send(value))
357 }
358
359 /// Invokes the underlying `poll_complete` method with this task in place.
360 ///
361 /// If the underlying operation returns `NotReady` then the `notify` value
362 /// passed in will receive a notification when the operation is ready to be
363 /// attempted again.
poll_flush_notify<N>(&mut self, notify: &N, id: usize) -> Poll<(), T::SinkError> where N: Clone + Into<NotifyHandle>, T: Sink,364 pub fn poll_flush_notify<N>(&mut self,
365 notify: &N,
366 id: usize)
367 -> Poll<(), T::SinkError>
368 where N: Clone + Into<NotifyHandle>,
369 T: Sink,
370 {
371 self.poll_fn_notify(notify, id, |s| s.poll_complete())
372 }
373
374 /// Invokes the underlying `close` method with this task in place.
375 ///
376 /// If the underlying operation returns `NotReady` then the `notify` value
377 /// passed in will receive a notification when the operation is ready to be
378 /// attempted again.
close_notify<N>(&mut self, notify: &N, id: usize) -> Poll<(), T::SinkError> where N: Clone + Into<NotifyHandle>, T: Sink,379 pub fn close_notify<N>(&mut self,
380 notify: &N,
381 id: usize)
382 -> Poll<(), T::SinkError>
383 where N: Clone + Into<NotifyHandle>,
384 T: Sink,
385 {
386 self.poll_fn_notify(notify, id, |s| s.close())
387 }
388
enter<F, R>(&mut self, unpark: BorrowedUnpark, f: F) -> R where F: FnOnce(&mut T) -> R389 fn enter<F, R>(&mut self, unpark: BorrowedUnpark, f: F) -> R
390 where F: FnOnce(&mut T) -> R
391 {
392 let borrowed = BorrowedTask {
393 id: self.id,
394 unpark: unpark,
395 events: BorrowedEvents::new(),
396 map: &self.data,
397 };
398 let obj = &mut self.obj;
399 set(&borrowed, || f(obj))
400 }
401 }
402
403 impl<T: fmt::Debug + ?Sized> fmt::Debug for Spawn<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result404 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
405 f.debug_struct("Spawn")
406 .field("obj", &&self.obj)
407 .finish()
408 }
409 }
410
411 /// A trait which represents a sink of notifications that a future is ready to
412 /// make progress.
413 ///
414 /// This trait is provided as an argument to the `Spawn::*_notify` family of
415 /// functions. It's transitively used as part of the `Task::notify` method to
416 /// internally deliver notifications of readiness of a future to move forward.
417 ///
418 /// An instance of `Notify` has one primary method, `notify`, which is given a
419 /// contextual argument as to what's being notified. This contextual argument is
420 /// *also* provided to the `Spawn::*_notify` family of functions and can be used
421 /// to reuse an instance of `Notify` across many futures.
422 ///
423 /// Instances of `Notify` must be safe to share across threads, and the methods
424 /// be invoked concurrently. They must also live for the `'static` lifetime,
425 /// not containing any stack references.
426 pub trait Notify: Send + Sync {
427 /// Indicates that an associated future and/or task are ready to make
428 /// progress.
429 ///
430 /// Typically this means that the receiver of the notification should
431 /// arrange for the future to get poll'd in a prompt fashion.
432 ///
433 /// This method takes an `id` as an argument which was transitively passed
434 /// in from the original call to `Spawn::*_notify`. This id can be used to
435 /// disambiguate which precise future became ready for polling.
436 ///
437 /// # Panics
438 ///
439 /// Since `unpark` may be invoked from arbitrary contexts, it should
440 /// endeavor not to panic and to do as little work as possible. However, it
441 /// is not guaranteed not to panic, and callers should be wary. If a panic
442 /// occurs, that panic may or may not be propagated to the end-user of the
443 /// future that you'd otherwise wake up.
notify(&self, id: usize)444 fn notify(&self, id: usize);
445
446 /// This function is called whenever a new copy of `id` is needed.
447 ///
448 /// This is called in one of two situations:
449 ///
450 /// * A `Task` is being created through `task::current` while a future is
451 /// being polled. In that case the instance of `Notify` passed in to one
452 /// of the `poll_*` functions is called with the `id` passed into the same
453 /// `poll_*` function.
454 /// * A `Task` is itself being cloned. Each `Task` contains its own id and a
455 /// handle to the `Notify` behind it, and the task's `Notify` is used to
456 /// clone the internal `id` to assign to the new task.
457 ///
458 /// The `id` returned here will be stored in the `Task`-to-be and used later
459 /// to pass to `notify` when the `Task::notify` function is called on that
460 /// `Task`.
461 ///
462 /// Note that typically this is just the identity function, passing through
463 /// the identifier. For more unsafe situations, however, if `id` is itself a
464 /// pointer of some kind this can be used as a hook to "clone" the pointer,
465 /// depending on what that means for the specified pointer.
clone_id(&self, id: usize) -> usize466 fn clone_id(&self, id: usize) -> usize {
467 id
468 }
469
470 /// All instances of `Task` store an `id` that they're going to internally
471 /// notify with, and this function is called when the `Task` is dropped.
472 ///
473 /// This function provides a hook for schemes which encode pointers in this
474 /// `id` argument to deallocate resources associated with the pointer. It's
475 /// guaranteed that after this function is called the `Task` containing this
476 /// `id` will no longer use the `id`.
drop_id(&self, id: usize)477 fn drop_id(&self, id: usize) {
478 drop(id);
479 }
480 }
481
482 /// Sets the `NotifyHandle` of the current task for the duration of the provided
483 /// closure.
484 ///
485 /// This function takes a type that can be converted into a notify handle,
486 /// `notify` and `id`, and a closure `f`. The closure `f` will be executed such
487 /// that calls to `task::current()` will store a reference to the notify handle
488 /// provided, not the one previously in the environment.
489 ///
490 /// Note that calls to `task::current()` in the closure provided *will not* be
491 /// equivalent to `task::current()` before this method is called. The two tasks
492 /// returned will notify different handles, and the task handles pulled out
493 /// during the duration of this closure will not notify the previous task. It's
494 /// recommended that you call `task::current()` in some capacity before calling
495 /// this function to ensure that calls to `task::current()` inside of this
496 /// closure can transitively wake up the outer task.
497 ///
498 /// # Panics
499 ///
500 /// This function will panic if it is called outside the context of a future's
501 /// task. This is only valid to call once you've already entered a future via
502 /// `Spawn::poll_*` functions.
with_notify<F, T, R>(notify: &T, id: usize, f: F) -> R where F: FnOnce() -> R, T: Clone + Into<NotifyHandle>,503 pub fn with_notify<F, T, R>(notify: &T, id: usize, f: F) -> R
504 where F: FnOnce() -> R,
505 T: Clone + Into<NotifyHandle>,
506 {
507 with(|task| {
508 let mk = || notify.clone().into();
509 let new_task = BorrowedTask {
510 id: task.id,
511 unpark: BorrowedUnpark::new(&mk, id),
512 events: task.events,
513 map: task.map,
514 };
515
516 set(&new_task, f)
517 })
518 }
519
520 /// An unsafe trait for implementing custom forms of memory management behind a
521 /// `Task`.
522 ///
523 /// The `futures` critically relies on "notification handles" to extract for
524 /// futures to contain and then later inform that they're ready to make
525 /// progress. These handles, however, must be cheap to create and cheap
526 /// to clone to ensure that this operation is efficient throughout the
527 /// execution of a program.
528 ///
529 /// Typically this sort of memory management is done in the standard library
530 /// with the `Arc` type. An `Arc` is relatively cheap to allocate an is
531 /// quite cheap to clone and pass around. Plus, it's 100% safe!
532 ///
533 /// When working outside the standard library, however, you don't always have
534 /// and `Arc` type available to you. This trait, `UnsafeNotify`, is intended
535 /// to be the "unsafe version" of the `Notify` trait. This trait encodes the
536 /// memory management operations of a `Task`'s notification handle, allowing
537 /// custom implementations for the memory management of a notification handle.
538 ///
539 /// Put another way, the core notification type in this library,
540 /// `NotifyHandle`, simply internally contains an instance of
541 /// `*mut UnsafeNotify`. This "unsafe trait object" is then used exclusively
542 /// to operate with, dynamically dispatching calls to clone, drop, and notify.
543 /// Critically though as a raw pointer it doesn't require a particular form
544 /// of memory management, allowing external implementations.
545 ///
546 /// A default implementation of the `UnsafeNotify` trait is provided for the
547 /// `Arc` type in the standard library. If the `use_std` feature of this crate
548 /// is not available however, you'll be required to implement your own
549 /// instance of this trait to pass it into `NotifyHandle::new`.
550 ///
551 /// # Unsafety
552 ///
553 /// This trait is manually encoding the memory management of the underlying
554 /// handle, and as a result is quite unsafe to implement! Implementors of
555 /// this trait must guarantee:
556 ///
557 /// * Calls to `clone_raw` produce uniquely owned handles. It should be safe
558 /// to drop the current handle and have the returned handle still be valid.
559 /// * Calls to `drop_raw` work with `self` as a raw pointer, deallocating
560 /// resources associated with it. This is a pretty unsafe operation as it's
561 /// invalidating the `self` pointer, so extreme care needs to be taken.
562 ///
563 /// In general it's recommended to review the trait documentation as well as
564 /// the implementation for `Arc` in this crate. When in doubt ping the
565 /// `futures` authors to clarify an unsafety question here.
566 pub unsafe trait UnsafeNotify: Notify {
567 /// Creates a new `NotifyHandle` from this instance of `UnsafeNotify`.
568 ///
569 /// This function will create a new uniquely owned handle that under the
570 /// hood references the same notification instance. In other words calls
571 /// to `notify` on the returned handle should be equivalent to calls to
572 /// `notify` on this handle.
573 ///
574 /// # Unsafety
575 ///
576 /// This trait is unsafe to implement, as are all these methods. This
577 /// method is also unsafe to call as it's asserting the `UnsafeNotify`
578 /// value is in a consistent state. In general it's recommended to
579 /// review the trait documentation as well as the implementation for `Arc`
580 /// in this crate. When in doubt ping the `futures` authors to clarify
581 /// an unsafety question here.
clone_raw(&self) -> NotifyHandle582 unsafe fn clone_raw(&self) -> NotifyHandle;
583
584 /// Drops this instance of `UnsafeNotify`, deallocating resources
585 /// associated with it.
586 ///
587 /// This method is intended to have a signature such as:
588 ///
589 /// ```ignore
590 /// fn drop_raw(self: *mut Self);
591 /// ```
592 ///
593 /// Unfortunately in Rust today that signature is not object safe.
594 /// Nevertheless it's recommended to implement this function *as if* that
595 /// were its signature. As such it is not safe to call on an invalid
596 /// pointer, nor is the validity of the pointer guaranteed after this
597 /// function returns.
598 ///
599 /// # Unsafety
600 ///
601 /// This trait is unsafe to implement, as are all these methods. This
602 /// method is also unsafe to call as it's asserting the `UnsafeNotify`
603 /// value is in a consistent state. In general it's recommended to
604 /// review the trait documentation as well as the implementation for `Arc`
605 /// in this crate. When in doubt ping the `futures` authors to clarify
606 /// an unsafety question here.
drop_raw(&self)607 unsafe fn drop_raw(&self);
608 }
609
610 /// A `NotifyHandle` is the core value through which notifications are routed
611 /// in the `futures` crate.
612 ///
613 /// All instances of `Task` will contain a `NotifyHandle` handle internally.
614 /// This handle itself contains a trait object pointing to an instance of the
615 /// `Notify` trait, allowing notifications to get routed through it.
616 ///
617 /// The `NotifyHandle` type internally does not codify any particular memory
618 /// management strategy. Internally it contains an instance of `*mut
619 /// UnsafeNotify`, and more details about that trait can be found on its own
620 /// documentation. Consequently, though, the one constructor of this type,
621 /// `NotifyHandle::new`, is `unsafe` to call. It is not recommended to call
622 /// this constructor directly.
623 ///
624 /// If you're working with the standard library then it's recommended to
625 /// work with the `Arc` type. If you have a struct, `T`, which implements the
626 /// `Notify` trait, then you can construct this with
627 /// `NotifyHandle::from(t: Arc<T>)`. The coercion to `UnsafeNotify` will
628 /// happen automatically and safely for you.
629 ///
630 /// When working externally from the standard library it's recommended to
631 /// provide a similar safe constructor for your custom type as opposed to
632 /// recommending an invocation of `NotifyHandle::new` directly.
633 pub struct NotifyHandle {
634 inner: *mut UnsafeNotify,
635 }
636
637 unsafe impl Send for NotifyHandle {}
638 unsafe impl Sync for NotifyHandle {}
639
640 impl NotifyHandle {
641 /// Constructs a new `NotifyHandle` directly.
642 ///
643 /// Note that most code will not need to call this. Implementers of the
644 /// `UnsafeNotify` trait will typically provide a wrapper that calls this
645 /// but you otherwise shouldn't call it directly.
646 ///
647 /// If you're working with the standard library then it's recommended to
648 /// use the `NotifyHandle::from` function instead which works with the safe
649 /// `Arc` type and the safe `Notify` trait.
650 #[inline]
new(inner: *mut UnsafeNotify) -> NotifyHandle651 pub unsafe fn new(inner: *mut UnsafeNotify) -> NotifyHandle {
652 NotifyHandle { inner: inner }
653 }
654
655 /// Invokes the underlying instance of `Notify` with the provided `id`.
notify(&self, id: usize)656 pub fn notify(&self, id: usize) {
657 unsafe { (*self.inner).notify(id) }
658 }
659
clone_id(&self, id: usize) -> usize660 fn clone_id(&self, id: usize) -> usize {
661 unsafe { (*self.inner).clone_id(id) }
662 }
663
drop_id(&self, id: usize)664 fn drop_id(&self, id: usize) {
665 unsafe { (*self.inner).drop_id(id) }
666 }
667 }
668
669 impl Clone for NotifyHandle {
670 #[inline]
clone(&self) -> Self671 fn clone(&self) -> Self {
672 unsafe {
673 (*self.inner).clone_raw()
674 }
675 }
676 }
677
678 impl fmt::Debug for NotifyHandle {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result679 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
680 f.debug_struct("NotifyHandle")
681 .finish()
682 }
683 }
684
685 impl Drop for NotifyHandle {
drop(&mut self)686 fn drop(&mut self) {
687 unsafe {
688 (*self.inner).drop_raw()
689 }
690 }
691 }
692
693 /// Marker for a `T` that is behind &'static.
694 struct StaticRef<T>(PhantomData<T>);
695
696 impl<T: Notify> Notify for StaticRef<T> {
notify(&self, id: usize)697 fn notify(&self, id: usize) {
698 let me = unsafe { &*(self as *const _ as *const T) };
699 me.notify(id);
700 }
701
clone_id(&self, id: usize) -> usize702 fn clone_id(&self, id: usize) -> usize {
703 let me = unsafe { &*(self as *const _ as *const T) };
704 me.clone_id(id)
705 }
706
drop_id(&self, id: usize)707 fn drop_id(&self, id: usize) {
708 let me = unsafe { &*(self as *const _ as *const T) };
709 me.drop_id(id);
710 }
711 }
712
713 unsafe impl<T: Notify + 'static> UnsafeNotify for StaticRef<T> {
clone_raw(&self) -> NotifyHandle714 unsafe fn clone_raw(&self) -> NotifyHandle {
715 NotifyHandle::new(self as *const _ as *mut StaticRef<T>)
716 }
717
drop_raw(&self)718 unsafe fn drop_raw(&self) {}
719 }
720
721 impl<T: Notify> From<&'static T> for NotifyHandle {
from(src : &'static T) -> NotifyHandle722 fn from(src : &'static T) -> NotifyHandle {
723 unsafe { NotifyHandle::new(src as *const _ as *mut StaticRef<T>) }
724 }
725 }
726
727 #[cfg(feature = "nightly")]
728 mod nightly {
729 use super::NotifyHandle;
730 use core::marker::Unpin;
731
732 impl Unpin for NotifyHandle {}
733 }
734