green: Remove the dependence on the crate map

This is the final nail in the coffin for the crate map. The `start` function for
libgreen now has a new added parameter which is the event loop factory instead
of inferring it from the crate map. The two current valid values for this
parameter are `green::basic::event_loop` and `rustuv::event_loop`.
This commit is contained in:
Alex Crichton 2014-03-24 10:40:36 -07:00
parent f8f60d80bf
commit b19261a749
15 changed files with 84 additions and 59 deletions

View File

@ -44,7 +44,9 @@ pub mod common;
pub mod errors;
#[start]
fn start(argc: int, argv: **u8) -> int { green::start(argc, argv, main) }
fn start(argc: int, argv: **u8) -> int {
green::start(argc, argv, rustuv::event_loop, main)
}
pub fn main() {
let args = os::args();

View File

@ -237,7 +237,7 @@ mod test {
fn pool() -> SchedPool {
SchedPool::new(PoolConfig {
threads: 1,
event_loop_factory: Some(basic::event_loop),
event_loop_factory: basic::event_loop,
})
}
@ -267,7 +267,7 @@ mod test {
fn multi_thread() {
let mut pool = SchedPool::new(PoolConfig {
threads: 2,
event_loop_factory: Some(basic::event_loop),
event_loop_factory: basic::event_loop,
});
for _ in range(0, 20) {

View File

@ -116,13 +116,34 @@
//! extern crate green;
//!
//! #[start]
//! fn start(argc: int, argv: **u8) -> int { green::start(argc, argv, main) }
//! fn start(argc: int, argv: **u8) -> int {
//! green::start(argc, argv, green::basic::event_loop, main)
//! }
//!
//! fn main() {
//! // this code is running in a pool of schedulers
//! }
//! ```
//!
//! > **Note**: This `main` funciton in this example does *not* have I/O
//! > support. The basic event loop does not provide any support
//!
//! # Starting with I/O support in libgreen
//!
//! ```rust
//! extern crate green;
//! extern crate rustuv;
//!
//! #[start]
//! fn start(argc: int, argv: **u8) -> int {
//! green::start(argc, argv, rustuv::event_loop, main)
//! }
//!
//! fn main() {
//! // this code is running in a pool of schedulers all powered by libuv
//! }
//! ```
//!
//! # Using a scheduler pool
//!
//! ```rust
@ -176,11 +197,11 @@
#[allow(visible_private_types)];
#[cfg(test)] #[phase(syntax, link)] extern crate log;
#[cfg(test)] extern crate rustuv;
extern crate rand;
use std::mem::replace;
use std::os;
use std::rt::crate_map;
use std::rt::rtio;
use std::rt::thread::Thread;
use std::rt;
@ -207,16 +228,6 @@ pub mod sleeper_list;
pub mod stack;
pub mod task;
#[lang = "start"]
#[cfg(not(test), stage0)]
pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int {
use std::cast;
start(argc, argv, proc() {
let main: extern "Rust" fn() = unsafe { cast::transmute(main) };
main();
})
}
/// Set up a default runtime configuration, given compiler-supplied arguments.
///
/// This function will block until the entire pool of M:N schedulers have
@ -235,12 +246,14 @@ pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int {
///
/// The return value is used as the process return code. 0 on success, 101 on
/// error.
pub fn start(argc: int, argv: **u8, main: proc()) -> int {
pub fn start(argc: int, argv: **u8,
event_loop_factory: fn() -> ~rtio::EventLoop,
main: proc()) -> int {
rt::init(argc, argv);
let mut main = Some(main);
let mut ret = None;
simple::task().run(|| {
ret = Some(run(main.take_unwrap()));
ret = Some(run(event_loop_factory, main.take_unwrap()));
});
// unsafe is ok b/c we're sure that the runtime is gone
unsafe { rt::cleanup() }
@ -255,10 +268,12 @@ pub fn start(argc: int, argv: **u8, main: proc()) -> int {
///
/// This function will not return until all schedulers in the associated pool
/// have returned.
pub fn run(main: proc()) -> int {
pub fn run(event_loop_factory: fn() -> ~rtio::EventLoop, main: proc()) -> int {
// Create a scheduler pool and spawn the main task into this pool. We will
// get notified over a channel when the main task exits.
let mut pool = SchedPool::new(PoolConfig::new());
let mut cfg = PoolConfig::new();
cfg.event_loop_factory = event_loop_factory;
let mut pool = SchedPool::new(cfg);
let (tx, rx) = channel();
let mut opts = TaskOpts::new();
opts.notify_chan = Some(tx);
@ -283,7 +298,7 @@ pub struct PoolConfig {
threads: uint,
/// A factory function used to create new event loops. If this is not
/// specified then the default event loop factory is used.
event_loop_factory: Option<fn() -> ~rtio::EventLoop>,
event_loop_factory: fn() -> ~rtio::EventLoop,
}
impl PoolConfig {
@ -292,7 +307,7 @@ impl PoolConfig {
pub fn new() -> PoolConfig {
PoolConfig {
threads: rt::default_sched_threads(),
event_loop_factory: None,
event_loop_factory: basic::event_loop,
}
}
}
@ -334,7 +349,6 @@ impl SchedPool {
threads: nscheds,
event_loop_factory: factory
} = config;
let factory = factory.unwrap_or(default_event_loop_factory());
assert!(nscheds > 0);
// The pool of schedulers that will be returned from this function
@ -503,20 +517,3 @@ impl Drop for SchedPool {
}
}
}
fn default_event_loop_factory() -> fn() -> ~rtio::EventLoop {
match crate_map::get_crate_map() {
None => {}
Some(map) => {
match map.event_loop_factory {
None => {}
Some(factory) => return factory
}
}
}
// If the crate map didn't specify a factory to create an event loop, then
// instead just use a basic event loop missing all I/O services to at least
// get the scheduler running.
return basic::event_loop;
}

View File

@ -1003,6 +1003,8 @@ fn new_sched_rng() -> XorShiftRng {
#[cfg(test)]
mod test {
use rustuv;
use std::comm;
use std::task::TaskOpts;
use std::rt::Runtime;
@ -1017,7 +1019,7 @@ mod test {
fn pool() -> SchedPool {
SchedPool::new(PoolConfig {
threads: 1,
event_loop_factory: Some(basic::event_loop),
event_loop_factory: basic::event_loop,
})
}
@ -1262,7 +1264,7 @@ mod test {
let mut pool = SchedPool::new(PoolConfig {
threads: 2,
event_loop_factory: None,
event_loop_factory: rustuv::event_loop,
});
// This is a regression test that when there are no schedulable tasks in
@ -1413,7 +1415,7 @@ mod test {
fn dont_starve_1() {
let mut pool = SchedPool::new(PoolConfig {
threads: 2, // this must be > 1
event_loop_factory: Some(basic::event_loop),
event_loop_factory: basic::event_loop,
});
pool.spawn(TaskOpts::new(), proc() {
let (tx, rx) = channel();

View File

@ -494,7 +494,7 @@ mod tests {
fn spawn_opts(opts: TaskOpts, f: proc()) {
let mut pool = SchedPool::new(PoolConfig {
threads: 1,
event_loop_factory: None,
event_loop_factory: ::rustuv::event_loop,
});
pool.spawn(opts, f);
pool.shutdown();

View File

@ -69,7 +69,7 @@ static OS_DEFAULT_STACK_ESTIMATE: uint = 1 << 20;
static OS_DEFAULT_STACK_ESTIMATE: uint = 2 * (1 << 20);
#[lang = "start"]
#[cfg(not(test), not(stage0))]
#[cfg(not(test))]
pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int {
use std::cast;
start(argc, argv, proc() {

View File

@ -167,7 +167,7 @@ mod test {
let (tx, rx) = channel();
let mut pool = SchedPool::new(PoolConfig {
threads: 1,
event_loop_factory: None,
event_loop_factory: ::event_loop,
});
pool.spawn(TaskOpts::new(), proc() {
@ -188,7 +188,7 @@ mod test {
let (tx, rx) = channel();
let mut pool = SchedPool::new(PoolConfig {
threads: 1,
event_loop_factory: None,
event_loop_factory: ::event_loop,
});
pool.spawn(TaskOpts::new(), proc() {

View File

@ -54,6 +54,7 @@ use std::libc::{c_int, c_void};
use std::ptr::null;
use std::ptr;
use std::rt::local::Local;
use std::rt::rtio;
use std::rt::task::{BlockedTask, Task};
use std::str::raw::from_c_str;
use std::str;
@ -76,7 +77,7 @@ pub use self::tty::TtyWatcher;
// '__test' module.
#[cfg(test)] #[start]
fn start(argc: int, argv: **u8) -> int {
green::start(argc, argv, __test::main)
green::start(argc, argv, event_loop, __test::main)
}
mod macros;
@ -104,6 +105,31 @@ pub mod tty;
pub mod signal;
pub mod stream;
/// Creates a new event loop which is powered by libuv
///
/// This function is used in tandem with libgreen's `PoolConfig` type as a value
/// for the `event_loop_factory` field. Using this function as the event loop
/// factory will power programs with libuv and enable green threading.
///
/// # Example
///
/// ```
/// extern crate rustuv;
/// extern crate green;
///
/// #[start]
/// fn start(argc: int, argv: **u8) -> int {
/// green::start(argc, argv, rustuv::event_loop, main)
/// }
///
/// fn main() {
/// // this code is running inside of a green task powered by libuv
/// }
/// ```
pub fn event_loop() -> ~rtio::EventLoop {
~uvio::UvEventLoop::new() as ~rtio::EventLoop
}
/// A type that wraps a uv handle
pub trait UvHandle<T> {
fn uv_handle(&self) -> *T;

View File

@ -105,12 +105,6 @@ impl rtio::EventLoop for UvEventLoop {
}
}
#[cfg(not(test))]
#[lang = "event_loop_factory"]
pub fn new_loop() -> ~rtio::EventLoop {
~UvEventLoop::new() as ~rtio::EventLoop
}
#[test]
fn test_callback_run_once() {
use std::rt::rtio::EventLoop;

View File

@ -84,7 +84,7 @@
// '__test' module.
#[cfg(test)] #[start]
fn start(argc: int, argv: **u8) -> int {
green::start(argc, argv, __test::main)
green::start(argc, argv, rustuv::event_loop, __test::main)
}
pub mod macros;

View File

@ -16,7 +16,7 @@ extern crate green;
#[no_mangle] // this needs to get called from C
pub extern "C" fn foo(argc: int, argv: **u8) -> int {
green::start(argc, argv, proc() {
green::start(argc, argv, rustuv::event_loop, proc() {
spawn(proc() {
println!("hello");
});

View File

@ -49,7 +49,7 @@ macro_rules! iotest (
#[cfg(test)] #[start]
fn start(argc: int, argv: **u8) -> int {
green::start(argc, argv, __test::main)
green::start(argc, argv, rustuv::event_loop, __test::main)
}
iotest!(fn test_destroy_once() {

View File

@ -15,7 +15,9 @@ extern crate green;
extern crate rustuv;
#[start]
fn start(argc: int, argv: **u8) -> int { green::start(argc, argv, main) }
fn start(argc: int, argv: **u8) -> int {
green::start(argc, argv, rustuv::event_loop, main)
}
fn main() {
native::task::spawn(proc() customtask());

View File

@ -18,7 +18,7 @@ static mut DROP_T: int = 0i;
#[start]
fn start(argc: int, argv: **u8) -> int {
let ret = green::start(argc, argv, main);
let ret = green::start(argc, argv, green::basic::event_loop, main);
unsafe {
assert_eq!(2, DROP);
assert_eq!(1, DROP_S);

View File

@ -28,7 +28,9 @@ use std::io::process;
use std::io::signal::{Listener, Interrupt};
#[start]
fn start(argc: int, argv: **u8) -> int { green::start(argc, argv, main) }
fn start(argc: int, argv: **u8) -> int {
green::start(argc, argv, rustuv::event_loop, main)
}
fn main() {
unsafe { libc::setsid(); }