| use core::fmt; |
| use core::marker::PhantomData; |
| |
| use {Poll, Future, Stream, Sink, StartSend}; |
| |
| mod atomic_task; |
| pub use self::atomic_task::AtomicTask; |
| |
| mod core; |
| |
| #[cfg(feature = "use_std")] |
| mod std; |
| #[cfg(feature = "use_std")] |
| pub use self::std::*; |
| #[cfg(not(feature = "use_std"))] |
| pub use self::core::*; |
| |
| pub struct BorrowedTask<'a> { |
| id: usize, |
| unpark: BorrowedUnpark<'a>, |
| events: BorrowedEvents<'a>, |
| // Task-local storage |
| map: &'a LocalMap, |
| } |
| |
| fn fresh_task_id() -> usize { |
| use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; |
| |
| // TODO: this assert is a real bummer, need to figure out how to reuse |
| // old IDs that are no longer in use. |
| // |
| // Note, though, that it is intended that these ids go away entirely |
| // eventually, see the comment on `is_current` below. |
| static NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT; |
| let id = NEXT_ID.fetch_add(1, Ordering::Relaxed); |
| assert!(id < usize::max_value() / 2, |
| "too many previous tasks have been allocated"); |
| id |
| } |
| |
| fn with<F: FnOnce(&BorrowedTask) -> R, R>(f: F) -> R { |
| unsafe { |
| let task = get_ptr().expect("no Task is currently running"); |
| assert!(!task.is_null(), "no Task is currently running"); |
| f(&*(task as *const BorrowedTask)) |
| } |
| } |
| |
| /// A handle to a "task", which represents a single lightweight "thread" of |
| /// execution driving a future to completion. |
| /// |
| /// In general, futures are composed into large units of work, which are then |
| /// spawned as tasks onto an *executor*. The executor is responsible for polling |
| /// the future as notifications arrive, until the future terminates. |
| /// |
| /// This is obtained by the `task::current` function. |
| #[derive(Clone)] |
| pub struct Task { |
| id: usize, |
| unpark: TaskUnpark, |
| events: UnparkEvents, |
| } |
| |
| trait AssertSend: Send {} |
| impl AssertSend for Task {} |
| |
| /// Returns a handle to the current task to call `notify` at a later date. |
| /// |
| /// The returned handle implements the `Send` and `'static` bounds and may also |
| /// be cheaply cloned. This is useful for squirreling away the handle into a |
| /// location which is then later signaled that a future can make progress. |
| /// |
| /// Implementations of the `Future` trait typically use this function if they |
| /// would otherwise perform a blocking operation. When something isn't ready |
| /// yet, this `current` function is called to acquire a handle to the current |
| /// task, and then the future arranges it such that when the blocking operation |
| /// otherwise finishes (perhaps in the background) it will `notify` the |
| /// returned handle. |
| /// |
| /// It's sometimes necessary to pass extra information to the task when |
| /// unparking it, so that the task knows something about *why* it was woken. |
| /// See the `FutureQueue` documentation for details on how to do this. |
| /// |
| /// # Panics |
| /// |
| /// This function will panic if a task is not currently being executed. That |
| /// is, this method can be dangerous to call outside of an implementation of |
| /// `poll`. |
| pub fn current() -> Task { |
| with(|borrowed| { |
| let unpark = borrowed.unpark.to_owned(); |
| let events = borrowed.events.to_owned(); |
| |
| Task { |
| id: borrowed.id, |
| unpark: unpark, |
| events: events, |
| } |
| }) |
| } |
| |
| #[doc(hidden)] |
| #[deprecated(note = "renamed to `current`")] |
| pub fn park() -> Task { |
| current() |
| } |
| |
| impl Task { |
| /// Indicate that the task should attempt to poll its future in a timely |
| /// fashion. |
| /// |
| /// It's typically guaranteed that, for each call to `notify`, `poll` will |
| /// be called at least once subsequently (unless the future has terminated). |
| /// If the task is currently polling its future when `notify` is called, it |
| /// must poll the future *again* afterwards, ensuring that all relevant |
| /// events are eventually observed by the future. |
| pub fn notify(&self) { |
| self.events.notify(); |
| self.unpark.notify(); |
| } |
| |
| #[doc(hidden)] |
| #[deprecated(note = "renamed to `notify`")] |
| pub fn unpark(&self) { |
| self.notify() |
| } |
| |
| /// Returns `true` when called from within the context of the task. |
| /// |
| /// In other words, the task is currently running on the thread calling the |
| /// function. Note that this is currently, and has historically, been |
| /// implemented by tracking an `id` on every instance of `Spawn` created. |
| /// When a `Spawn` is being polled it stores in thread-local-storage the id |
| /// of the instance, and then `task::current` will return a `Task` that also |
| /// stores this id. |
| /// |
| /// The intention of this function was to answer questions like "if I |
| /// `notify` this task, is it equivalent to `task::current().notify()`?" |
| /// The answer "yes" may be able to avoid some extra work to block the |
| /// current task, such as sending a task along a channel or updating a |
| /// stored `Task` somewhere. An answer of "no" typically results in doing |
| /// the work anyway. |
| /// |
| /// Unfortunately this function has been somewhat buggy in the past and is |
| /// not intended to be supported in the future. By simply matching `id` the |
| /// intended question above isn't accurately taking into account, for |
| /// example, unpark events (now deprecated, but still a feature). Thus many |
| /// old users of this API weren't fully accounting for the question it was |
| /// intended they were asking. |
| /// |
| /// This API continues to be implemented but will in the future, e.g. in the |
| /// 0.1.x series of this crate, eventually return `false` unconditionally. |
| /// It is intended that this function will be removed in the next breaking |
| /// change of this crate. If you'd like to continue to be able to answer the |
| /// example question above, it's recommended you use the |
| /// `will_notify_current` method. |
| /// |
| /// If you've got questions about this though please let us know! We'd like |
| /// to learn about other use cases here that we did not consider. |
| /// |
| /// # Panics |
| /// |
| /// This function will panic if no current future is being polled. |
| #[deprecated(note = "intended to be removed, see docs for details")] |
| pub fn is_current(&self) -> bool { |
| with(|current| current.id == self.id) |
| } |
| |
| /// This function is intended as a performance optimization for structures |
| /// which store a `Task` internally. |
| /// |
| /// The purpose of this function is to answer the question "if I `notify` |
| /// this task is it equivalent to `task::current().notify()`". An answer |
| /// "yes" may mean that you don't actually need to call `task::current()` |
| /// and store it, but rather you can simply leave a stored task in place. An |
| /// answer of "no" typically means that you need to call `task::current()` |
| /// and store it somewhere. |
| /// |
| /// As this is purely a performance optimization a valid implementation for |
| /// this function is to always return `false`. A best effort is done to |
| /// return `true` where possible, but false negatives may happen. Note that |
| /// this function will not return a false positive, however. |
| /// |
| /// # Panics |
| /// |
| /// This function will panic if no current future is being polled. |
| #[allow(deprecated)] |
| pub fn will_notify_current(&self) -> bool { |
| with(|current| { |
| self.unpark.will_notify(¤t.unpark) && |
| self.events.will_notify(¤t.events) |
| }) |
| } |
| } |
| |
| impl fmt::Debug for Task { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| f.debug_struct("Task") |
| .finish() |
| } |
| } |
| |
| /// Representation of a spawned future/stream. |
| /// |
| /// This object is returned by the `spawn` function in this module. This |
| /// represents a "fused task and future", storing all necessary pieces of a task |
| /// and owning the top-level future that's being driven as well. |
| /// |
| /// A `Spawn` can be poll'd for completion or execution of the current thread |
| /// can be blocked indefinitely until a notification arrives. This can be used |
| /// with either futures or streams, with different methods being available on |
| /// `Spawn` depending which is used. |
| pub struct Spawn<T> { |
| id: usize, |
| obj: T, |
| data: LocalMap, |
| } |
| |
| /// Spawns a new future, returning the fused future and task. |
| /// |
| /// This function is the termination endpoint for running futures. This method |
| /// will conceptually allocate a new task to run the given object, which is |
| /// normally either a `Future` or `Stream`. |
| /// |
| /// This function is similar to the `thread::spawn` function but does not |
| /// attempt to run code in the background. The future will not make progress |
| /// until the methods on `Spawn` are called in turn. |
| pub fn spawn<T>(obj: T) -> Spawn<T> { |
| Spawn { |
| id: fresh_task_id(), |
| obj: obj, |
| data: local_map(), |
| } |
| } |
| |
| impl<T> Spawn<T> { |
| /// Get a shared reference to the object the Spawn is wrapping. |
| pub fn get_ref(&self) -> &T { |
| &self.obj |
| } |
| |
| /// Get a mutable reference to the object the Spawn is wrapping. |
| pub fn get_mut(&mut self) -> &mut T { |
| &mut self.obj |
| } |
| |
| /// Consume the Spawn, returning its inner object |
| pub fn into_inner(self) -> T { |
| self.obj |
| } |
| } |
| |
| impl<F: Future> Spawn<F> { |
| /// Polls the internal future, scheduling notifications to be sent to the |
| /// `notify` argument. |
| /// |
| /// This method will poll the internal future, testing if it's completed |
| /// yet. The `notify` argument is used as a sink for notifications sent to |
| /// this future. That is, while the future is being polled, any call to |
| /// `task::current()` will return a handle that contains the `notify` |
| /// specified. |
| /// |
| /// If this function returns `NotReady`, then the `notify` should have been |
| /// scheduled to receive a notification when poll can be called again. |
| /// Otherwise if `Ready` or `Err` is returned, the `Spawn` task can be |
| /// safely destroyed. |
| /// |
| /// Note that `notify` itself is passed as a shared reference, and is itself |
| /// not required to be a `NotifyHandle`. The `Clone` and `Into` trait bounds |
| /// will be used to convert this `notify` to a `NotifyHandle` if necessary. |
| /// This construction can avoid an unnecessary atomic reference count bump |
| /// in some situations. |
| /// |
| /// ## Unsafety and `id` |
| /// |
| /// This function and all other `*_notify` functions on this type will treat |
| /// the `id` specified very carefully, explicitly calling functions like the |
| /// `notify` argument's `clone_id` and `drop_id` functions. It should be |
| /// safe to encode a pointer itself into the `id` specified, such as an |
| /// `Arc<T>` or a `Box<T>`. The `clone_id` and `drop_id` functions are then |
| /// intended to be sufficient for the memory management related to that |
| /// pointer. |
| pub fn poll_future_notify<T>(&mut self, |
| notify: &T, |
| id: usize) -> Poll<F::Item, F::Error> |
| where T: Clone + Into<NotifyHandle>, |
| { |
| let mk = || notify.clone().into(); |
| self.enter(BorrowedUnpark::new(&mk, id), |f| f.poll()) |
| } |
| } |
| |
| impl<S: Stream> Spawn<S> { |
| /// Like `poll_future_notify`, except polls the underlying stream. |
| pub fn poll_stream_notify<T>(&mut self, |
| notify: &T, |
| id: usize) |
| -> Poll<Option<S::Item>, S::Error> |
| where T: Clone + Into<NotifyHandle>, |
| { |
| let mk = || notify.clone().into(); |
| self.enter(BorrowedUnpark::new(&mk, id), |s| s.poll()) |
| } |
| } |
| |
| impl<S: Sink> Spawn<S> { |
| /// Invokes the underlying `start_send` method with this task in place. |
| /// |
| /// If the underlying operation returns `NotReady` then the `notify` value |
| /// passed in will receive a notification when the operation is ready to be |
| /// attempted again. |
| pub fn start_send_notify<T>(&mut self, |
| value: S::SinkItem, |
| notify: &T, |
| id: usize) |
| -> StartSend<S::SinkItem, S::SinkError> |
| where T: Clone + Into<NotifyHandle>, |
| { |
| let mk = || notify.clone().into(); |
| self.enter(BorrowedUnpark::new(&mk, id), |s| s.start_send(value)) |
| } |
| |
| /// Invokes the underlying `poll_complete` method with this task in place. |
| /// |
| /// If the underlying operation returns `NotReady` then the `notify` value |
| /// passed in will receive a notification when the operation is ready to be |
| /// attempted again. |
| pub fn poll_flush_notify<T>(&mut self, |
| notify: &T, |
| id: usize) |
| -> Poll<(), S::SinkError> |
| where T: Clone + Into<NotifyHandle>, |
| { |
| let mk = || notify.clone().into(); |
| self.enter(BorrowedUnpark::new(&mk, id), |s| s.poll_complete()) |
| } |
| } |
| |
| impl<T> Spawn<T> { |
| fn enter<F, R>(&mut self, unpark: BorrowedUnpark, f: F) -> R |
| where F: FnOnce(&mut T) -> R |
| { |
| let borrowed = BorrowedTask { |
| id: self.id, |
| unpark: unpark, |
| events: BorrowedEvents::new(), |
| map: &self.data, |
| }; |
| let obj = &mut self.obj; |
| set(&borrowed, || f(obj)) |
| } |
| } |
| |
| impl<T: fmt::Debug> fmt::Debug for Spawn<T> { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| f.debug_struct("Spawn") |
| .field("obj", &self.obj) |
| .finish() |
| } |
| } |
| |
| /// A trait which represents a sink of notifications that a future is ready to |
| /// make progress. |
| /// |
| /// This trait is provided as an argument to the `Spawn::*_notify` family of |
| /// functions. It's transitively used as part of the `Task::notify` method to |
| /// internally deliver notifications of readiness of a future to move forward. |
| /// |
| /// An instance of `Notify` has one primary method, `notify`, which is given a |
| /// contextual argument as to what's being notified. This contextual argument is |
| /// *also* provided to the `Spawn::*_notify` family of functions and can be used |
| /// to reuse an instance of `Notify` across many futures. |
| /// |
| /// Instances of `Notify` must be safe to share across threads, and the methods |
| /// be invoked concurrently. They must also live for the `'static` lifetime, |
| /// not containing any stack references. |
| pub trait Notify: Send + Sync { |
| /// Indicates that an associated future and/or task are ready to make |
| /// progress. |
| /// |
| /// Typically this means that the receiver of the notification should |
| /// arrange for the future to get poll'd in a prompt fashion. |
| /// |
| /// This method takes an `id` as an argument which was transitively passed |
| /// in from the original call to `Spawn::*_notify`. This id can be used to |
| /// disambiguate which precise future became ready for polling. |
| /// |
| /// # Panics |
| /// |
| /// Since `unpark` may be invoked from arbitrary contexts, it should |
| /// endeavor not to panic and to do as little work as possible. However, it |
| /// is not guaranteed not to panic, and callers should be wary. If a panic |
| /// occurs, that panic may or may not be propagated to the end-user of the |
| /// future that you'd otherwise wake up. |
| fn notify(&self, id: usize); |
| |
| /// This function is called whenever a new copy of `id` is needed. |
| /// |
| /// This is called in one of two situations: |
| /// |
| /// * A `Task` is being created through `task::current` while a future is |
| /// being polled. In that case the instance of `Notify` passed in to one |
| /// of the `poll_*` functions is called with the `id` passed into the same |
| /// `poll_*` function. |
| /// * A `Task` is itself being cloned. Each `Task` contains its own id and a |
| /// handle to the `Notify` behind it, and the task's `Notify` is used to |
| /// clone the internal `id` to assign to the new task. |
| /// |
| /// The `id` returned here will be stored in the `Task`-to-be and used later |
| /// to pass to `notify` when the `Task::notify` function is called on that |
| /// `Task`. |
| /// |
| /// Note that typically this is just the identity function, passing through |
| /// the identifier. For more unsafe situations, however, if `id` is itself a |
| /// pointer of some kind this can be used as a hook to "clone" the pointer, |
| /// depending on what that means for the specified pointer. |
| fn clone_id(&self, id: usize) -> usize { |
| id |
| } |
| |
| /// All instances of `Task` store an `id` that they're going to internally |
| /// notify with, and this function is called when the `Task` is dropped. |
| /// |
| /// This function provides a hook for schemes which encode pointers in this |
| /// `id` argument to deallocate resources associated with the pointer. It's |
| /// guaranteed that after this function is called the `Task` containing this |
| /// `id` will no longer use the `id`. |
| fn drop_id(&self, id: usize) { |
| drop(id); |
| } |
| } |
| |
| /// Sets the `NotifyHandle` of the current task for the duration of the provided |
| /// closure. |
| /// |
| /// This function takes a type that can be converted into a notify handle, |
| /// `notify` and `id`, and a closure `f`. The closure `f` will be executed such |
| /// that calls to `task::current()` will store a reference to the notify handle |
| /// provided, not the one previously in the environment. |
| /// |
| /// Note that calls to `task::current()` in the closure provided *will not* be |
| /// equivalent to `task::current()` before this method is called. The two tasks |
| /// returned will notify different handles, and the task handles pulled out |
| /// during the duration of this closure will not notify the previous task. It's |
| /// recommended that you call `task::current()` in some capacity before calling |
| /// this function to ensure that calls to `task::current()` inside of this |
| /// closure can transitively wake up the outer task. |
| /// |
| /// # Panics |
| /// |
| /// This function will panic if it is called outside the context of a future's |
| /// task. This is only valid to call once you've already entered a future via |
| /// `Spawn::poll_*` functions. |
| pub fn with_notify<F, T, R>(notify: &T, id: usize, f: F) -> R |
| where F: FnOnce() -> R, |
| T: Clone + Into<NotifyHandle>, |
| { |
| with(|task| { |
| let mk = || notify.clone().into(); |
| let new_task = BorrowedTask { |
| id: task.id, |
| unpark: BorrowedUnpark::new(&mk, id), |
| events: task.events, |
| map: task.map, |
| }; |
| |
| set(&new_task, f) |
| }) |
| } |
| |
| /// An unsafe trait for implementing custom forms of memory management behind a |
| /// `Task`. |
| /// |
| /// The `futures` critically relies on "notification handles" to extract for |
| /// futures to contain and then later inform that they're ready to make |
| /// progress. These handles, however, must be cheap to create and cheap |
| /// to clone to ensure that this operation is efficient throughout the |
| /// execution of a program. |
| /// |
| /// Typically this sort of memory management is done in the standard library |
| /// with the `Arc` type. An `Arc` is relatively cheap to allocate an is |
| /// quite cheap to clone and pass around. Plus, it's 100% safe! |
| /// |
| /// When working outside the standard library, however, you don't always have |
| /// and `Arc` type available to you. This trait, `UnsafeNotify`, is intended |
| /// to be the "unsafe version" of the `Notify` trait. This trait encodes the |
| /// memory management operations of a `Task`'s notification handle, allowing |
| /// custom implementations for the memory management of a notification handle. |
| /// |
| /// Put another way, the core notification type in this library, |
| /// `NotifyHandle`, simply internally contains an instance of |
| /// `*mut UnsafeNotify`. This "unsafe trait object" is then used exclusively |
| /// to operate with, dynamically dispatching calls to clone, drop, and notify. |
| /// Critically though as a raw pointer it doesn't require a particular form |
| /// of memory management, allowing external implementations. |
| /// |
| /// A default implementation of the `UnsafeNotify` trait is provided for the |
| /// `Arc` type in the standard library. If the `use_std` feature of this crate |
| /// is not available however, you'll be required to implement your own |
| /// instance of this trait to pass it into `NotifyHandle::new`. |
| /// |
| /// # Unsafety |
| /// |
| /// This trait is manually encoding the memory management of the underlying |
| /// handle, and as a result is quite unsafe to implement! Implementors of |
| /// this trait must guarantee: |
| /// |
| /// * Calls to `clone_raw` produce uniquely owned handles. It should be safe |
| /// to drop the current handle and have the returned handle still be valid. |
| /// * Calls to `drop_raw` work with `self` as a raw pointer, deallocating |
| /// resources associated with it. This is a pretty unsafe operation as it's |
| /// invalidating the `self` pointer, so extreme care needs to be taken. |
| /// |
| /// In general it's recommended to review the trait documentation as well as |
| /// the implementation for `Arc` in this crate. When in doubt ping the |
| /// `futures` authors to clarify an unsafety question here. |
| pub unsafe trait UnsafeNotify: Notify { |
| /// Creates a new `NotifyHandle` from this instance of `UnsafeNotify`. |
| /// |
| /// This function will create a new uniquely owned handle that under the |
| /// hood references the same notification instance. In other words calls |
| /// to `notify` on the returned handle should be equivalent to calls to |
| /// `notify` on this handle. |
| /// |
| /// # Unsafety |
| /// |
| /// This trait is unsafe to implement, as are all these methods. This |
| /// method is also unsafe to call as it's asserting the `UnsafeNotify` |
| /// value is in a consistent state. In general it's recommended to |
| /// review the trait documentation as well as the implementation for `Arc` |
| /// in this crate. When in doubt ping the `futures` authors to clarify |
| /// an unsafety question here. |
| unsafe fn clone_raw(&self) -> NotifyHandle; |
| |
| /// Drops this instance of `UnsafeNotify`, deallocating resources |
| /// associated with it. |
| /// |
| /// This method is intended to have a signature such as: |
| /// |
| /// ```ignore |
| /// fn drop_raw(self: *mut Self); |
| /// ``` |
| /// |
| /// Unfortunately in Rust today that signature is not object safe. |
| /// Nevertheless it's recommended to implement this function *as if* that |
| /// were its signature. As such it is not safe to call on an invalid |
| /// pointer, nor is the validity of the pointer guaranteed after this |
| /// function returns. |
| /// |
| /// # Unsafety |
| /// |
| /// This trait is unsafe to implement, as are all these methods. This |
| /// method is also unsafe to call as it's asserting the `UnsafeNotify` |
| /// value is in a consistent state. In general it's recommended to |
| /// review the trait documentation as well as the implementation for `Arc` |
| /// in this crate. When in doubt ping the `futures` authors to clarify |
| /// an unsafety question here. |
| unsafe fn drop_raw(&self); |
| } |
| |
| /// A `NotifyHandle` is the core value through which notifications are routed |
| /// in the `futures` crate. |
| /// |
| /// All instances of `Task` will contain a `NotifyHandle` handle internally. |
| /// This handle itself contains a trait object pointing to an instance of the |
| /// `Notify` trait, allowing notifications to get routed through it. |
| /// |
| /// The `NotifyHandle` type internally does not codify any particular memory |
| /// management strategy. Internally it contains an instance of `*mut |
| /// UnsafeNotify`, and more details about that trait can be found on its own |
| /// documentation. Consequently, though, the one constructor of this type, |
| /// `NotifyHandle::new`, is `unsafe` to call. It is not recommended to call |
| /// this constructor directly. |
| /// |
| /// If you're working with the standard library then it's recommended to |
| /// work with the `Arc` type. If you have a struct, `T`, which implements the |
| /// `Notify` trait, then you can construct this with |
| /// `NotifyHandle::from(t: Arc<T>)`. The coercion to `UnsafeNotify` will |
| /// happen automatically and safely for you. |
| /// |
| /// When working externally from the standard library it's recommended to |
| /// provide a similar safe constructor for your custom type as opposed to |
| /// recommending an invocation of `NotifyHandle::new` directly. |
| pub struct NotifyHandle { |
| inner: *mut UnsafeNotify, |
| } |
| |
| unsafe impl Send for NotifyHandle {} |
| unsafe impl Sync for NotifyHandle {} |
| |
| impl NotifyHandle { |
| /// Constructs a new `NotifyHandle` directly. |
| /// |
| /// Note that most code will not need to call this. Implementers of the |
| /// `UnsafeNotify` trait will typically provide a wrapper that calls this |
| /// but you otherwise shouldn't call it directly. |
| /// |
| /// If you're working with the standard library then it's recommended to |
| /// use the `NotifyHandle::from` function instead which works with the safe |
| /// `Arc` type and the safe `Notify` trait. |
| #[inline] |
| pub unsafe fn new(inner: *mut UnsafeNotify) -> NotifyHandle { |
| NotifyHandle { inner: inner } |
| } |
| |
| /// Invokes the underlying instance of `Notify` with the provided `id`. |
| pub fn notify(&self, id: usize) { |
| unsafe { (*self.inner).notify(id) } |
| } |
| |
| fn clone_id(&self, id: usize) -> usize { |
| unsafe { (*self.inner).clone_id(id) } |
| } |
| |
| fn drop_id(&self, id: usize) { |
| unsafe { (*self.inner).drop_id(id) } |
| } |
| } |
| |
| impl Clone for NotifyHandle { |
| #[inline] |
| fn clone(&self) -> Self { |
| unsafe { |
| (*self.inner).clone_raw() |
| } |
| } |
| } |
| |
| impl fmt::Debug for NotifyHandle { |
| fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| f.debug_struct("NotifyHandle") |
| .finish() |
| } |
| } |
| |
| impl Drop for NotifyHandle { |
| fn drop(&mut self) { |
| unsafe { |
| (*self.inner).drop_raw() |
| } |
| } |
| } |
| |
| /// Marker for a `T` that is behind &'static. |
| struct StaticRef<T>(PhantomData<T>); |
| |
| impl<T: Notify> Notify for StaticRef<T> { |
| fn notify(&self, id: usize) { |
| let me = unsafe { &*(self as *const _ as *const T) }; |
| me.notify(id); |
| } |
| |
| fn clone_id(&self, id: usize) -> usize { |
| let me = unsafe { &*(self as *const _ as *const T) }; |
| me.clone_id(id) |
| } |
| |
| fn drop_id(&self, id: usize) { |
| let me = unsafe { &*(self as *const _ as *const T) }; |
| me.drop_id(id); |
| } |
| } |
| |
| unsafe impl<T: Notify + 'static> UnsafeNotify for StaticRef<T> { |
| unsafe fn clone_raw(&self) -> NotifyHandle { |
| NotifyHandle::new(self as *const _ as *mut StaticRef<T>) |
| } |
| |
| unsafe fn drop_raw(&self) {} |
| } |
| |
| impl<T: Notify> From<&'static T> for NotifyHandle { |
| fn from(src : &'static T) -> NotifyHandle { |
| unsafe { NotifyHandle::new(src as *const _ as *mut StaticRef<T>) } |
| } |
| } |