use std::env;
use std::fs;
use std::path::{Path, PathBuf};
-use std::thunk::Thunk;
use getopts::{optopt, optflag, reqopt};
use common::Config;
use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Codegen};
pub fn make_test_closure(config: &Config, testfile: &Path) -> test::TestFn {
let config = (*config).clone();
let testfile = testfile.to_path_buf();
- test::DynTestFn(Thunk::new(move || {
+ test::DynTestFn(Box::new(move || {
runtest::run(config, &testfile)
}))
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {}
+
+/// `FnBox` is a version of the `FnOnce` intended for use with boxed
+/// closure objects. The idea is that where one would normally store a
+/// `Box<FnOnce()>` in a data structure, you should use
+/// `Box<FnBox()>`. The two traits behave essentially the same, except
+/// that a `FnBox` closure can only be called if it is boxed. (Note
+/// that `FnBox` may be deprecated in the future if `Box<FnOnce()>`
+/// closures become directly usable.)
+///
+/// ### Example
+///
+/// Here is a snippet of code which creates a hashmap full of boxed
+/// once closures and then removes them one by one, calling each
+/// closure as it is removed. Note that the type of the closures
+/// stored in the map is `Box<FnBox() -> i32>` and not `Box<FnOnce()
+/// -> i32>`.
+///
+/// ```
+/// #![feature(core)]
+///
+/// use std::boxed::FnBox;
+/// use std::collections::HashMap;
+///
+/// fn make_map() -> HashMap<i32, Box<FnBox() -> i32>> {
+/// let mut map: HashMap<i32, Box<FnBox() -> i32>> = HashMap::new();
+/// map.insert(1, Box::new(|| 22));
+/// map.insert(2, Box::new(|| 44));
+/// map
+/// }
+///
+/// fn main() {
+/// let mut map = make_map();
+/// for i in &[1, 2] {
+/// let f = map.remove(&i).unwrap();
+/// assert_eq!(f(), i * 22);
+/// }
+/// }
+/// ```
+#[rustc_paren_sugar]
+#[unstable(feature = "core", reason = "Newly introduced")]
+pub trait FnBox<A> {
+ type Output;
+
+ fn call_box(self: Box<Self>, args: A) -> Self::Output;
+}
+
+impl<A,F> FnBox<A> for F
+ where F: FnOnce<A>
+{
+ type Output = F::Output;
+
+ fn call_box(self: Box<F>, args: A) -> F::Output {
+ self.call_once(args)
+ }
+}
+
+impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+'a> {
+ type Output = R;
+
+ extern "rust-call" fn call_once(self, args: A) -> R {
+ self.call_box(args)
+ }
+}
+
+impl<'a,A,R> FnOnce<A> for Box<FnBox<A,Output=R>+Send+'a> {
+ type Output = R;
+
+ extern "rust-call" fn call_once(self, args: A) -> R {
+ self.call_box(args)
+ }
+}
use std::process::Command;
use std::str;
use std::sync::{Arc, Mutex};
-use std::thunk::Thunk;
use testing;
use rustc_lint;
ignore: should_ignore,
should_panic: testing::ShouldPanic::No, // compiler failures are test failures
},
- testfn: testing::DynTestFn(Thunk::new(move|| {
+ testfn: testing::DynTestFn(Box::new(move|| {
runtest(&test,
&cratename,
libs,
#[path = "num/f64.rs"] pub mod f64;
pub mod ascii;
+
pub mod thunk;
/* Common traits */
if queue as usize != 0 {
let queue: Box<Queue> = Box::from_raw(queue);
for to_run in *queue {
- to_run.invoke(());
+ to_run();
}
}
}
use prelude::v1::*;
use sys;
-use thunk::Thunk;
use usize;
// Reexport some of our utilities which are expected by other crates.
/// that the closure could not be registered, meaning that it is not scheduled
/// to be rune.
pub fn at_exit<F: FnOnce() + Send + 'static>(f: F) -> Result<(), ()> {
- if at_exit_imp::push(Thunk::new(f)) {Ok(())} else {Err(())}
+ if at_exit_imp::push(Box::new(f)) {Ok(())} else {Err(())}
}
/// One-time runtime cleanup.
use core::prelude::*;
use core::mem::replace;
+use boxed::Box;
use self::FutureState::*;
use sync::mpsc::{Receiver, channel};
use thunk::Thunk;
match replace(&mut self.state, Evaluating) {
Forced(_) | Evaluating => panic!("Logic error."),
Pending(f) => {
- self.state = Forced(f.invoke(()));
+ self.state = Forced(f());
self.get_ref()
}
}
* function. It is not spawned into another task.
*/
- Future {state: Pending(Thunk::new(f))}
+ Future {state: Pending(Box::new(f))}
}
}
unsafe {
stack::record_os_managed_stack_bounds(0, usize::MAX);
let _handler = stack_overflow::Handler::new();
- Box::from_raw(main as *mut Thunk).invoke(());
+ let main: Box<Thunk> = Box::from_raw(main as *mut Thunk);
+ main();
}
}
pub fn spawn<F>(self, f: F) -> io::Result<JoinHandle> where
F: FnOnce(), F: Send + 'static
{
- self.spawn_inner(Thunk::new(f)).map(|i| JoinHandle(i))
+ self.spawn_inner(Box::new(f)).map(|i| JoinHandle(i))
}
/// Spawn a new child thread that must be joined within a given
pub fn scoped<'a, T, F>(self, f: F) -> io::Result<JoinGuard<'a, T>> where
T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
{
- self.spawn_inner(Thunk::new(f)).map(|inner| {
+ self.spawn_inner(Box::new(f)).map(|inner| {
JoinGuard { inner: inner, _marker: PhantomData }
})
}
thread_info::set(imp::guard::current(), their_thread);
}
- let mut output = None;
+ let mut output: Option<T> = None;
let try_result = {
let ptr = &mut output;
// 'unwinding' flag in the thread itself. For these reasons,
// this unsafety should be ok.
unsafe {
- unwind::try(move || *ptr = Some(f.invoke(())))
+ unwind::try(move || {
+ let f: Thunk<(), T> = f;
+ let v: T = f();
+ *ptr = Some(v)
+ })
}
};
unsafe {
};
Ok(JoinInner {
- native: try!(unsafe { imp::create(stack_size, Thunk::new(main)) }),
+ native: try!(unsafe { imp::create(stack_size, Box::new(main)) }),
thread: my_thread,
packet: my_packet,
joined: false,
let x: Box<_> = box 1;
let x_in_parent = (&*x) as *const i32 as usize;
- spawnfn(Thunk::new(move|| {
+ spawnfn(Box::new(move|| {
let x_in_child = (&*x) as *const i32 as usize;
tx.send(x_in_child).unwrap();
}));
#[test]
fn test_avoid_copying_the_body_spawn() {
avoid_copying_the_body(|v| {
- thread::spawn(move || v.invoke(()));
+ thread::spawn(move || v());
});
}
fn test_avoid_copying_the_body_thread_spawn() {
avoid_copying_the_body(|f| {
thread::spawn(move|| {
- f.invoke(());
+ f();
});
})
}
fn test_avoid_copying_the_body_join() {
avoid_copying_the_body(|f| {
let _ = thread::spawn(move|| {
- f.invoke(())
+ f()
}).join();
})
}
// valgrind-friendly. try this at home, instead..!)
const GENERATIONS: u32 = 16;
fn child_no(x: u32) -> Thunk<'static> {
- return Thunk::new(move|| {
+ return Box::new(move|| {
if x < GENERATIONS {
- thread::spawn(move|| child_no(x+1).invoke(()));
+ thread::spawn(move|| child_no(x+1)());
}
});
}
- thread::spawn(|| child_no(0).invoke(()));
+ thread::spawn(|| child_no(0)());
}
#[test]
#![allow(missing_docs)]
#![unstable(feature = "std_misc")]
-use alloc::boxed::Box;
+use alloc::boxed::{Box, FnBox};
use core::marker::Send;
-use core::ops::FnOnce;
-pub struct Thunk<'a, A=(),R=()> {
- invoke: Box<Invoke<A,R>+Send + 'a>,
-}
+pub type Thunk<'a, A=(), R=()> =
+ Box<FnBox<A,Output=R> + Send + 'a>;
-impl<'a, R> Thunk<'a,(),R> {
- pub fn new<F>(func: F) -> Thunk<'a,(),R>
- where F : FnOnce() -> R, F : Send + 'a
- {
- Thunk::with_arg(move|()| func())
- }
-}
-
-impl<'a,A,R> Thunk<'a,A,R> {
- pub fn with_arg<F>(func: F) -> Thunk<'a,A,R>
- where F : FnOnce(A) -> R, F : Send + 'a
- {
- Thunk {
- invoke: Box::<F>::new(func)
- }
- }
-
- pub fn invoke(self, arg: A) -> R {
- self.invoke.invoke(arg)
- }
-}
-
-pub trait Invoke<A=(),R=()> {
- fn invoke(self: Box<Self>, arg: A) -> R;
-}
-
-impl<A,R,F> Invoke<A,R> for F
- where F : FnOnce(A) -> R
-{
- fn invoke(self: Box<F>, arg: A) -> R {
- let f = *self;
- f(arg)
- }
-}
use stats::Stats;
use getopts::{OptGroup, optflag, optopt};
use serialize::Encodable;
+use std::boxed::FnBox;
use term::Terminal;
use term::color::{Color, RED, YELLOW, GREEN, CYAN};
use std::sync::mpsc::{channel, Sender};
use std::sync::{Arc, Mutex};
use std::thread;
-use std::thunk::{Thunk, Invoke};
+use std::thunk::Thunk;
use std::time::Duration;
// to be used by rustc to compile tests in libtest
StaticBenchFn(fn(&mut Bencher)),
StaticMetricFn(fn(&mut MetricMap)),
DynTestFn(Thunk<'static>),
- DynMetricFn(Box<for<'a> Invoke<&'a mut MetricMap>+'static>),
+ DynMetricFn(Box<FnBox(&mut MetricMap)+Send>),
DynBenchFn(Box<TDynBenchFn+'static>)
}
io::set_print(box Sink(data2.clone()));
io::set_panic(box Sink(data2));
}
- testfn.invoke(())
+ testfn()
}).unwrap();
let test_result = calc_result(&desc, result_guard.join());
let stdout = data.lock().unwrap().to_vec();
}
DynMetricFn(f) => {
let mut mm = MetricMap::new();
- f.invoke(&mut mm);
+ f.call_box((&mut mm,));
monitor_ch.send((desc, TrMetrics(mm), Vec::new())).unwrap();
return;
}
}
DynTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, f),
StaticTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture,
- Thunk::new(move|| f()))
+ Box::new(move|| f()))
}
}
ignore: true,
should_panic: ShouldPanic::No,
},
- testfn: DynTestFn(Thunk::new(move|| f())),
+ testfn: DynTestFn(Box::new(move|| f())),
};
let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, tx);
ignore: true,
should_panic: ShouldPanic::No,
},
- testfn: DynTestFn(Thunk::new(move|| f())),
+ testfn: DynTestFn(Box::new(move|| f())),
};
let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, tx);
ignore: false,
should_panic: ShouldPanic::Yes(None)
},
- testfn: DynTestFn(Thunk::new(move|| f())),
+ testfn: DynTestFn(Box::new(move|| f())),
};
let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, tx);
ignore: false,
should_panic: ShouldPanic::Yes(Some("error message"))
},
- testfn: DynTestFn(Thunk::new(move|| f())),
+ testfn: DynTestFn(Box::new(move|| f())),
};
let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, tx);
ignore: false,
should_panic: ShouldPanic::Yes(Some("foobar"))
},
- testfn: DynTestFn(Thunk::new(move|| f())),
+ testfn: DynTestFn(Box::new(move|| f())),
};
let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, tx);
ignore: false,
should_panic: ShouldPanic::Yes(None)
},
- testfn: DynTestFn(Thunk::new(move|| f())),
+ testfn: DynTestFn(Box::new(move|| f())),
};
let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, tx);
ignore: true,
should_panic: ShouldPanic::No,
},
- testfn: DynTestFn(Thunk::new(move|| {})),
+ testfn: DynTestFn(Box::new(move|| {})),
},
TestDescAndFn {
desc: TestDesc {
ignore: false,
should_panic: ShouldPanic::No,
},
- testfn: DynTestFn(Thunk::new(move|| {})),
+ testfn: DynTestFn(Box::new(move|| {})),
});
let filtered = filter_tests(&opts, tests);
ignore: false,
should_panic: ShouldPanic::No,
},
- testfn: DynTestFn(Thunk::new(testfn)),
+ testfn: DynTestFn(Box::new(testfn)),
};
tests.push(test);
}
let a = slot.take();
let _a = match a {
// `{let .. a(); }` would break
- Some(a) => { let _a = a.invoke(()); },
+ Some(a) => { let _a = a(); },
None => (),
};
}
pub fn main() {
let mut x = 1;
- let _thunk = Thunk::new(move|| { x = 2; });
+ let _thunk = Box::new(move|| { x = 2; });
}
use std::thunk::Thunk;
-fn action(cb: Thunk<usize, usize>) -> usize {
- cb.invoke(1)
+fn action(cb: Thunk<(usize,), usize>) -> usize {
+ cb(1)
}
pub fn main() {
- println!("num: {}", action(Thunk::with_arg(move |u| u)));
+ println!("num: {}", action(Box::new(move |u| u)));
}
pub trait Promisable: Send + Sync {}
impl<T: Send + Sync> Promisable for T {}
-pub fn propagate<'a, T, E, F, G>(action: F) -> Thunk<'a,Result<T, E>, Result<T, E>>
+pub fn propagate<'a, T, E, F, G>(action: F) -> Thunk<'a, (Result<T, E>,), Result<T, E>>
where
T: Promisable + Clone + 'a,
E: Promisable + Clone + 'a,
F: FnOnce(&T) -> Result<T, E> + Send + 'a,
G: FnOnce(Result<T, E>) -> Result<T, E> + 'a {
- Thunk::with_arg(move |result: Result<T, E>| {
+ Box::new(move |result: Result<T, E>| {
match result {
Ok(ref t) => action(t),
Err(ref e) => Err(e.clone()),
static generations: usize = 1024+256+128+49;
fn spawn(f: Thunk<'static>) {
- Builder::new().stack_size(32 * 1024).spawn(move|| f.invoke(()));
+ Builder::new().stack_size(32 * 1024).spawn(move|| f());
}
fn child_no(x: usize) -> Thunk<'static> {
- Thunk::new(move|| {
+ Box::new(move|| {
if x < generations {
spawn(child_no(x+1));
}
use std::thread;
use std::sync::mpsc::Sender;
-use std::thunk::Invoke;
type RingBuffer = Vec<f64> ;
type SamplesFn = Box<FnMut(&RingBuffer) + Send>;