From 1a6d920e3df3d48168b22879a194538ec10c951a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 13 Dec 2013 18:28:18 -0800 Subject: [PATCH] green: Allow specifying an IoFactory for pools This allows creation of different sched pools with different io factories. Namely, this will be used to test the basic I/O loop in the green crate. This can also be used to override the global default. --- src/libgreen/lib.rs | 22 ++++++++++++++++------ src/librustuv/homing.rs | 10 ++++++++-- src/librustuv/uvio.rs | 2 +- src/libstd/rt/crate_map.rs | 2 +- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/libgreen/lib.rs b/src/libgreen/lib.rs index 9a3f27f7dbc..82d5bc83e2e 100644 --- a/src/libgreen/lib.rs +++ b/src/libgreen/lib.rs @@ -115,6 +115,9 @@ pub fn run(main: proc()) -> int { pub struct PoolConfig { /// The number of schedulers (OS threads) to spawn into this M:N pool. 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 ~rtio::EventLoop>, } impl PoolConfig { @@ -123,6 +126,7 @@ impl PoolConfig { pub fn new() -> PoolConfig { PoolConfig { threads: rt::default_sched_threads(), + event_loop_factory: None, } } } @@ -138,6 +142,7 @@ pub struct SchedPool { priv stack_pool: StackPool, priv deque_pool: deque::BufferPool<~task::GreenTask>, priv sleepers: SleeperList, + priv factory: fn() -> ~rtio::EventLoop, } impl SchedPool { @@ -148,7 +153,11 @@ impl SchedPool { pub fn new(config: PoolConfig) -> SchedPool { static mut POOL_ID: AtomicUint = INIT_ATOMIC_UINT; - let PoolConfig { threads: nscheds } = config; + let PoolConfig { + 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 @@ -161,6 +170,7 @@ pub fn new(config: PoolConfig) -> SchedPool { stack_pool: StackPool::new(), deque_pool: deque::BufferPool::new(), next_friend: 0, + factory: factory, }; // Create a work queue for each scheduler, ntimes. Create an extra @@ -176,7 +186,7 @@ pub fn new(config: PoolConfig) -> SchedPool { rtdebug!("inserting a regular scheduler"); let mut sched = ~Scheduler::new(pool.id, - new_event_loop(), + (pool.factory)(), worker, pool.stealers.clone(), pool.sleepers.clone()); @@ -232,7 +242,7 @@ pub fn spawn_sched(&mut self) -> SchedHandle { // other schedulers as well as having a stealer handle to all other // schedulers. let mut sched = ~Scheduler::new(self.id, - new_event_loop(), + (self.factory)(), worker, self.stealers.clone(), self.sleepers.clone()); @@ -270,13 +280,13 @@ fn drop(&mut self) { } } -fn new_event_loop() -> ~rtio::EventLoop { +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() + Some(factory) => return factory } } } @@ -284,5 +294,5 @@ fn new_event_loop() -> ~rtio::EventLoop { // 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(); + return basic::event_loop; } diff --git a/src/librustuv/homing.rs b/src/librustuv/homing.rs index 1f9e3831e20..1ee64398ca3 100644 --- a/src/librustuv/homing.rs +++ b/src/librustuv/homing.rs @@ -161,7 +161,10 @@ mod test { #[test] fn test_homing_closes_correctly() { let (port, chan) = Chan::new(); - let mut pool = SchedPool::new(PoolConfig { threads: 1 }); + let mut pool = SchedPool::new(PoolConfig { + threads: 1, + event_loop_factory: None, + }); do pool.spawn(TaskOpts::new()) { let listener = UdpWatcher::bind(local_loop(), next_test_ip4()); @@ -179,7 +182,10 @@ fn test_homing_closes_correctly() { #[test] fn test_homing_read() { let (port, chan) = Chan::new(); - let mut pool = SchedPool::new(PoolConfig { threads: 1 }); + let mut pool = SchedPool::new(PoolConfig { + threads: 1, + event_loop_factory: None, + }); do pool.spawn(TaskOpts::new()) { let addr1 = next_test_ip4(); diff --git a/src/librustuv/uvio.rs b/src/librustuv/uvio.rs index 57bb0cfdc7a..210ee2fc451 100644 --- a/src/librustuv/uvio.rs +++ b/src/librustuv/uvio.rs @@ -96,7 +96,7 @@ fn io<'a>(&'a mut self) -> Option<&'a mut rtio::IoFactory> { #[cfg(not(test))] #[lang = "event_loop_factory"] -pub extern "C" fn new_loop() -> ~rtio::EventLoop { +pub fn new_loop() -> ~rtio::EventLoop { ~UvEventLoop::new() as ~rtio::EventLoop } diff --git a/src/libstd/rt/crate_map.rs b/src/libstd/rt/crate_map.rs index 22fc3f0ab56..d9b40cfbb6e 100644 --- a/src/libstd/rt/crate_map.rs +++ b/src/libstd/rt/crate_map.rs @@ -30,7 +30,7 @@ pub struct CrateMap<'a> { version: i32, entries: &'a [ModEntry<'a>], children: &'a [&'a CrateMap<'a>], - event_loop_factory: Option ~EventLoop>, + event_loop_factory: Option ~EventLoop>, } #[cfg(not(windows))]