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; pub mod errors;
#[start] #[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() { pub fn main() {
let args = os::args(); let args = os::args();

View File

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

View File

@@ -116,13 +116,34 @@
//! extern crate green; //! extern crate green;
//! //!
//! #[start] //! #[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() { //! fn main() {
//! // this code is running in a pool of schedulers //! // 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 //! # Using a scheduler pool
//! //!
//! ```rust //! ```rust
@@ -176,11 +197,11 @@
#[allow(visible_private_types)]; #[allow(visible_private_types)];
#[cfg(test)] #[phase(syntax, link)] extern crate log; #[cfg(test)] #[phase(syntax, link)] extern crate log;
#[cfg(test)] extern crate rustuv;
extern crate rand; extern crate rand;
use std::mem::replace; use std::mem::replace;
use std::os; use std::os;
use std::rt::crate_map;
use std::rt::rtio; use std::rt::rtio;
use std::rt::thread::Thread; use std::rt::thread::Thread;
use std::rt; use std::rt;
@@ -207,16 +228,6 @@ pub mod sleeper_list;
pub mod stack; pub mod stack;
pub mod task; 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. /// Set up a default runtime configuration, given compiler-supplied arguments.
/// ///
/// This function will block until the entire pool of M:N schedulers have /// 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 /// The return value is used as the process return code. 0 on success, 101 on
/// error. /// 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); rt::init(argc, argv);
let mut main = Some(main); let mut main = Some(main);
let mut ret = None; let mut ret = None;
simple::task().run(|| { 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 is ok b/c we're sure that the runtime is gone
unsafe { rt::cleanup() } 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 /// This function will not return until all schedulers in the associated pool
/// have returned. /// 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 // Create a scheduler pool and spawn the main task into this pool. We will
// get notified over a channel when the main task exits. // 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 (tx, rx) = channel();
let mut opts = TaskOpts::new(); let mut opts = TaskOpts::new();
opts.notify_chan = Some(tx); opts.notify_chan = Some(tx);
@@ -283,7 +298,7 @@ pub struct PoolConfig {
threads: uint, threads: uint,
/// A factory function used to create new event loops. If this is not /// A factory function used to create new event loops. If this is not
/// specified then the default event loop factory is used. /// specified then the default event loop factory is used.
event_loop_factory: Option<fn() -> ~rtio::EventLoop>, event_loop_factory: fn() -> ~rtio::EventLoop,
} }
impl PoolConfig { impl PoolConfig {
@@ -292,7 +307,7 @@ impl PoolConfig {
pub fn new() -> PoolConfig { pub fn new() -> PoolConfig {
PoolConfig { PoolConfig {
threads: rt::default_sched_threads(), threads: rt::default_sched_threads(),
event_loop_factory: None, event_loop_factory: basic::event_loop,
} }
} }
} }
@@ -334,7 +349,6 @@ impl SchedPool {
threads: nscheds, threads: nscheds,
event_loop_factory: factory event_loop_factory: factory
} = config; } = config;
let factory = factory.unwrap_or(default_event_loop_factory());
assert!(nscheds > 0); assert!(nscheds > 0);
// The pool of schedulers that will be returned from this function // 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)] #[cfg(test)]
mod test { mod test {
use rustuv;
use std::comm; use std::comm;
use std::task::TaskOpts; use std::task::TaskOpts;
use std::rt::Runtime; use std::rt::Runtime;
@@ -1017,7 +1019,7 @@ mod test {
fn pool() -> SchedPool { fn pool() -> SchedPool {
SchedPool::new(PoolConfig { SchedPool::new(PoolConfig {
threads: 1, 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 { let mut pool = SchedPool::new(PoolConfig {
threads: 2, 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 // This is a regression test that when there are no schedulable tasks in
@@ -1413,7 +1415,7 @@ mod test {
fn dont_starve_1() { fn dont_starve_1() {
let mut pool = SchedPool::new(PoolConfig { let mut pool = SchedPool::new(PoolConfig {
threads: 2, // this must be > 1 threads: 2, // this must be > 1
event_loop_factory: Some(basic::event_loop), event_loop_factory: basic::event_loop,
}); });
pool.spawn(TaskOpts::new(), proc() { pool.spawn(TaskOpts::new(), proc() {
let (tx, rx) = channel(); let (tx, rx) = channel();

View File

@@ -494,7 +494,7 @@ mod tests {
fn spawn_opts(opts: TaskOpts, f: proc()) { fn spawn_opts(opts: TaskOpts, f: proc()) {
let mut pool = SchedPool::new(PoolConfig { let mut pool = SchedPool::new(PoolConfig {
threads: 1, threads: 1,
event_loop_factory: None, event_loop_factory: ::rustuv::event_loop,
}); });
pool.spawn(opts, f); pool.spawn(opts, f);
pool.shutdown(); 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); static OS_DEFAULT_STACK_ESTIMATE: uint = 2 * (1 << 20);
#[lang = "start"] #[lang = "start"]
#[cfg(not(test), not(stage0))] #[cfg(not(test))]
pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int { pub fn lang_start(main: *u8, argc: int, argv: **u8) -> int {
use std::cast; use std::cast;
start(argc, argv, proc() { start(argc, argv, proc() {

View File

@@ -167,7 +167,7 @@ mod test {
let (tx, rx) = channel(); let (tx, rx) = channel();
let mut pool = SchedPool::new(PoolConfig { let mut pool = SchedPool::new(PoolConfig {
threads: 1, threads: 1,
event_loop_factory: None, event_loop_factory: ::event_loop,
}); });
pool.spawn(TaskOpts::new(), proc() { pool.spawn(TaskOpts::new(), proc() {
@@ -188,7 +188,7 @@ mod test {
let (tx, rx) = channel(); let (tx, rx) = channel();
let mut pool = SchedPool::new(PoolConfig { let mut pool = SchedPool::new(PoolConfig {
threads: 1, threads: 1,
event_loop_factory: None, event_loop_factory: ::event_loop,
}); });
pool.spawn(TaskOpts::new(), proc() { 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::null;
use std::ptr; use std::ptr;
use std::rt::local::Local; use std::rt::local::Local;
use std::rt::rtio;
use std::rt::task::{BlockedTask, Task}; use std::rt::task::{BlockedTask, Task};
use std::str::raw::from_c_str; use std::str::raw::from_c_str;
use std::str; use std::str;
@@ -76,7 +77,7 @@ pub use self::tty::TtyWatcher;
// '__test' module. // '__test' module.
#[cfg(test)] #[start] #[cfg(test)] #[start]
fn start(argc: int, argv: **u8) -> int { fn start(argc: int, argv: **u8) -> int {
green::start(argc, argv, __test::main) green::start(argc, argv, event_loop, __test::main)
} }
mod macros; mod macros;
@@ -104,6 +105,31 @@ pub mod tty;
pub mod signal; pub mod signal;
pub mod stream; 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 /// A type that wraps a uv handle
pub trait UvHandle<T> { pub trait UvHandle<T> {
fn uv_handle(&self) -> *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] #[test]
fn test_callback_run_once() { fn test_callback_run_once() {
use std::rt::rtio::EventLoop; use std::rt::rtio::EventLoop;

View File

@@ -84,7 +84,7 @@
// '__test' module. // '__test' module.
#[cfg(test)] #[start] #[cfg(test)] #[start]
fn start(argc: int, argv: **u8) -> int { 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; pub mod macros;

View File

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

View File

@@ -49,7 +49,7 @@ macro_rules! iotest (
#[cfg(test)] #[start] #[cfg(test)] #[start]
fn start(argc: int, argv: **u8) -> int { 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() { iotest!(fn test_destroy_once() {

View File

@@ -15,7 +15,9 @@ extern crate green;
extern crate rustuv; extern crate rustuv;
#[start] #[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() { fn main() {
native::task::spawn(proc() customtask()); native::task::spawn(proc() customtask());

View File

@@ -18,7 +18,7 @@ static mut DROP_T: int = 0i;
#[start] #[start]
fn start(argc: int, argv: **u8) -> int { 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 { unsafe {
assert_eq!(2, DROP); assert_eq!(2, DROP);
assert_eq!(1, DROP_S); assert_eq!(1, DROP_S);

View File

@@ -28,7 +28,9 @@ use std::io::process;
use std::io::signal::{Listener, Interrupt}; use std::io::signal::{Listener, Interrupt};
#[start] #[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() { fn main() {
unsafe { libc::setsid(); } unsafe { libc::setsid(); }