Skip to content

Commit 66a78a0

Browse files
authored
Merge pull request #609 from cramertj/unsized-spawn
Allow Spawn to be unsized
2 parents 9f3f6cd + 2321b84 commit 66a78a0

File tree

2 files changed

+47
-36
lines changed

2 files changed

+47
-36
lines changed

src/task_impl/mod.rs

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,10 @@ impl fmt::Debug for Task {
210210
/// can be blocked indefinitely until a notification arrives. This can be used
211211
/// with either futures or streams, with different methods being available on
212212
/// `Spawn` depending which is used.
213-
pub struct Spawn<T> {
213+
pub struct Spawn<T: ?Sized> {
214214
id: usize,
215-
obj: T,
216215
data: LocalMap,
216+
obj: T,
217217
}
218218

219219
/// Spawns a new future, returning the fused future and task.
@@ -233,7 +233,7 @@ pub fn spawn<T>(obj: T) -> Spawn<T> {
233233
}
234234
}
235235

236-
impl<T> Spawn<T> {
236+
impl<T: ?Sized> Spawn<T> {
237237
/// Get a shared reference to the object the Spawn is wrapping.
238238
pub fn get_ref(&self) -> &T {
239239
&self.obj
@@ -245,12 +245,10 @@ impl<T> Spawn<T> {
245245
}
246246

247247
/// Consume the Spawn, returning its inner object
248-
pub fn into_inner(self) -> T {
248+
pub fn into_inner(self) -> T where T: Sized {
249249
self.obj
250250
}
251-
}
252251

253-
impl<F: Future> Spawn<F> {
254252
/// Polls the internal future, scheduling notifications to be sent to the
255253
/// `notify` argument.
256254
///
@@ -277,44 +275,43 @@ impl<F: Future> Spawn<F> {
277275
/// the `id` specified very carefully, explicitly calling functions like the
278276
/// `notify` argument's `clone_id` and `drop_id` functions. It should be
279277
/// safe to encode a pointer itself into the `id` specified, such as an
280-
/// `Arc<T>` or a `Box<T>`. The `clone_id` and `drop_id` functions are then
278+
/// `Arc<N>` or a `Box<N>`. The `clone_id` and `drop_id` functions are then
281279
/// intended to be sufficient for the memory management related to that
282280
/// pointer.
283-
pub fn poll_future_notify<T>(&mut self,
284-
notify: &T,
285-
id: usize) -> Poll<F::Item, F::Error>
286-
where T: Clone + Into<NotifyHandle>,
281+
pub fn poll_future_notify<N>(&mut self,
282+
notify: &N,
283+
id: usize) -> Poll<T::Item, T::Error>
284+
where N: Clone + Into<NotifyHandle>,
285+
T: Future,
287286
{
288287
let mk = || notify.clone().into();
289288
self.enter(BorrowedUnpark::new(&mk, id), |f| f.poll())
290289
}
291-
}
292290

293-
impl<S: Stream> Spawn<S> {
294291
/// Like `poll_future_notify`, except polls the underlying stream.
295-
pub fn poll_stream_notify<T>(&mut self,
296-
notify: &T,
292+
pub fn poll_stream_notify<N>(&mut self,
293+
notify: &N,
297294
id: usize)
298-
-> Poll<Option<S::Item>, S::Error>
299-
where T: Clone + Into<NotifyHandle>,
295+
-> Poll<Option<T::Item>, T::Error>
296+
where N: Clone + Into<NotifyHandle>,
297+
T: Stream,
300298
{
301299
let mk = || notify.clone().into();
302300
self.enter(BorrowedUnpark::new(&mk, id), |s| s.poll())
303301
}
304-
}
305302

306-
impl<S: Sink> Spawn<S> {
307303
/// Invokes the underlying `start_send` method with this task in place.
308304
///
309305
/// If the underlying operation returns `NotReady` then the `notify` value
310306
/// passed in will receive a notification when the operation is ready to be
311307
/// attempted again.
312-
pub fn start_send_notify<T>(&mut self,
313-
value: S::SinkItem,
314-
notify: &T,
308+
pub fn start_send_notify<N>(&mut self,
309+
value: T::SinkItem,
310+
notify: &N,
315311
id: usize)
316-
-> StartSend<S::SinkItem, S::SinkError>
317-
where T: Clone + Into<NotifyHandle>,
312+
-> StartSend<T::SinkItem, T::SinkError>
313+
where N: Clone + Into<NotifyHandle>,
314+
T: Sink,
318315
{
319316
let mk = || notify.clone().into();
320317
self.enter(BorrowedUnpark::new(&mk, id), |s| s.start_send(value))
@@ -325,11 +322,12 @@ impl<S: Sink> Spawn<S> {
325322
/// If the underlying operation returns `NotReady` then the `notify` value
326323
/// passed in will receive a notification when the operation is ready to be
327324
/// attempted again.
328-
pub fn poll_flush_notify<T>(&mut self,
329-
notify: &T,
325+
pub fn poll_flush_notify<N>(&mut self,
326+
notify: &N,
330327
id: usize)
331-
-> Poll<(), S::SinkError>
332-
where T: Clone + Into<NotifyHandle>,
328+
-> Poll<(), T::SinkError>
329+
where N: Clone + Into<NotifyHandle>,
330+
T: Sink,
333331
{
334332
let mk = || notify.clone().into();
335333
self.enter(BorrowedUnpark::new(&mk, id), |s| s.poll_complete())
@@ -340,18 +338,17 @@ impl<S: Sink> Spawn<S> {
340338
/// If the underlying operation returns `NotReady` then the `notify` value
341339
/// passed in will receive a notification when the operation is ready to be
342340
/// attempted again.
343-
pub fn close_notify<T>(&mut self,
344-
notify: &T,
341+
pub fn close_notify<N>(&mut self,
342+
notify: &N,
345343
id: usize)
346-
-> Poll<(), S::SinkError>
347-
where T: Clone + Into<NotifyHandle>,
344+
-> Poll<(), T::SinkError>
345+
where N: Clone + Into<NotifyHandle>,
346+
T: Sink,
348347
{
349348
let mk = || notify.clone().into();
350349
self.enter(BorrowedUnpark::new(&mk, id), |s| s.close())
351350
}
352-
}
353351

354-
impl<T> Spawn<T> {
355352
fn enter<F, R>(&mut self, unpark: BorrowedUnpark, f: F) -> R
356353
where F: FnOnce(&mut T) -> R
357354
{
@@ -366,10 +363,10 @@ impl<T> Spawn<T> {
366363
}
367364
}
368365

369-
impl<T: fmt::Debug> fmt::Debug for Spawn<T> {
366+
impl<T: fmt::Debug + ?Sized> fmt::Debug for Spawn<T> {
370367
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
371368
f.debug_struct("Spawn")
372-
.field("obj", &self.obj)
369+
.field("obj", &&self.obj)
373370
.finish()
374371
}
375372
}

tests/all.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,3 +359,17 @@ fn option() {
359359
assert_eq!(Ok(Some(())), Some(ok::<(), ()>(())).wait());
360360
assert_eq!(Ok(None), <Option<FutureResult<(), ()>> as Future>::wait(None));
361361
}
362+
363+
#[test]
364+
fn spawn_does_unsize() {
365+
#[derive(Clone, Copy)]
366+
struct EmptyNotify;
367+
impl executor::Notify for EmptyNotify {
368+
fn notify(&self, _: usize) { panic!("Cannot notify"); }
369+
}
370+
static EMPTY: &'static EmptyNotify = &EmptyNotify;
371+
372+
let spawn: executor::Spawn<FutureResult<(), ()>> = executor::spawn(future::ok(()));
373+
let mut spawn_box: Box<executor::Spawn<Future<Item = (), Error = ()>>> = Box::new(spawn);
374+
spawn_box.poll_future_notify(&EMPTY, 0).unwrap();
375+
}

0 commit comments

Comments
 (0)