1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 #[allow(missing_doc)];
13 /// A task pool abstraction. Useful for achieving predictable CPU
17 use std::comm::{Chan, GenericChan, GenericPort};
19 use std::task::SchedMode;
23 #[cfg(test)] use std::task::SingleThreaded;
30 pub struct TaskPool<T> {
31 channels: ~[Chan<Msg<T>>],
36 impl<T> Drop for TaskPool<T> {
38 for channel in self.channels.iter() {
45 /// Spawns a new task pool with `n_tasks` tasks. If the `sched_mode`
46 /// is None, the tasks run on this scheduler; otherwise, they run on a
47 /// new scheduler with the given mode. The provided `init_fn_factory`
48 /// returns a function which, given the index of the task, should return
49 /// local data to be kept around in that task.
50 pub fn new(n_tasks: uint,
51 opt_sched_mode: Option<SchedMode>,
52 init_fn_factory: ~fn() -> ~fn(uint) -> T)
54 assert!(n_tasks >= 1);
56 let channels = do vec::from_fn(n_tasks) |i| {
57 let (port, chan) = comm::stream::<Msg<T>>();
58 let init_fn = init_fn_factory();
60 let task_body: ~fn() = || {
61 let local_data = init_fn(i);
64 Execute(f) => f(&local_data),
71 match opt_sched_mode {
73 // Run on this scheduler.
74 task::spawn(task_body);
77 let mut task = task::task();
78 task.sched_mode(sched_mode);
79 task.spawn(task_body);
86 return TaskPool { channels: channels, next_index: 0 };
89 /// Executes the function `f` on a task in the pool. The function
90 /// receives a reference to the local data returned by the `init_fn`.
91 pub fn execute(&mut self, f: ~fn(&T)) {
92 self.channels[self.next_index].send(Execute(f));
94 if self.next_index == self.channels.len() { self.next_index = 0; }
100 let f: ~fn() -> ~fn(uint) -> uint = || {
101 let g: ~fn(uint) -> uint = |i| i;
104 let mut pool = TaskPool::new(4, Some(SingleThreaded), f);
106 pool.execute(|i| printfln!("Hello from thread %u!", *i));