├── .travis.yml ├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md ├── examples └── prime_numbers.rs ├── tests └── lib.rs └── src └── lib.rs /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - linux 3 | language: rust -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.lock 3 | *.swp 4 | tags* 5 | build/ 6 | build-tests/ 7 | target/ 8 | *~ 9 | /.idea 10 | tests/tmp* 11 | src/tmp* 12 | *.sublime-* 13 | .project -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "asynchronous" 3 | version = "0.4.5" 4 | authors = ["bcndanos "] 5 | description = "Promises Q style , async and event loops" 6 | repository = "https://github.com/bcndanos/asynchronous" 7 | documentation = "http://bcndanos.github.io/asynchronous/asynchronous/" 8 | readme = "README.md" 9 | license = "Apache-2.0 / MIT" 10 | 11 | [dependencies] 12 | num_cpus = "0.2.5" 13 | 14 | [dev-dependencies] 15 | rustc-serialize = "0.3.14" 16 | docopt = "0.6.64" 17 | ansi_term = "0.5.2" 18 | 19 | [[example]] 20 | name = "prime_numbers" 21 | path = "examples/prime_numbers.rs" 22 | test = false 23 | bench = false -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright 2015 bcndanos 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # asynchronous 2 | 3 | **Asynchronous promises in rust using threads** 4 | 5 | 6 | |Crate|Travis| 7 | |:------:|:-------:| 8 | |[![](http://meritbadge.herokuapp.com/asynchronous)](https://crates.io/crates/asynchronous)|[![Build Status](https://travis-ci.org/bcndanos/asynchronous.svg?branch=master)](https://travis-ci.org/bcndanos/asynchronous)| 9 | 10 | | [API Documentation](http://bcndanos.github.io/asynchronous/asynchronous/) | 11 | 12 | #Overview 13 | 14 | This library provides an usefull way to invoke functions (clousures) in a **Promise Style** using separated threads. A Promise 15 | is a Struct that represents the return value or the error that the funcion produces. 16 | 17 | It also allows the execution of tasks in Parallel or Series in deferred, joining the result in a Promise. 18 | 19 | It includes methods to manage Event Loops, where there are tasks that "emit" events in background, and they are collected by a promise. 20 | 21 | [Project github page](https://github.com/bcndanos/asynchronous) 22 | 23 | This project is based on the [Q Promise](https://github.com/kriskowal/q) library for Node JS and [Async.js](https://github.com/caolan/async) 24 | 25 | #License 26 | 27 | Dual-licensed to be compatible with the Rust project. 28 | 29 | Licensed under the Apache License, Version 2.0 30 | http://www.apache.org/licenses/LICENSE-2.0 or the MIT license 31 | http://opensource.org/licenses/MIT, at your 32 | option. This file may not be copied, modified, or distributed 33 | except according to those terms. 34 | 35 | # Examples 36 | 37 | This is a simple setup for a promise based execution: 38 | 39 | ```rust 40 | use asynchronous::Promise; 41 | 42 | Promise::new(|| { 43 | // Do something 44 | let ret = 10.0 / 3.0; 45 | if ret > 0.0 { Ok(ret) } else { Err("Incorrect Value") } 46 | }).success(|res| { // res has type f64 47 | // Do something if the previous result is correct 48 | assert_eq!(res, 10.0 / 3.0); 49 | let res_int = res as u32 * 2; 50 | Ok(res_int) 51 | }).finally_sync(|res| { // res has type Result 52 | // Executed always at the end 53 | assert_eq!(res.unwrap(), 6u32); 54 | }); 55 | ``` 56 | 57 | Deferred execution: 58 | 59 | ```rust 60 | use asynchronous::{Promise,Deferred,ControlFlow}; 61 | 62 | let d_a = Deferred::<&str, &str>::new(|| { Ok("a") }); 63 | let p_b = Promise::<&str, &str>::new(|| { Ok("b") }); // Executed right now 64 | let d1 = Deferred::::new(|| { Ok(1u32) }); 65 | let d2 = Deferred::::new(|| { Err("Mock Error") }); 66 | let d3 = Deferred::::new(|| { Ok(3u32) }); 67 | let d4 = Deferred::::new(|| { Ok(4u32) }); 68 | let d5 = Deferred::::new(|| { Ok(5u32) }); 69 | 70 | let promise = Deferred::vec_to_promise(vec![d1,d2,d3], ControlFlow::Parallel); 71 | // Only d1, d2 and d3 are being executed at this time. 72 | 73 | assert_eq!("ab", d_a.to_promise().success(|res_a| { 74 | p_b.success(move |res_b| { 75 | Ok(res_a.to_string() + res_b) 76 | }).sync() 77 | }).sync().unwrap()); 78 | 79 | promise.success(|res| { 80 | // Catch the result. In this case, tasks d4 and d5 never will be executed 81 | Ok(res) 82 | }).fail(|error| { 83 | // Catch the error and execute another Promise 84 | assert_eq!(error, vec![Ok(1u32), Err("Mock Error"), Ok(3u32)]); 85 | Deferred::vec_to_promise(vec![d4,d5], ControlFlow::Series).sync() 86 | }).finally_sync(|res| { // res : Result,&str> 87 | // Do something here 88 | assert_eq!(res.unwrap(), vec![4u32, 5u32]); 89 | }); 90 | 91 | ``` 92 | 93 | Simple event loop: 94 | 95 | ```rust 96 | use asynchronous::EventLoop; 97 | 98 | let el = EventLoop::new().finish_in_ms(100); 99 | el.emit("Event1"); 100 | el.emit("Event2"); 101 | // Do something here 102 | el.to_promise().finally_sync(|res| { // res: Result,()> 103 | assert_eq!(res.unwrap(), vec!["Event1", "Event2"]); 104 | }); 105 | ``` 106 | -------------------------------------------------------------------------------- /examples/prime_numbers.rs: -------------------------------------------------------------------------------- 1 | extern crate asynchronous; 2 | extern crate rustc_serialize; 3 | extern crate docopt; 4 | extern crate ansi_term; 5 | 6 | use asynchronous::{Promise, EventLoop, EventLoopHandler, Emit}; 7 | use docopt::Docopt; 8 | use std::thread; 9 | use std::io; 10 | use std::io::Write; 11 | use std::sync::{Arc,Mutex}; 12 | use ansi_term::Colour::{Green, Yellow, Red}; 13 | 14 | static USAGE: &'static str = " 15 | Usage: 16 | cli submit [--duration=] 17 | cli stop 18 | cli status 19 | cli exit 20 | 21 | Options: 22 | --duration= Execution duration in milliseconds 23 | "; 24 | 25 | static USAGE_INFO: &'static str = " 26 | Usage: 27 | submit [--duration=] 28 | stop 29 | status 30 | exit 31 | 32 | Options: 33 | --duration= Execution duration in milliseconds 34 | "; 35 | 36 | #[derive(RustcDecodable, Debug)] 37 | struct Args { 38 | cmd_submit: bool, 39 | cmd_stop: bool, 40 | cmd_status: bool, 41 | cmd_exit: bool, 42 | arg_id: Option, 43 | flag_duration: Option, 44 | } 45 | 46 | enum Execute { 47 | Submit(Option), 48 | Stop(usize), 49 | Status, 50 | Exit 51 | } 52 | 53 | enum Job { 54 | Update(usize, u64) 55 | } 56 | 57 | struct Jobs { 58 | active : Vec<(usize, EventLoopHandler, u64)>, 59 | ended : Vec<(usize, EventLoopHandler, u64)>, 60 | } 61 | 62 | impl Jobs { 63 | fn new() -> Jobs{ 64 | Jobs { 65 | active :vec![], 66 | ended : vec![], 67 | } 68 | } 69 | 70 | fn get_status(&self) -> (usize, usize) { 71 | (self.active.len(), self.ended.len()) 72 | } 73 | 74 | fn add(&mut self, handler:EventLoopHandler) -> usize { 75 | let id = self.active.len() + self.ended.len() + 1; 76 | self.active.push((id, handler, 1)); 77 | id 78 | } 79 | 80 | fn stop(&mut self, id:usize) { 81 | let position = self.active.iter().enumerate().find(|r| (r.1).0 == id).unwrap().0; 82 | self.ended.push(self.active.remove(position)); 83 | } 84 | 85 | fn is_active(&self, id:usize) -> bool { 86 | self.active.iter().find(|r| r.0 == id).is_some() 87 | } 88 | 89 | fn find(&self, id:usize) -> Option<&EventLoopHandler> { 90 | let rec = self.active.iter().find(|r| r.0 == id); 91 | if rec.is_none() { return None } 92 | Some(&rec.unwrap().1) 93 | } 94 | 95 | fn set_prime_number(&mut self, id:usize, prime:u64) { 96 | let rec = self.active.iter_mut().find(|r| r.0 == id); 97 | if rec.is_none() { return } 98 | rec.unwrap().2 = prime; 99 | } 100 | 101 | fn get_prime_number(&self, id:usize) -> u64 { 102 | let rec = self.active.iter().find(|r| r.0 == id); 103 | if rec.is_none() { return 1 } 104 | rec.unwrap().2 105 | } 106 | 107 | fn get_active_jobs(&self) -> Vec<(usize, u64)> { 108 | self.active.iter().map(|v| (v.0, v.2)).collect() 109 | } 110 | 111 | fn get_ended_jobs(&self) -> Vec<(usize, u64)> { 112 | self.ended.iter().map(|v| (v.0, v.2)).collect() 113 | } 114 | } 115 | 116 | fn main() { 117 | 118 | println!("{}", Green.paint(USAGE_INFO)); 119 | 120 | let jobs = Arc::new(Mutex::new(Jobs::new())); 121 | 122 | let el = EventLoop::on_managed(move |event| { 123 | match event { 124 | Execute::Submit(duration) => { 125 | submit_job(jobs.clone(), duration).then(|res| { 126 | let st = format!("Job {} submitted successfully!", res); 127 | println!("{}", Yellow.paint(&st)); 128 | Ok(res) 129 | }, |err| { 130 | println!("There was an error submitting a job!"); 131 | Err(err) 132 | }).finally(|_| { 133 | show_command_line(); 134 | }); 135 | }, 136 | Execute::Stop(id) => { 137 | stop_job(jobs.clone(), id).fail(move |err| { 138 | let st = format!("Error stopping job {} : {}", id, err); 139 | println!("{}", Red.paint(&st)); 140 | show_command_line(); 141 | Err(err) 142 | }); 143 | }, 144 | Execute::Status => { show_status(jobs.clone()); }, 145 | Execute::Exit => return Emit::Stop, 146 | }; 147 | Emit::Continue 148 | }); 149 | 150 | el.emit_until(|| { 151 | show_command_line(); 152 | let ref mut command = String::new(); 153 | let docopt: Docopt = Docopt::new(USAGE).unwrap_or_else(|error| error.exit()); 154 | let _ = io::stdin().read_line(command); 155 | let x: &[_] = &['\r', '\n']; 156 | let mut raw_args: Vec<&str> = command.trim_right_matches(x).split(' ').collect(); 157 | raw_args.insert(0, "cli"); 158 | let args: Args = match docopt.clone().argv(raw_args.into_iter()).decode() { 159 | Ok(args) => args, 160 | Err(error) => { 161 | match error { 162 | docopt::Error::Decode(what) => println!("{}", what), 163 | _ => println!("{}", Green.paint(USAGE_INFO)) , 164 | }; 165 | return Emit::Continue 166 | }, 167 | }; 168 | if args.cmd_exit { return Emit::Event(Execute::Exit) } 169 | if args.cmd_submit { return Emit::Event(Execute::Submit(args.flag_duration)) } 170 | if args.cmd_stop { return Emit::Event(Execute::Stop(args.arg_id.unwrap())) } 171 | if args.cmd_status { return Emit::Event(Execute::Status) } 172 | Emit::Continue 173 | }); 174 | 175 | let _ = el.to_promise().finally_sync(|_| { 176 | println!("Goodbye!"); 177 | }); 178 | } 179 | 180 | fn show_command_line() { 181 | print!(">>> "); 182 | let _ = io::stdout().flush(); 183 | } 184 | 185 | fn show_status(jobs:Arc>) -> Promise<(),String> { 186 | Promise::<(),String>::new(||{ 187 | println!("{}", Yellow.paint("Status -> Collecting info ..... ")); 188 | show_command_line(); 189 | thread::sleep_ms(2000); // Simulate I/O wait 190 | Ok(()) 191 | }).then(move |res| { 192 | let lock = jobs.lock().unwrap(); 193 | let (active, ended) = lock.get_status(); 194 | let st = format!("Status -> Active Processes: {} ", active); 195 | println!("{}", Yellow.paint(&st)); 196 | for v in lock.get_active_jobs() { 197 | let st = format!(" Id Job: {} , Prime Number Found: {}", v.0, v.1); 198 | println!("{}", Green.paint(&st)); 199 | } 200 | let st = format!(" Ended Processes : {} ", ended); 201 | println!("{}", Yellow.paint(&st)); 202 | for v in lock.get_ended_jobs() { 203 | let st = format!(" Id Job: {} , Last Prime Number Found: {}", v.0, v.1); 204 | println!("{}", Red.paint(&st)); 205 | } 206 | Ok(res) 207 | },|err| { 208 | let st = format!("Status -> Error calculating: {}", err); 209 | println!("{}", Yellow.paint(&st)); 210 | Err(err) 211 | }).chain(|res| { 212 | show_command_line(); 213 | res 214 | }) 215 | } 216 | 217 | fn submit_job(jobs:Arc>, duration:Option) -> Promise { 218 | 219 | Promise::new(move || { 220 | thread::sleep_ms(2000); // Simulate I/O wait 221 | 222 | let jobs_cloned = jobs.clone(); 223 | let mut event_loop_job = EventLoop::on(move |event| { 224 | match event { 225 | Job::Update(id, prime) => { 226 | let mut lock = jobs_cloned.lock().unwrap(); 227 | lock.set_prime_number(id, prime); 228 | } 229 | } 230 | }); 231 | if duration.is_some() { event_loop_job = event_loop_job.finish_in_ms(duration.unwrap()); } 232 | 233 | let mut lock = jobs.lock().unwrap(); 234 | let new_id = lock.add(event_loop_job.get_handler()); 235 | 236 | execute_job(jobs.clone(), new_id, event_loop_job.get_handler()); 237 | 238 | let jobs_cloned = jobs.clone(); 239 | event_loop_job.to_promise().finally(move |_| { 240 | let mut lock = jobs_cloned.lock().unwrap(); 241 | lock.stop(new_id); 242 | let st = format!("Job {} ended!", new_id); 243 | println!("{}", Yellow.paint(&st)); 244 | show_command_line(); 245 | }); 246 | Ok(new_id) 247 | }) 248 | } 249 | 250 | fn stop_job(jobs:Arc>, id:usize) -> Promise<(),String> { 251 | Promise::new(move || { 252 | { 253 | let lock = jobs.lock().unwrap(); 254 | if !lock.is_active(id) { 255 | return Err("Process not active".to_string()); 256 | } 257 | } 258 | let st = format!("Stopping Job {} ...", id); 259 | println!("{}", Yellow.paint(&st)); 260 | show_command_line(); 261 | 262 | thread::sleep_ms(2000); // Simulate I/O wait 263 | let jobs_lock = jobs.lock().unwrap(); 264 | match jobs_lock.find(id) { 265 | Some(job) => Ok(job.finish()), 266 | None => Err("Error finding job!".to_string()) 267 | } 268 | }) 269 | } 270 | 271 | fn execute_job(jobs:Arc>, id_job:usize, event_loop_job: EventLoopHandler) { 272 | event_loop_job.emit_until(move || { 273 | thread::sleep_ms(10); 274 | let lock = jobs.lock().unwrap(); 275 | let next_prime = find_next_prime_number(lock.get_prime_number(id_job)); 276 | Emit::Event(Job::Update(id_job, next_prime)) 277 | }); 278 | } 279 | 280 | fn is_prime(number:u64) -> bool { 281 | for i in 2..number { 282 | if number % i == 0 { return false } 283 | } 284 | true 285 | } 286 | 287 | fn find_next_prime_number(from:u64) -> u64 { 288 | let mut probe = from + 1; 289 | while !is_prime(probe) { probe += 1; } 290 | return probe 291 | } -------------------------------------------------------------------------------- /tests/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate asynchronous; 2 | 3 | use std::sync::{Arc, Mutex}; 4 | use std::thread; 5 | use asynchronous::*; 6 | 7 | #[test] 8 | fn promises() { 9 | for x in 0..10 { 10 | let promise = Promise::::new(move || { 11 | match x { 12 | 0 => Err("Division by zero"), 13 | _ => Ok(x * 2) 14 | } 15 | }).success(move |res| { 16 | assert_eq!(res, x * 2); 17 | Ok(res * 2) 18 | }).fail(|error| { 19 | assert_eq!(error, "Division by zero"); 20 | Err(error) 21 | }) ; 22 | 23 | let result = promise.sync(); 24 | 25 | match x { 26 | 0 => assert!(result.is_err()), 27 | _ => { 28 | assert!(result.is_ok()); 29 | assert_eq!(result.unwrap(), x * 4); 30 | } 31 | } 32 | } 33 | } 34 | 35 | #[test] 36 | fn promises_parallel() { 37 | let promise1 = Promise::::new(|| { 38 | Ok(1u32) 39 | }); 40 | let promise2 = Promise::::new(|| { 41 | Ok(2u32) 42 | }); 43 | let promise3 = Promise::::new(|| { 44 | Ok(3u32) 45 | }); 46 | let promise4 = Promise::::new(|| { 47 | Err("Error") 48 | }); 49 | let promise5 = Promise::::new(|| { 50 | Ok(5u32) 51 | }); 52 | Promise::all(vec![promise1, promise2, promise3]).finally_sync(|res| { 53 | assert_eq!(res.unwrap(), vec![1u32,2u32,3u32]); 54 | }); 55 | Promise::all(vec![promise4, promise5]).finally_sync(|res| { 56 | match res { 57 | Ok(_) => unreachable!(), 58 | Err(err) => { 59 | assert!(err[0].is_err()); 60 | assert!(err[1].is_ok()); 61 | } 62 | } 63 | }); 64 | } 65 | 66 | #[test] 67 | fn deferred() { 68 | for x in 0..10 { 69 | let deferred = Deferred::::new(move || { 70 | match x { 71 | 0 => Err("Division by zero"), 72 | _ => Ok(x * 2) 73 | } 74 | }).success(move |res| { 75 | assert_eq!(res, x * 2); 76 | Ok(res * 2) 77 | }).fail(|error| { 78 | assert_eq!(error, "Division by zero"); 79 | Err(error) 80 | }) ; 81 | 82 | let result = deferred.sync(); 83 | 84 | match x { 85 | 0 => assert!(result.is_err()), 86 | _ => { 87 | assert!(result.is_ok()); 88 | assert_eq!(result.unwrap(), x * 4); 89 | } 90 | } 91 | } 92 | } 93 | 94 | #[test] 95 | fn deferred_to_promise() { 96 | Deferred::::new(|| { 97 | Ok(88u32) 98 | }).to_promise().finally_sync(|r| { 99 | assert_eq!(r.unwrap(), 88u32); 100 | }); 101 | } 102 | 103 | #[test] 104 | fn deferred_in_series() { 105 | let st = Arc::new(Mutex::new(String::new())); 106 | 107 | let lock1 = st.clone(); 108 | let d1 = Deferred::::new(move ||{ 109 | thread::sleep_ms(200); 110 | lock1.lock().unwrap().push_str("Def1"); 111 | Ok(1u32) 112 | }); 113 | 114 | let lock2 = st.clone(); 115 | let d2 = Deferred::::new(move || { 116 | thread::sleep_ms(100); 117 | lock2.lock().unwrap().push_str("Def2"); 118 | Ok(2u32) 119 | }); 120 | 121 | let lock3 = st.clone(); 122 | let d3 = Deferred::::new(move ||{ 123 | thread::sleep_ms(200); 124 | lock3.lock().unwrap().push_str("Def3"); 125 | Ok(3u32) 126 | }); 127 | 128 | let d4 = Deferred::::new(|| { 129 | Ok(4u32) 130 | }).chain(|res| { 131 | Ok(res.unwrap() * 3) 132 | }); 133 | let d5 = Deferred::::new(|| { 134 | Err("Error") 135 | }); 136 | let d6 = Deferred::::new(|| { 137 | Ok(6u32) 138 | }); 139 | 140 | let r = Deferred::vec_to_promise(vec![d1, d2, d3], ControlFlow::Series) 141 | .success(|res| { 142 | assert_eq!(vec![1u32,2u32, 3u32], res); 143 | Ok(0u32) 144 | }).sync(); 145 | assert_eq!(r, Ok(0u32)); 146 | assert_eq!(*st.lock().unwrap(),"Def1Def2Def3"); 147 | 148 | Deferred::vec_to_promise(vec![d4,d5,d6], ControlFlow::Series) 149 | .finally_sync(|res| { 150 | match res { 151 | Ok(r) => unreachable!("Res: {:?}", r), 152 | Err(errors) => { 153 | assert_eq!(errors.len(), 2); 154 | assert_eq!(errors[0], Ok(12u32)); 155 | assert_eq!(errors[1], Err("Error")); 156 | } 157 | } 158 | 159 | }); 160 | } 161 | 162 | #[test] 163 | fn deferred_in_parallel() { 164 | let st = Arc::new(Mutex::new(String::new())); 165 | 166 | let lock1 = st.clone(); 167 | let d1 = Deferred::::new(move ||{ 168 | thread::sleep_ms(200); 169 | lock1.lock().unwrap().push_str("Def1"); 170 | Ok(1u32) 171 | }); 172 | let lock2 = st.clone(); 173 | let d2 = Deferred::::new(move || { 174 | thread::sleep_ms(300); 175 | lock2.lock().unwrap().push_str("Def2"); 176 | Ok(2u32) 177 | }); 178 | let lock3 = st.clone(); 179 | let d3 = Deferred::::new(move ||{ 180 | thread::sleep_ms(50); 181 | lock3.lock().unwrap().push_str("Def3"); 182 | Ok(3u32) 183 | }); 184 | let d4 = Deferred::::new(|| { 185 | Ok(4u32) 186 | }); 187 | let d5 = Deferred::::new(|| { 188 | Err("Error") 189 | }); 190 | let d6 = Deferred::::new(|| { 191 | Ok(6u32) 192 | }); 193 | 194 | let r = Deferred::vec_to_promise(vec![d1, d2, d3], ControlFlow::Parallel) 195 | .success(|res| { 196 | assert_eq!(vec![1u32,2u32, 3u32], res); 197 | Ok(0u32) 198 | }).sync(); 199 | assert_eq!(r, Ok(0u32)); 200 | assert_eq!(*st.lock().unwrap(),"Def3Def1Def2"); 201 | 202 | Deferred::vec_to_promise(vec![d4,d5,d6], ControlFlow::Parallel) 203 | .finally_sync(|res| { 204 | match res { 205 | Ok(r) => unreachable!("Res: {:?}", r), 206 | Err(errors) => { 207 | assert_eq!(errors.len(), 3); 208 | assert_eq!(errors[0], Ok(4u32)); 209 | assert_eq!(errors[1], Err("Error")); 210 | assert_eq!(errors[2], Ok(6u32)); 211 | } 212 | } 213 | }); 214 | } 215 | 216 | #[test] 217 | fn deferred_in_parallel_limit() { 218 | let st = Arc::new(Mutex::new(String::new())); 219 | 220 | let lock1 = st.clone(); 221 | let d1 = Deferred::::new(move ||{ 222 | thread::sleep_ms(150); 223 | lock1.lock().unwrap().push_str("Def1"); 224 | Ok(1u32) 225 | }); 226 | let lock2 = st.clone(); 227 | let d2 = Deferred::::new(move || { 228 | thread::sleep_ms(300); 229 | lock2.lock().unwrap().push_str("Def2"); 230 | Ok(2u32) 231 | }); 232 | let lock3 = st.clone(); 233 | let d3 = Deferred::::new(move ||{ 234 | thread::sleep_ms(50); 235 | lock3.lock().unwrap().push_str("Def3"); 236 | Ok(3u32) 237 | }); 238 | let lock4 = st.clone(); 239 | let d4 = Deferred::::new(move || { 240 | thread::sleep_ms(200); 241 | lock4.lock().unwrap().push_str("Def4"); 242 | Ok(4u32) 243 | }); 244 | 245 | let d5 = Deferred::::new(|| { 246 | Ok(5u32) 247 | }); 248 | let d6 = Deferred::::new(|| { 249 | Err("Error d") 250 | }); 251 | 252 | let r = Deferred::vec_to_promise(vec![d1, d2, d3, d4], ControlFlow::ParallelLimit(2)) 253 | .success(|res| { 254 | assert_eq!(vec![1u32,2u32, 3u32,4u32], res); 255 | Ok(0u32) 256 | }).sync(); 257 | assert_eq!(r, Ok(0u32)); 258 | assert_eq!(*st.lock().unwrap(),"Def1Def3Def2Def4"); 259 | 260 | Deferred::vec_to_promise(vec![d5,d6], ControlFlow::ParallelLimit(1)) 261 | .finally_sync(|res| { 262 | match res { 263 | Ok(r) => unreachable!("Res: {:?}", r), 264 | Err(errors) => { 265 | assert_eq!(errors.len(), 2); 266 | assert_eq!(errors[0], Ok(5u32)); 267 | assert_eq!(errors[1], Err("Error d")); 268 | } 269 | } 270 | }); 271 | } 272 | 273 | #[test] 274 | fn deferred_in_parallel_limit_cpus() { 275 | let mut vec = Vec::new(); 276 | for i in 1..5 { 277 | vec.push(Deferred::::new(move ||{ Ok(i) })); 278 | } 279 | Deferred::vec_to_promise(vec, ControlFlow::ParallelCPUS) 280 | .finally_sync(|res| { 281 | assert_eq!(res.unwrap(), vec![1u32, 2u32, 3u32, 4u32]); 282 | }); 283 | } 284 | 285 | #[test] 286 | fn deferred_first_wait() { 287 | let mut v = vec![]; 288 | for i in 0..20 { 289 | v.push(Deferred::::new(move ||{ Ok(i) })); 290 | } 291 | let _ = Deferred::first_to_promise(2, true, v, ControlFlow::Series) 292 | .finally_sync(|res| { 293 | assert_eq!(res.unwrap().len(), 2); 294 | }); 295 | 296 | let mut v = vec![]; 297 | for i in 0..20 { 298 | v.push(Deferred::::new(move ||{ Ok(i) })); 299 | } 300 | let _ = Deferred::first_to_promise(5, true, v, ControlFlow::ParallelLimit(3)) 301 | .finally_sync(|res| { 302 | let r = res.unwrap(); 303 | assert!(r.len()>=5 && r.len()<=7); 304 | }); 305 | 306 | let mut v = vec![]; 307 | for i in 0..20 { 308 | v.push(Deferred::::new(move ||{ Ok(i) })); 309 | } 310 | let _ = Deferred::first_to_promise(5, true, v, ControlFlow::Parallel) 311 | .finally_sync(|res| { 312 | assert_eq!(res.unwrap().len(), 20); 313 | }); 314 | 315 | let mut v = vec![]; 316 | for i in 0..5 { 317 | v.push(Deferred::::new(move ||{ Ok(i) })); 318 | } 319 | v.push(Deferred::::new(move ||{ Err("Error in the middle") })); 320 | for i in 6..20 { 321 | v.push(Deferred::::new(move ||{ Ok(i) })); 322 | } 323 | let _ = Deferred::first_to_promise(10, true, v, ControlFlow::Parallel) 324 | .finally_sync(|res| { 325 | assert_eq!(res.unwrap().len(), 19); 326 | }); 327 | 328 | let mut v = vec![]; 329 | for i in 0..5 { 330 | v.push(Deferred::::new(move ||{ Ok(i) })); 331 | } 332 | for _ in 5..10 { 333 | v.push(Deferred::::new(move ||{ Err("Error") })); 334 | } 335 | let _ = Deferred::first_to_promise(7, true, v, ControlFlow::ParallelLimit(3)) 336 | .finally_sync(|res| { 337 | assert_eq!(res.unwrap_err().len(), 10); 338 | }); 339 | 340 | let mut v = vec![]; 341 | for i in 0..5 { 342 | v.push(Deferred::::new(move ||{ Ok(i) })); 343 | } 344 | let _ = Deferred::first_to_promise(7, true, v, ControlFlow::ParallelLimit(3)) 345 | .finally_sync(|res| { 346 | assert_eq!(res.unwrap_err().len(), 5); 347 | }); 348 | } 349 | 350 | #[test] 351 | fn deferred_first_no_wait() { 352 | let mut v = vec![]; 353 | for i in 0..20 { 354 | v.push(Deferred::::new(move ||{ Ok(i) })); 355 | } 356 | let _ = Deferred::first_to_promise(2, false, v, ControlFlow::Series) 357 | .finally_sync(|res| { 358 | assert_eq!(res.unwrap().len(), 2); 359 | }); 360 | 361 | let mut v = vec![]; 362 | for i in 0..20 { 363 | v.push(Deferred::::new(move ||{ Ok(i) })); 364 | } 365 | let _ = Deferred::first_to_promise(5, false, v, ControlFlow::ParallelLimit(3)) 366 | .finally_sync(|res| { 367 | assert_eq!(res.unwrap().len(), 5); 368 | }); 369 | 370 | let mut v = vec![]; 371 | for i in 0..20 { 372 | v.push(Deferred::::new(move ||{ Ok(i) })); 373 | } 374 | let _ = Deferred::first_to_promise(5, false, v, ControlFlow::Parallel) 375 | .finally_sync(|res| { 376 | assert_eq!(res.unwrap().len(), 5); 377 | }); 378 | 379 | let mut v = vec![]; 380 | for i in 0..5 { 381 | v.push(Deferred::::new(move ||{ Ok(i) })); 382 | } 383 | v.push(Deferred::::new(move ||{ Err("Error in the middle") })); 384 | for i in 6..20 { 385 | v.push(Deferred::::new(move ||{ Ok(i) })); 386 | } 387 | let _ = Deferred::first_to_promise(10, false, v, ControlFlow::ParallelLimit(3)) 388 | .finally_sync(|res| { 389 | assert_eq!(res.unwrap().len(), 10); 390 | }); 391 | 392 | let mut v = vec![]; 393 | for i in 0..5 { 394 | v.push(Deferred::::new(move ||{ Ok(i) })); 395 | } 396 | for _ in 5..10 { 397 | v.push(Deferred::::new(move ||{ Err("Error") })); 398 | } 399 | let _ = Deferred::first_to_promise(7, false, v, ControlFlow::ParallelLimit(3)) 400 | .finally_sync(|res| { 401 | assert_eq!(res.unwrap_err().len(), 10); 402 | }); 403 | 404 | let mut v = vec![]; 405 | for i in 0..5 { 406 | v.push(Deferred::::new(move ||{ Ok(i) })); 407 | } 408 | let _ = Deferred::first_to_promise(7, false, v, ControlFlow::ParallelLimit(3)) 409 | .finally_sync(|res| { 410 | assert_eq!(res.unwrap_err().len(), 5); 411 | }); 412 | } 413 | 414 | #[test] 415 | fn deferred_chained() { 416 | Deferred::::new(||{ 417 | thread::sleep_ms(50); 418 | if true { Ok("first".to_string()) } else { Err("Nothing") } 419 | }).chain(|res| { 420 | let mut v = res.unwrap(); 421 | assert_eq!(v, "first"); 422 | thread::sleep_ms(50); 423 | if true { 424 | v.push_str("second"); 425 | Ok(v) 426 | } else { 427 | Err("Nothing") 428 | } 429 | }).finally_sync(|res| { 430 | assert_eq!(res.unwrap(), "firstsecond"); 431 | }); 432 | } 433 | 434 | #[test] 435 | fn nested_promises() { 436 | let res = Promise::<_,&str>::new(|| { 437 | // Do nothing 438 | Promise::new(|| { 439 | Promise::new(|| { 440 | Ok(4) 441 | }).success(|res| { 442 | Ok(res + 2) 443 | }).sync() 444 | }).success(|res| { 445 | Ok(res * 7) 446 | }).sync() 447 | }).success(|res| { 448 | Ok(res + 5) 449 | }).sync().unwrap(); 450 | assert_eq!(res, 47); 451 | } 452 | 453 | #[test] 454 | fn event_loop_1() { 455 | let event_loop = EventLoop::new(); 456 | assert_eq!(event_loop.emit("EventA"), Ok(())); 457 | assert_eq!(event_loop.emit("EventB"), Ok(())); 458 | assert_eq!(event_loop.emit("EventC"), Ok(())); 459 | let res = event_loop.finish().to_promise().sync().unwrap(); 460 | assert_eq!(res, vec!["EventA", "EventB", "EventC"]); 461 | } 462 | 463 | #[test] 464 | fn event_loop_2() { 465 | let event_loop = EventLoop::new().finish_in_ms(50); 466 | assert_eq!(event_loop.emit("EventA"), Ok(())); 467 | assert_eq!(event_loop.emit("EventB"), Ok(())); 468 | thread::sleep_ms(100); 469 | assert_eq!(event_loop.emit("EventC"), Err("EventC")); 470 | let res = event_loop.finish().to_promise().sync().unwrap(); 471 | assert_eq!(res, vec!["EventA", "EventB"]); 472 | } 473 | 474 | #[test] 475 | fn event_loop_3() { 476 | let event_loop = EventLoop::new(); 477 | assert_eq!(event_loop.emit("EventA"), Ok(())); 478 | assert_eq!(event_loop.emit("EventB"), Ok(())); 479 | let event_loop = event_loop.finish(); 480 | assert_eq!(event_loop.emit("EventC"), Err("EventC")); 481 | assert_eq!(event_loop.is_active(), false); 482 | let res = event_loop.to_promise().sync().unwrap(); 483 | assert_eq!(res, vec!["EventA", "EventB"]); 484 | } 485 | 486 | #[test] 487 | fn event_loop_4() { 488 | let event_loop = EventLoop::new().finish_in_ms(450); 489 | assert_eq!(event_loop.emit("EventA"), Ok(())); 490 | assert_eq!(event_loop.emit("EventB"), Ok(())); 491 | let x = Arc::new(Mutex::new(0)); 492 | event_loop.emit_until(move || { 493 | thread::sleep_ms(100); 494 | let mut lock_x = x.lock().unwrap(); *lock_x += 1; 495 | if *lock_x == 2 { return Emit::Continue } 496 | if *lock_x <= 5 { Emit::Event("EventC") } else { Emit::Stop } 497 | }); 498 | let res = event_loop.to_promise().sync().unwrap(); 499 | assert_eq!(res, vec!["EventA", "EventB", "EventC", "EventC", "EventC"]); 500 | } 501 | 502 | #[test] 503 | fn event_loop_on_1() { 504 | let v = Arc::new(Mutex::new(Vec::<&str>::new())); 505 | let v_cloned = v.clone(); 506 | let event_loop = EventLoop::on(move |event| { 507 | match event { 508 | "EventA" => { let mut v_lock = v_cloned.lock().unwrap(); v_lock.push("EventATreated"); }, 509 | "EventB" => (), 510 | _ => { let mut v_lock = v_cloned.lock().unwrap(); v_lock.push("EventOtherTreated"); }, 511 | } 512 | }); 513 | assert_eq!(event_loop.emit("EventA"), Ok(())); 514 | assert_eq!(event_loop.emit("EventB"), Ok(())); 515 | assert_eq!(event_loop.emit("EventC"), Ok(())); 516 | let res = event_loop.finish().to_promise().sync().unwrap(); 517 | assert_eq!(res.len(), 0); 518 | } 519 | 520 | #[test] 521 | fn event_loop_on_2() { 522 | enum Event { 523 | Hello(String), 524 | Goodbye(String) 525 | } 526 | let v = Arc::new(Mutex::new(Vec::::new())); 527 | let v_cloned = v.clone(); 528 | let event_loop = EventLoop::on(move |event| { 529 | match event { 530 | Event::Hello(_) => (), 531 | Event::Goodbye(v) => { let mut v_lock = v_cloned.lock().unwrap(); v_lock.push(v); }, 532 | } 533 | }).finish_in_ms(100); 534 | assert!(event_loop.emit(Event::Hello("World".to_string())).is_ok()); 535 | assert!(event_loop.emit(Event::Goodbye("BCN".to_string())).is_ok()); 536 | assert!(event_loop.emit(Event::Goodbye("MAD".to_string())).is_ok()); 537 | let res = event_loop.to_promise().sync().unwrap(); 538 | assert_eq!(res.len(), 0); 539 | } 540 | 541 | #[test] 542 | fn event_loop_on_managed_1() { 543 | let event_loop = EventLoop::on_managed(|event| { 544 | match event { 545 | "EventA" => Emit::Event("EventATreated"), 546 | "EventB" => Emit::Continue, 547 | "EventStop" => Emit::Stop, 548 | _ => Emit::Event("EventOtherTreated") 549 | } 550 | }); 551 | assert_eq!(event_loop.emit("EventA"), Ok(())); 552 | assert_eq!(event_loop.emit("EventB"), Ok(())); 553 | assert_eq!(event_loop.emit("EventC"), Ok(())); 554 | assert_eq!(event_loop.emit("EventStop"), Ok(())); 555 | thread::sleep_ms(75); 556 | assert_eq!(event_loop.emit("EventE"), Err("EventE")); 557 | let res = event_loop.finish().to_promise().sync().unwrap(); 558 | assert_eq!(res, vec!["EventATreated", "EventOtherTreated"]); 559 | } 560 | 561 | #[test] 562 | fn event_loop_on_managed_2() { 563 | enum Event { 564 | Hello(String), 565 | Goodbye(String) 566 | } 567 | let event_loop = EventLoop::on_managed(|event| { 568 | match event { 569 | Event::Hello(_) => Emit::Continue, 570 | Event::Goodbye(v) => Emit::Event(Event::Goodbye(v)), 571 | } 572 | }).finish_in_ms(100); 573 | assert!(event_loop.emit(Event::Hello("World".to_string())).is_ok()); 574 | assert!(event_loop.emit(Event::Goodbye("BCN".to_string())).is_ok()); 575 | assert!(event_loop.emit(Event::Goodbye("MAD".to_string())).is_ok()); 576 | let res = event_loop.to_promise().sync().unwrap(); 577 | assert_eq!(res.len(), 2); 578 | match res[0] { Event::Goodbye(ref v) => assert_eq!(v, "BCN") , _ => panic!() }; 579 | match res[1] { Event::Goodbye(ref v) => assert_eq!(v, "MAD") , _ => panic!() }; 580 | } -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | A **promise** based asynchronous library 3 | 4 | This library provides an usefull way to invoke functions (clousures) in a **Promise Style** using separated threads. A Promise 5 | is a Struct that represents the return value or the error that the funcion produces. 6 | 7 | It also allows the execution of tasks in Parallel or Series in deferred, joining the result in a Promise. 8 | 9 | It includes methods to manage Event Loops, where there are tasks that "emit" events in background, and they are collected by a promise. 10 | 11 | [Project github page](https://github.com/bcndanos/asynchronous) 12 | 13 | This project is based on the [Q Promise](https://github.com/kriskowal/q) library for Node JS and [Async.js](https://github.com/caolan/async) 14 | 15 | #License 16 | 17 | Dual-licensed to be compatible with the Rust project. 18 | 19 | Licensed under the Apache License, Version 2.0 20 | http://www.apache.org/licenses/LICENSE-2.0 or the MIT license 21 | http://opensource.org/licenses/MIT, at your 22 | option. This file may not be copied, modified, or distributed 23 | except according to those terms. 24 | 25 | # Examples 26 | 27 | This is a simple setup for a promise based execution: 28 | 29 | ```rust 30 | use asynchronous::Promise; 31 | 32 | Promise::new(|| { 33 | // Do something 34 | let ret = 10.0 / 3.0; 35 | if ret > 0.0 { Ok(ret) } else { Err("Incorrect Value") } 36 | }).success(|res| { // res has type f64 37 | // Do something if the previous result is correct 38 | assert_eq!(res, 10.0 / 3.0); 39 | let res_int = res as u32 * 2; 40 | Ok(res_int) 41 | }).finally_sync(|res| { // res has type Result 42 | // Executed always at the end 43 | assert_eq!(res.unwrap(), 6u32); 44 | }); 45 | ``` 46 | 47 | Deferred execution: 48 | 49 | ```rust 50 | use asynchronous::{Promise,Deferred,ControlFlow}; 51 | 52 | let d_a = Deferred::<&str, &str>::new(|| { Ok("a") }); 53 | let p_b = Promise::<&str, &str>::new(|| { Ok("b") }); // Executed right now 54 | let d1 = Deferred::::new(|| { Ok(1u32) }); 55 | let d2 = Deferred::::new(|| { Err("Mock Error") }); 56 | let d3 = Deferred::::new(|| { Ok(3u32) }); 57 | let d4 = Deferred::::new(|| { Ok(4u32) }); 58 | let d5 = Deferred::::new(|| { Ok(5u32) }); 59 | 60 | let promise = Deferred::vec_to_promise(vec![d1,d2,d3], ControlFlow::Parallel); 61 | // Only d1, d2 and d3 are being executed at this time. 62 | 63 | assert_eq!("ab", d_a.to_promise().success(|res_a| { 64 | p_b.success(move |res_b| { 65 | Ok(res_a.to_string() + res_b) 66 | }).sync() 67 | }).sync().unwrap()); 68 | 69 | promise.success(|res| { 70 | // Catch the result. In this case, tasks d4 and d5 never will be executed 71 | Ok(res) 72 | }).fail(|error| { 73 | // Catch the error and execute another Promise 74 | assert_eq!(error, vec![Ok(1u32), Err("Mock Error"), Ok(3u32)]); 75 | Deferred::vec_to_promise(vec![d4,d5], ControlFlow::Series).sync() 76 | }).finally_sync(|res| { // res : Result,&str> 77 | // Do something here 78 | assert_eq!(res.unwrap(), vec![4u32, 5u32]); 79 | }); 80 | 81 | ``` 82 | 83 | Simple event loop: 84 | 85 | ```rust 86 | use asynchronous::EventLoop; 87 | 88 | let el = EventLoop::new().finish_in_ms(100); 89 | el.emit("Event1"); 90 | el.emit("Event2"); 91 | // Do something here 92 | el.to_promise().finally_sync(|res| { // res: Result,()> 93 | assert_eq!(res.unwrap(), vec!["Event1", "Event2"]); 94 | }); 95 | ``` 96 | 97 | */ 98 | extern crate num_cpus; 99 | 100 | use std::thread; 101 | use std::sync::{mpsc, Arc, Mutex, Condvar}; 102 | 103 | /// Different possibilities for asynchronous treatment of vectors 104 | pub enum ControlFlow { 105 | /// Executes one after each other. Stops execution if one fails. 106 | Series, 107 | /// Executes all tasks at the same time 108 | Parallel, 109 | /// Executes all tasks but only **usize** tasks running at the same time 110 | ParallelLimit(usize), 111 | /// Executes all tasks but only **NumberCpus** tasks running at the same time 112 | ParallelCPUS 113 | } 114 | 115 | /// Stores a function and delays its execution until it's transform to a promise. 116 | /// T : Type of value returned 117 | /// E : Type of error returned 118 | pub struct Deferred { 119 | starter : Arc<(Mutex, Condvar)>, 120 | receiver : mpsc::Receiver> 121 | } 122 | 123 | 124 | impl Deferred where T: Send + 'static , E: Send + 'static { 125 | /// Create a new task in deferred. 126 | /// 127 | /// ```rust 128 | /// let deferred = asynchronous::Deferred::new(|| { 129 | /// // Do something 130 | /// if true { Ok("value a") } else { Err("Error description") } 131 | /// }); 132 | /// // At this point "deferred" is not executed 133 | /// ``` 134 | pub fn new(f:F) -> Deferred where F: Send + 'static + FnOnce() -> Result { 135 | let (tx,rx) = mpsc::channel(); 136 | let pair = Arc::new((Mutex::new(false), Condvar::new())); 137 | let pair_c = pair.clone(); 138 | thread::spawn(move|| { 139 | // wait for the thread to start up 140 | let &(ref lock, ref cvar) = &*pair_c; 141 | let mut started = lock.lock().unwrap(); 142 | while !*started { started = cvar.wait(started).unwrap(); } 143 | tx.send(f()) 144 | }); 145 | Deferred { 146 | starter : pair, 147 | receiver : rx 148 | } 149 | } 150 | 151 | /// Syncronizes the execution with the caller, and returns its value. 152 | /// 153 | /// ```rust 154 | /// use asynchronous::Deferred; 155 | /// 156 | /// let deferred_a = Deferred::<_,&str>::new(|| { 157 | /// // Do something 158 | /// Ok("value a") 159 | /// }); 160 | /// let deferred_b = Deferred::<_,&str>::new(|| { 161 | /// // Do something 162 | /// Ok("value b") 163 | /// }); 164 | /// // Do something 165 | /// assert_eq!(deferred_a.sync(), Ok("value a")); 166 | /// assert_eq!(deferred_b.sync(), Ok("value b")); 167 | /// ``` 168 | pub fn sync(self) -> Result { 169 | self.to_promise().sync() 170 | } 171 | 172 | /// Executes only one of the two functions received depending on the result of the previous task deferred (Ok or Err). 173 | /// Returns a new Deferred 174 | /// 175 | /// ```rust 176 | /// let r = asynchronous::Deferred::new(|| { 177 | /// if false { Ok(1.23) } else { Err("Final error")} 178 | /// }).then(|res| { 179 | /// unreachable!(); 180 | /// assert_eq!(res, 1.23); 181 | /// Ok(34) 182 | /// }, |err| { 183 | /// assert_eq!(err, "Final error"); 184 | /// if true { Ok(35) } else { Err(44u64)} 185 | /// }).sync(); 186 | /// assert_eq!(r, Ok(35)); 187 | /// ``` 188 | pub fn then(self,ft:FT,fe:FE) -> Deferred 189 | where TT: Send + 'static, EE: Send + 'static, 190 | FT: Send + 'static + FnOnce(T) -> Result, 191 | FE: Send + 'static + FnOnce(E) -> Result { 192 | let (tx,rx) = mpsc::channel(); 193 | let pair = Arc::new((Mutex::new(false), Condvar::new())); 194 | let pair_c = pair.clone(); 195 | thread::spawn(move|| { 196 | // wait for the thread to start up 197 | let &(ref lock, ref cvar) = &*pair_c; 198 | let mut started = lock.lock().unwrap(); 199 | while !*started { started = cvar.wait(started).unwrap(); } 200 | self.unlock(); 201 | tx.send(match self.receiver.recv().unwrap() { 202 | Ok(t) => ft(t), 203 | Err(e) => fe(e), 204 | }) 205 | }); 206 | Deferred:: { 207 | starter : pair, 208 | receiver : rx 209 | } 210 | } 211 | 212 | /// The same functionality as **then**, but wraps the result in only one function 213 | /// 214 | /// ```rust 215 | /// let r = asynchronous::Deferred::new(|| { 216 | /// if false { Ok(1.23) } else { Err("Final error")} 217 | /// }).chain(|res| { 218 | /// // Do something that executes always even on error 219 | /// assert!(res.is_err()); 220 | /// res 221 | /// }).then(|res| { 222 | /// unreachable!(); 223 | /// assert_eq!(res, 1.23); 224 | /// Ok(34) 225 | /// }, |err| { 226 | /// assert_eq!(err, "Final error"); 227 | /// if true { Ok(35) } else { Err(44u64)} 228 | /// }).sync(); 229 | /// assert_eq!(r, Ok(35)); 230 | /// ``` 231 | pub fn chain(self, f:FF) -> Deferred 232 | where TT: Send + 'static, EE : Send + 'static, 233 | FF: Send + 'static + FnOnce(Result) -> Result { 234 | let (tx,rx) = mpsc::channel(); 235 | let pair = Arc::new((Mutex::new(false), Condvar::new())); 236 | let pair_c = pair.clone(); 237 | thread::spawn(move|| { 238 | // wait for the thread to start up 239 | let &(ref lock, ref cvar) = &*pair_c; 240 | let mut started = lock.lock().unwrap(); 241 | while !*started { started = cvar.wait(started).unwrap(); } 242 | self.unlock(); 243 | tx.send(f(self.receiver.recv().unwrap())) 244 | }); 245 | Deferred:: { 246 | starter : pair, 247 | receiver : rx 248 | } 249 | } 250 | 251 | /// Executes a new task if the result of the previous promise is Ok. It may return a new type in a correct result (Ok), 252 | /// but it must return the same type of error of its previous promise. 253 | /// 254 | /// ```rust 255 | /// asynchronous::Deferred::new(|| { 256 | /// Ok(1.23) 257 | /// }).success(|res| { 258 | /// assert_eq!(res, 1.23); 259 | /// Ok(34) 260 | /// }).success(|res| { 261 | /// assert_eq!(res, 34); 262 | /// if true { Ok(res) } else { Err("Final error")} 263 | /// }).sync(); 264 | /// ``` 265 | pub fn success(self,f:F) -> Deferred where F: Send + 'static + FnOnce(T) -> Result, TT: Send + 'static { 266 | let (tx,rx) = mpsc::channel(); 267 | let pair = Arc::new((Mutex::new(false), Condvar::new())); 268 | let pair_c = pair.clone(); 269 | thread::spawn(move|| { 270 | // wait for the thread to start up 271 | let &(ref lock, ref cvar) = &*pair_c; 272 | let mut started = lock.lock().unwrap(); 273 | while !*started { started = cvar.wait(started).unwrap(); } 274 | self.unlock(); 275 | tx.send(match self.receiver.recv().unwrap() { 276 | Ok(t) => f(t), 277 | Err(e) => Err(e), 278 | }) 279 | }); 280 | Deferred:: { 281 | starter : pair, 282 | receiver : rx 283 | } 284 | } 285 | 286 | /// Executes a new task if the result of the previous promise is Err. It may return a new type in a correct result (Ok), 287 | /// but it must return the same type of error of its previous promise. 288 | /// 289 | /// ```rust 290 | /// asynchronous::Deferred::new(|| { 291 | /// Err(32) 292 | /// }).success(|res| { 293 | /// unreachable!(); 294 | /// Ok(res) 295 | /// }).fail(|err| { 296 | /// assert_eq!(err, 32); 297 | /// Ok("Value Ok") 298 | /// }).sync(); 299 | /// ``` 300 | pub fn fail(self,f:F) -> Deferred where F: Send + 'static + FnOnce(E) -> Result { 301 | let (tx,rx) = mpsc::channel(); 302 | let pair = Arc::new((Mutex::new(false), Condvar::new())); 303 | let pair_c = pair.clone(); 304 | thread::spawn(move|| { 305 | // wait for the thread to start up 306 | let &(ref lock, ref cvar) = &*pair_c; 307 | let mut started = lock.lock().unwrap(); 308 | while !*started { started = cvar.wait(started).unwrap(); } 309 | self.unlock(); 310 | tx.send(match self.receiver.recv().unwrap() { 311 | Ok(t) => Ok(t), 312 | Err(e) => f(e), 313 | }) 314 | }); 315 | Deferred:: { 316 | starter : pair, 317 | receiver : rx 318 | } 319 | } 320 | 321 | /// Executes one function with the result of the previous deferred. 322 | /// It doesn't return anything and it's completly asynchronous. 323 | /// 324 | /// ```rust 325 | /// asynchronous::Deferred::new(|| { 326 | /// std::thread::sleep_ms(100); 327 | /// if true { Ok(32) } else { Err("Error txt") } 328 | /// }).finally(|res| { 329 | /// assert_eq!(res.unwrap(), 32); 330 | /// }); 331 | /// 332 | /// let a = 2 + 3; // This line is executed before the above Promise 333 | /// 334 | /// ``` 335 | pub fn finally(self, f:F) where F: Send + 'static + FnOnce(Result) { 336 | self.to_promise().finally(f); 337 | } 338 | 339 | /// Executes one function with the result of the previous deferred. 340 | /// It doesn't return anything, but it's synchronized with the caller 341 | /// 342 | /// ```rust 343 | /// use asynchronous::Promise; 344 | /// 345 | /// Promise::new(|| { 346 | /// std::thread::sleep_ms(100); 347 | /// if true { Ok(32) } else { Err("Error txt") } 348 | /// }).finally_sync(|res| { 349 | /// assert_eq!(res.unwrap(), 32); 350 | /// }); 351 | /// 352 | /// let a = 2 + 3; // This line is executed after the above Promise 353 | pub fn finally_sync(self, f:F) where F: Send + 'static + FnOnce(Result) { 354 | self.to_promise().finally_sync(f); 355 | } 356 | 357 | /// Executes the task stored and returns a Promise 358 | /// 359 | /// ```rust 360 | /// let deferred = asynchronous::Deferred::new(|| { 361 | /// // Do something 362 | /// if true { Ok("value a") } else { Err("Error description") } 363 | /// }); 364 | /// // deferred is only stored in memory waiting for .sync() or .to_promise() 365 | /// deferred.to_promise(); 366 | /// // At this point "deferred" is executing 367 | /// ``` 368 | pub fn to_promise(self) -> Promise { 369 | self.unlock(); 370 | Promise { receiver: self.receiver } 371 | } 372 | 373 | /// Executes a vector of tasks and returns a Promise with a vector of values in case that all tasks ended ok. 374 | /// If there's one or more tasks with error, the promise fails and returns a vector with all the Results. 375 | /// 376 | /// ```rust 377 | /// use asynchronous::{Deferred, ControlFlow}; 378 | /// 379 | /// let mut vec_deferred = Vec::new(); 380 | /// for i in 0..5 { vec_deferred.push(Deferred::<_,&str>::new(move || Ok(i) )) } 381 | /// let promise = Deferred::vec_to_promise(vec_deferred, ControlFlow::ParallelCPUS); 382 | /// // At this point all tasks in "vec_deferred" are executing 383 | /// assert_eq!(promise.sync().unwrap(), vec![0,1,2,3,4]); 384 | /// ``` 385 | pub fn vec_to_promise(vector:Vec>, control: ControlFlow) -> Promise,Vec>> { 386 | match control { 387 | ControlFlow::Series => Deferred::process_series(vector, 0), 388 | ControlFlow::Parallel => Deferred::process_parallel(vector, 0, 0, true), 389 | ControlFlow::ParallelLimit(limit) => Deferred::process_parallel(vector, limit, 0, true), 390 | ControlFlow::ParallelCPUS => Deferred::process_parallel(vector, num_cpus::get(), 0, true) 391 | } 392 | } 393 | 394 | /// Executes a vector of tasks and returns a Promise with a vector of the first **num_first** tasks that return Ok. 395 | /// If the **wait** parameter is **true**, the promise waits for all tasks that are running at that moment. 396 | /// If it's **false**, the promise returns once reaches the **num_first** tasks with Ok. 397 | /// If it's not possible achieve this number, the promise fails and returns a vector with all the Results. 398 | /// 399 | /// ```rust 400 | /// use asynchronous::{Deferred, ControlFlow}; 401 | /// 402 | /// let mut v = vec![]; 403 | /// for i in 0..20 { v.push(Deferred::::new(move ||{ Ok(i) })); } 404 | /// // The first 5 tasks that ended with Ok 405 | /// let _ = Deferred::first_to_promise(5, false, v, ControlFlow::ParallelLimit(3)) 406 | /// .finally_sync(|res| { 407 | /// assert_eq!(res.unwrap().len(), 5); 408 | /// }); 409 | /// ``` 410 | pub fn first_to_promise(num_first:usize, wait:bool, vector:Vec>, control: ControlFlow) -> Promise,Vec>> { 411 | match control { 412 | ControlFlow::Series => Deferred::process_series(vector, num_first), 413 | ControlFlow::Parallel => Deferred::process_parallel(vector, 0, num_first, wait), 414 | ControlFlow::ParallelLimit(limit) => Deferred::process_parallel(vector, limit, num_first, wait), 415 | ControlFlow::ParallelCPUS => Deferred::process_parallel(vector, num_cpus::get(), num_first, wait) 416 | } 417 | } 418 | 419 | fn process_series(vector:Vec>, num_first:usize) -> Promise,Vec>> { 420 | let (tx,rx) = mpsc::channel(); 421 | thread::spawn(move || { 422 | let mut results:Vec = Vec::new(); 423 | for defer in vector { 424 | defer.unlock(); 425 | match defer.receiver.recv().unwrap() { 426 | Ok(t) => { 427 | results.push(t); 428 | if num_first > 0 && results.len() >= num_first { break } 429 | }, 430 | Err(e) => { 431 | let mut results_error:Vec> = Vec::new(); 432 | for t in results { results_error.push(Ok(t)) } 433 | results_error.push(Err(e)); 434 | let res:Result,Vec>> = Err(results_error); 435 | tx.send(res).unwrap(); 436 | return 437 | } 438 | } 439 | } 440 | let ok_results:Result, Vec>> = Ok(results); 441 | tx.send(ok_results).unwrap() 442 | }); 443 | Promise::, Vec>> { receiver: rx } 444 | } 445 | 446 | fn process_parallel(vector:Vec>, limit:usize, num_first:usize, wait:bool) -> Promise,Vec>> { 447 | let (tx,rx) = mpsc::channel(); 448 | thread::spawn(move || { 449 | let mut num_results_received = 0; 450 | let mut results:Vec>> = vec![]; 451 | for _ in 0..vector.len() { results.push(None); } 452 | let mut it = vector.into_iter(); 453 | let (txinter, rxinter) = mpsc::channel(); 454 | let mut id_process = 0; 455 | let mut active_process = 0; 456 | let mut is_error = false; 457 | loop { 458 | if active_process > 0 { 459 | match rxinter.recv() { 460 | Ok(r) => { 461 | let finished:(usize,Result) = r; 462 | if finished.1.is_err() { is_error = true } else { num_results_received += 1 } 463 | results[finished.0] = Some(finished.1); 464 | active_process -= 1; 465 | }, 466 | Err(_) => break, 467 | } 468 | } 469 | if !wait && num_first > 0 && num_results_received >= num_first { break } 470 | loop { 471 | if num_first > 0 && num_results_received >= num_first { break } 472 | match it.next() { 473 | Some(defer) => { 474 | active_process += 1; 475 | defer.unlock(); 476 | let txinter_cloned = txinter.clone(); 477 | thread::spawn(move || { 478 | match defer.receiver.recv() { 479 | Ok(r) => { &txinter_cloned.send((id_process, r)); } , 480 | Err(_) => (), 481 | } 482 | 483 | }); 484 | id_process += 1; 485 | }, 486 | None => break 487 | } 488 | if limit > 0 && active_process >= limit { break } 489 | } 490 | if active_process == 0 { break } 491 | } 492 | if num_first > 0 { is_error = num_results_received < num_first } 493 | let ok_results:Result, Vec>> = match is_error { 494 | false => { 495 | let mut v:Vec = Vec::new(); 496 | for r in results { 497 | if r.is_none() { continue } 498 | v.push(match r.unwrap() { Ok(t) => t, Err(_) => continue }) 499 | } 500 | Ok(v) 501 | }, 502 | true => { 503 | let mut v:Vec> = Vec::new(); 504 | for r in results { 505 | if r.is_none() { continue } 506 | v.push(r.unwrap()) 507 | } 508 | Err(v) 509 | } 510 | }; 511 | tx.send(ok_results).unwrap() 512 | }); 513 | Promise::, Vec>> { receiver: rx } 514 | } 515 | 516 | fn unlock(&self) { 517 | let &(ref lock, ref cvar) = &*self.starter; 518 | let mut started = lock.lock().unwrap(); 519 | *started = true; 520 | cvar.notify_one(); 521 | } 522 | } 523 | 524 | /// Stores a result of previous execution tasks. 525 | /// T : Type of value returned 526 | /// E : Type of error returned 527 | pub struct Promise { 528 | receiver : mpsc::Receiver> 529 | } 530 | 531 | impl Promise where T: Send + 'static , E: Send + 'static { 532 | /// Execute a task inmediatly and returns its Promise. 533 | /// 534 | /// ```rust 535 | /// let promise = asynchronous::Promise::new(|| { 536 | /// // Do something 537 | /// if true { Ok("value a")} else { Err("Error description") } 538 | /// }); 539 | /// ``` 540 | pub fn new(f:F) -> Promise where F: Send + 'static + FnOnce() -> Result { 541 | let (tx,rx) = mpsc::channel(); 542 | thread::spawn(move || { tx.send(f()) }); 543 | Promise:: { receiver: rx } 544 | } 545 | 546 | /// Syncronizes the execution with the caller, and returns its value. 547 | /// 548 | /// ```rust 549 | /// use asynchronous::Promise; 550 | /// 551 | /// let promise_a = Promise::<_,&str>::new(|| { 552 | /// // Do something 553 | /// Ok("value a") 554 | /// }); 555 | /// let promise_b = Promise::<_,&str>::new(|| { 556 | /// // Do something 557 | /// Ok("value b") 558 | /// }); 559 | /// // Do something 560 | /// assert_eq!(promise_a.sync(), Ok("value a")); 561 | /// assert_eq!(promise_b.sync(), Ok("value b")); 562 | /// ``` 563 | pub fn sync(self) -> Result { 564 | self.receiver.recv().unwrap() 565 | } 566 | 567 | /// Creates a new promise with the result of all other Promises in the vector. 568 | /// 569 | /// ```rust 570 | /// use asynchronous::Promise; 571 | /// 572 | /// let mut vec_promises = Vec::new(); 573 | /// for i in 0..5 { vec_promises.push(Promise::<_,&str>::new(move || Ok(i) )) } 574 | /// let res = Promise::all(vec_promises).sync().unwrap(); 575 | /// assert_eq!(res, vec![0,1,2,3,4]); 576 | /// ``` 577 | pub fn all(vector:Vec>) -> Promise, Vec>> { 578 | let (tx,rx) = mpsc::channel(); 579 | thread::spawn(move || { 580 | let results:Vec> = vector.iter().map(|p| p.receiver.recv().unwrap() ).collect(); 581 | let is_error = results.iter().find(|r| r.is_err()).is_some(); 582 | let ok_results:Result, Vec>> = match is_error { 583 | false => { 584 | let mut v:Vec = Vec::new(); 585 | for r in results { v.push(match r { Ok(t) => t, Err(_) => unreachable!() })} 586 | Ok(v) 587 | }, 588 | true => Err(results) 589 | }; 590 | tx.send(ok_results).unwrap() 591 | }); 592 | Promise::, Vec>> { receiver: rx } 593 | } 594 | 595 | /// Executes only one of the two functions received depending on the result of the previous promise (Ok or Err). 596 | /// Returns a new Promise 597 | /// 598 | /// ```rust 599 | /// let r = asynchronous::Promise::new(|| { 600 | /// if false { Ok(1.23) } else { Err("Final error")} 601 | /// }).then(|res| { 602 | /// unreachable!(); 603 | /// assert_eq!(res, 1.23); 604 | /// Ok(34) 605 | /// }, |err| { 606 | /// assert_eq!(err, "Final error"); 607 | /// if true { Ok(35) } else { Err(44u64)} 608 | /// }).sync(); 609 | /// assert_eq!(r, Ok(35)); 610 | /// ``` 611 | pub fn then(self,ft:FT,fe:FE) -> Promise 612 | where TT: Send + 'static, EE: Send + 'static, 613 | FT: Send + 'static + FnOnce(T) -> Result, 614 | FE: Send + 'static + FnOnce(E) -> Result { 615 | let (tx,rx) = mpsc::channel(); 616 | thread::spawn(move || { 617 | let res = self.receiver.recv().unwrap(); 618 | match res { 619 | Ok(t) => tx.send(ft(t)), 620 | Err(e) => tx.send(fe(e)) 621 | } 622 | }); 623 | Promise:: { receiver: rx } 624 | } 625 | 626 | /// The same functionality as **then**, but wraps the result in only one function 627 | /// 628 | /// ```rust 629 | /// let r = asynchronous::Promise::new(|| { 630 | /// if false { Ok(1.23) } else { Err("Final error")} 631 | /// }).chain(|res| { 632 | /// // Do something that executes always even on error 633 | /// assert!(res.is_err()); 634 | /// res 635 | /// }).then(|res| { 636 | /// unreachable!(); 637 | /// assert_eq!(res, 1.23); 638 | /// Ok(34) 639 | /// }, |err| { 640 | /// assert_eq!(err, "Final error"); 641 | /// if true { Ok(35) } else { Err(44u64)} 642 | /// }).sync(); 643 | /// assert_eq!(r, Ok(35)); 644 | /// ``` 645 | pub fn chain(self, f:F) -> Promise 646 | where TT: Send + 'static, EE: Send + 'static, 647 | F: Send + 'static + FnOnce(Result) -> Result { 648 | let (tx,rx) = mpsc::channel(); 649 | thread::spawn(move || { 650 | let res = self.receiver.recv().unwrap(); 651 | tx.send(f(res)) 652 | }); 653 | Promise:: { receiver: rx } 654 | } 655 | 656 | /// Executes a new task if the result of the previous promise is Ok. It may return a new type in a correct result (Ok), 657 | /// but it must return the same type of error of its previous promise. 658 | /// 659 | /// ```rust 660 | /// asynchronous::Promise::new(|| { 661 | /// Ok(1.23) 662 | /// }).success(|res| { 663 | /// assert_eq!(res, 1.23); 664 | /// Ok(34) 665 | /// }).success(|res| { 666 | /// assert_eq!(res, 34); 667 | /// if true { Ok(res) } else { Err("Final error")} 668 | /// }).sync(); 669 | /// ``` 670 | pub fn success(self,f:F) -> Promise where F: Send + 'static + FnOnce(T) -> Result, TT: Send + 'static { 671 | let (tx,rx) = mpsc::channel(); 672 | thread::spawn(move || { 673 | let res = self.receiver.recv().unwrap(); 674 | match res { 675 | Ok(t) => tx.send(f(t)), 676 | Err(e) => tx.send(Err(e)) 677 | } 678 | }); 679 | Promise:: { receiver: rx } 680 | } 681 | 682 | /// Executes a new task if the result of the previous promise is Err. It may return a new type in a correct result (Ok), 683 | /// but it must return the same type of error of its previous promise. 684 | /// 685 | /// ```rust 686 | /// asynchronous::Promise::new(|| { 687 | /// Err(32) 688 | /// }).success(|res| { 689 | /// unreachable!(); 690 | /// Ok(res) 691 | /// }).fail(|err| { 692 | /// assert_eq!(err, 32); 693 | /// Ok("Value Ok") 694 | /// }).sync(); 695 | /// ``` 696 | pub fn fail(self,f:F) -> Promise where F: Send + 'static + FnOnce(E) -> Result { 697 | let (tx,rx) = mpsc::channel(); 698 | thread::spawn(move || { 699 | let res = self.receiver.recv().unwrap(); 700 | match res { 701 | Ok(t) => tx.send(Ok(t)), 702 | Err(e) => tx.send(f(e)) 703 | } 704 | }); 705 | Promise:: { receiver: rx } 706 | } 707 | 708 | /// Executes one function with the result of the previous promise. 709 | /// It doesn't return anything and it's completly asynchronous. 710 | /// 711 | /// ```rust 712 | /// asynchronous::Promise::new(|| { 713 | /// std::thread::sleep_ms(100); 714 | /// if true { Ok(32) } else { Err("Error txt") } 715 | /// }).finally(|res| { 716 | /// assert_eq!(res.unwrap(), 32); 717 | /// }); 718 | /// 719 | /// let a = 2 + 3; // This line is executed before the above Promise 720 | /// 721 | /// ``` 722 | pub fn finally(self, f:F) where F: Send + 'static + FnOnce(Result) { 723 | thread::spawn(move || { 724 | f(self.receiver.recv().unwrap()); 725 | }); 726 | } 727 | 728 | /// Executes one function with the result of the previous promise. 729 | /// It doesn't return anything, but it's synchronized with the caller 730 | /// 731 | /// ```rust 732 | /// use asynchronous::Promise; 733 | /// 734 | /// Promise::new(|| { 735 | /// std::thread::sleep_ms(100); 736 | /// if true { Ok(32) } else { Err("Error txt") } 737 | /// }).finally_sync(|res| { 738 | /// assert_eq!(res.unwrap(), 32); 739 | /// }); 740 | /// 741 | /// let a = 2 + 3; // This line is executed after the above Promise 742 | pub fn finally_sync(self, f:F) where F: Send + 'static + FnOnce(Result) { 743 | f(self.sync()); 744 | } 745 | } 746 | 747 | // Event Loops // 748 | 749 | /// Enum representing type of Emit in loops 750 | pub enum Emit { 751 | /// Generates a new event 752 | Event(Ev), 753 | /// Continues the loop 754 | Continue, 755 | /// Stops the loop 756 | Stop 757 | } 758 | 759 | ///Event Loop wrapper that can be cloned to pass through threads 760 | pub struct EventLoopHandler { 761 | tx : mpsc::Sender>, 762 | finisher : Arc<(Mutex, Condvar)>, 763 | finished : Arc>, 764 | } 765 | 766 | impl Clone for EventLoopHandler { 767 | fn clone(&self) -> EventLoopHandler { 768 | EventLoopHandler { 769 | tx : self.tx.clone(), 770 | finisher : self.finisher.clone(), 771 | finished : self.finished.clone(), 772 | } 773 | } 774 | } 775 | 776 | impl EventLoopHandler where Ev: Send + 'static { 777 | /// Triggers an event "Ev" once. Returns the same event if the event loop is not active. 778 | pub fn emit(&self, event:Ev) -> Result<(), Ev>{ 779 | if self.is_active() { 780 | match self.tx.send(Some(event)) { 781 | Ok(_) => Ok(()), 782 | Err(e) => Err(e.0.unwrap()) 783 | } 784 | } else { 785 | Err(event) 786 | } 787 | } 788 | 789 | /// Triggers an event "Ev" until the return of the "clousure" is None 790 | /// 791 | /// ```rust 792 | /// use asynchronous::{EventLoop, Emit}; 793 | /// 794 | /// let el = EventLoop::new(); 795 | /// let x = std::sync::Arc::new(std::sync::Mutex::new(0)); 796 | /// el.emit_until(move || { 797 | /// let mut lock_x = x.lock().unwrap(); *lock_x += 1; 798 | /// if *lock_x <= 3 { Emit::Event("Event Test") } else { Emit::Stop } 799 | /// }); 800 | /// // Do something here 801 | /// el.finish_in_ms(100).to_promise().finally_sync(|res| { // res: Result,()> 802 | /// assert_eq!(res.unwrap(), vec!["Event Test", "Event Test", "Event Test"]); 803 | /// }); 804 | /// ``` 805 | pub fn emit_until(&self, f:F) where F : Send + 'static + Fn() -> Emit { 806 | let handler = self.clone(); 807 | thread::spawn(move || { 808 | loop { 809 | match f() { 810 | Emit::Event(e) => match handler.emit(e) { 811 | Ok(_) => (), 812 | Err(_) => break, 813 | }, 814 | Emit::Continue => continue, 815 | Emit::Stop => break, 816 | }; 817 | } 818 | }); 819 | } 820 | 821 | /// Returns true if the event loop is running 822 | pub fn is_active(&self) -> bool { 823 | let lock_finished = self.finished.lock().unwrap(); 824 | !*lock_finished 825 | } 826 | 827 | /// Finishes the event loop immediately. 828 | pub fn finish(&self) { 829 | let mut lock_finished = self.finished.lock().unwrap(); 830 | if !*lock_finished { 831 | *lock_finished = true; 832 | let _ = self.tx.send(None); 833 | } 834 | } 835 | 836 | /// Finishes the event loop in N milliseconds 837 | pub fn finish_in_ms(&self, duration_ms:u32) { 838 | let handler = self.clone(); 839 | thread::spawn(move|| { 840 | thread::sleep_ms(duration_ms); 841 | let _ = handler.finish(); 842 | }); 843 | } 844 | 845 | } 846 | 847 | ///Executes a task in background collecting events from other threads 848 | pub struct EventLoop { 849 | handler : EventLoopHandler, 850 | receiver : mpsc::Receiver, 851 | } 852 | 853 | impl EventLoop where Ev: Send + 'static { 854 | 855 | /// Creates a new Event Loop and collects all the events into a vector 856 | /// 857 | /// ```rust 858 | /// use asynchronous::EventLoop; 859 | /// 860 | /// let el = EventLoop::new().finish_in_ms(100); 861 | /// el.emit("Event1"); 862 | /// el.emit("Event2"); 863 | /// // Do something here 864 | /// el.to_promise().finally_sync(|res| { // res: Result,()> 865 | /// assert_eq!(res.unwrap(), vec!["Event1", "Event2"]); 866 | /// }); 867 | /// ``` 868 | pub fn new() -> EventLoop { 869 | let pair = Arc::new((Mutex::new(false), Condvar::new())); 870 | let pair_cloned = pair.clone(); 871 | let (tx,rx) = mpsc::channel(); 872 | let (sender, receiver) = mpsc::channel(); 873 | thread::spawn(move || { 874 | loop { 875 | match rx.recv() { 876 | Ok(t) => match t { 877 | Some(v) => sender.send(v).unwrap(), 878 | None => break 879 | }, 880 | Err(_) => break 881 | }; 882 | } 883 | let &(ref lock, ref cvar) = &*pair_cloned; 884 | let mut finished = lock.lock().unwrap(); 885 | *finished = true; 886 | cvar.notify_one(); 887 | }); 888 | EventLoop { 889 | handler : EventLoopHandler { 890 | tx : tx, 891 | finisher : pair, 892 | finished : Arc::new(Mutex::new(false)), 893 | }, 894 | receiver : receiver, 895 | } 896 | } 897 | 898 | /// Creates a new Event Loop and parses all the events produced 899 | /// 900 | /// ```rust 901 | /// use asynchronous::EventLoop; 902 | /// enum MiEvents { Hello(String), Goodbye(u32)} 903 | /// 904 | /// let el = EventLoop::on(|event| { 905 | /// match event { 906 | /// MiEvents::Hello(s) => println!("Hello {}", s), 907 | /// MiEvents::Goodbye(v) => println!("Goodbye {}", v), 908 | /// } 909 | /// }); 910 | /// el.emit(MiEvents::Hello("World".to_string())); 911 | /// el.emit(MiEvents::Goodbye(3)); 912 | /// // Do something here 913 | /// el.finish().to_promise().finally_sync(|res| { // res: Result,()> 914 | /// assert_eq!(res.unwrap().len(), 0); 915 | /// }); 916 | /// ``` 917 | pub fn on(f:F) -> EventLoop where F : Send + 'static + Fn(Ev) { 918 | let pair = Arc::new((Mutex::new(false), Condvar::new())); 919 | let pair_cloned = pair.clone(); 920 | let (tx,rx) = mpsc::channel(); 921 | let (_, receiver) = mpsc::channel(); 922 | thread::spawn(move || { 923 | loop { 924 | match rx.recv() { 925 | Ok(t) => match t { 926 | Some(v) => f(v) , 927 | None => break 928 | }, 929 | Err(_) => break 930 | }; 931 | } 932 | let &(ref lock, ref cvar) = &*pair_cloned; 933 | let mut finished = lock.lock().unwrap(); 934 | *finished = true; 935 | cvar.notify_one(); 936 | }); 937 | EventLoop { 938 | handler : EventLoopHandler { 939 | tx : tx, 940 | finisher : pair, 941 | finished : Arc::new(Mutex::new(false)), 942 | }, 943 | receiver : receiver, 944 | } 945 | } 946 | 947 | /// Creates a new Event Loop, parses all the events produced and collects what you want into a vector 948 | /// 949 | /// ```rust 950 | /// use asynchronous::{EventLoop, Emit}; 951 | /// enum MiEvents { Hello(String), Goodbye(u32)} 952 | /// 953 | /// let el = EventLoop::on_managed(|event| { 954 | /// match event { 955 | /// MiEvents::Hello(s) => { println!("Hello {}", s); Emit::Continue }, 956 | /// MiEvents::Goodbye(v) => Emit::Event(MiEvents::Goodbye(v)), 957 | /// } 958 | /// }); 959 | /// el.emit(MiEvents::Hello("World".to_string())); 960 | /// el.emit(MiEvents::Goodbye(555)); 961 | /// // Do something here 962 | /// el.finish().to_promise().finally_sync(|res| { // res: Result,()> 963 | /// let vec_res = res.unwrap(); 964 | /// assert_eq!(vec_res.len(), 1); 965 | /// match vec_res[0] { MiEvents::Goodbye(vec_res) => assert_eq!(vec_res, 555), _=> () }; 966 | /// }); 967 | /// ``` 968 | pub fn on_managed(f:F) -> EventLoop where F : Send + 'static + Fn(Ev) -> Emit { 969 | let pair = Arc::new((Mutex::new(false), Condvar::new())); 970 | let pair_cloned = pair.clone(); 971 | let (tx,rx) = mpsc::channel(); 972 | let (sender, receiver) = mpsc::channel(); 973 | thread::spawn(move || { 974 | loop { 975 | let rec = match rx.recv() { 976 | Ok(t) => match t { 977 | Some(v) => v , 978 | None => break 979 | }, 980 | Err(_) => break 981 | }; 982 | match f(rec) { 983 | Emit::Event(e) => sender.send(e).unwrap(), 984 | Emit::Continue => (), 985 | Emit::Stop => break, 986 | } 987 | } 988 | let &(ref lock, ref cvar) = &*pair_cloned; 989 | let mut finished = lock.lock().unwrap(); 990 | *finished = true; 991 | cvar.notify_one(); 992 | }); 993 | EventLoop { 994 | handler : EventLoopHandler { 995 | tx : tx, 996 | finisher : pair, 997 | finished : Arc::new(Mutex::new(false)), 998 | }, 999 | receiver : receiver, 1000 | } 1001 | } 1002 | 1003 | /// Triggers an event "Ev" once. Returns the same event if the event loop is not active. 1004 | pub fn emit(&self, event:Ev) -> Result<(), Ev>{ 1005 | self.handler.emit(event) 1006 | } 1007 | 1008 | /// Triggers an event "Ev" until the return of the "clousure" is None 1009 | /// 1010 | /// ```rust 1011 | /// use asynchronous::{EventLoop, Emit}; 1012 | /// 1013 | /// let el = EventLoop::new(); 1014 | /// let x = std::sync::Arc::new(std::sync::Mutex::new(0)); 1015 | /// el.emit_until(move || { 1016 | /// let mut lock_x = x.lock().unwrap(); *lock_x += 1; 1017 | /// if *lock_x <= 3 { Emit::Event("Event Test") } else { Emit::Stop } 1018 | /// }); 1019 | /// // Do something here 1020 | /// el.finish_in_ms(100).to_promise().finally_sync(|res| { // res: Result,()> 1021 | /// assert_eq!(res.unwrap(), vec!["Event Test", "Event Test", "Event Test"]); 1022 | /// }); 1023 | /// ``` 1024 | pub fn emit_until(&self, f:F) where F : Send + 'static + Fn() -> Emit { 1025 | self.handler.emit_until(f); 1026 | } 1027 | 1028 | /// Finishes the event loop immediately. 1029 | pub fn finish(self) -> EventLoop { 1030 | self.handler.finish(); 1031 | self 1032 | } 1033 | 1034 | /// Finishes the event loop in N milliseconds 1035 | pub fn finish_in_ms(self, duration_ms:u32) -> EventLoop { 1036 | self.handler.finish_in_ms(duration_ms); 1037 | self 1038 | } 1039 | 1040 | /// Returns true if the event loop is running 1041 | pub fn is_active(&self) -> bool { 1042 | self.handler.is_active() 1043 | } 1044 | 1045 | /// Returns a handler to Event Emitter 1046 | pub fn get_handler(&self) -> EventLoopHandler { 1047 | self.handler.clone() 1048 | } 1049 | 1050 | /// Once the event loop is finished, the promise collects the results. 1051 | pub fn to_promise(self) -> Promise,()> { 1052 | let handler = self.get_handler(); 1053 | Promise::new(move || { 1054 | let &(ref lock, ref cvar) = &*handler.finisher; 1055 | let mut finished = lock.lock().unwrap(); 1056 | while !*finished { finished = cvar.wait(finished).unwrap(); } 1057 | let mut vec = Vec::new(); 1058 | loop { 1059 | match self.receiver.recv() { 1060 | Ok(val) => vec.push(val), 1061 | Err(_) => break, 1062 | } 1063 | } 1064 | Ok(vec) 1065 | }) 1066 | } 1067 | } 1068 | --------------------------------------------------------------------------------