use may::go;
use may::sync::mpsc;
use may_actor::Actor;
const TOTAL_NUM: usize = 100_000_000;
const WORK_LOAD: usize = 10000;
const ACTOR_NUMBER: usize = 100;
#[inline]
fn pow_of_minus_one(pow: usize) -> f64 {
if pow & 1 != 0 {
-1.0
} else {
1.0
}
}
#[inline]
fn calc_work(start: usize, end: usize) -> f64 {
let mut sum = 0.0;
let mut divisor = 2 * start + 1;
for i in start..end {
sum += pow_of_minus_one(i) / divisor as f64;
divisor += 2;
}
sum
}
fn pi() -> f64 {
calc_work(0, TOTAL_NUM) * 4.0
}
fn pi_coroutine() -> f64 {
let works = TOTAL_NUM / WORK_LOAD;
let (tx, rx) = mpsc::channel();
let mut start = 0;
for _ in 0..works {
let tx = tx.clone();
let end = start + WORK_LOAD;
go!(move || tx.send(calc_work(start, end)).unwrap());
start = end;
}
let mut sum = 0.0;
for _ in 0..works {
sum += rx.recv().unwrap();
}
sum * 4.0
}
fn pi_actor() -> f64 {
const WORKS: usize = TOTAL_NUM / WORK_LOAD;
struct Worker;
impl Worker {
fn work(&self, master: Actor<Master>, start: usize, end: usize) {
let data = calc_work(start, end);
master.call(move |me| me.recv_data(data));
}
}
struct Master {
pi: f64,
count: usize,
tx: mpsc::Sender<f64>,
}
impl Master {
fn start(&self) {
let mut workers = Vec::with_capacity(ACTOR_NUMBER);
for _ in 0..ACTOR_NUMBER {
workers.push(Actor::new(Worker));
}
let mut start = 0;
for i in 0..WORKS {
let end = start + WORK_LOAD;
let master = unsafe { Actor::from(self) };
workers[i % ACTOR_NUMBER].call(move |me| me.work(master, start, end));
start = end;
}
}
fn recv_data(&mut self, data: f64) {
self.pi += data;
self.count += 1;
if self.count == WORKS {
self.tx.send(self.pi).unwrap();
}
}
}
let (tx, rx) = mpsc::channel();
let master = Actor::new(Master {
pi: 0.0,
count: 0,
tx: tx,
});
master.call(|me| me.start());
rx.recv().unwrap() * 4.0
}
fn main() {
may::config().set_workers(4);
let dur = std::time::Instant::now();
println!("pi is {}, dur = {:?}", pi(), dur.elapsed());
let dur = std::time::Instant::now();
println!("pi is {}, dur = {:?}", pi_coroutine(), dur.elapsed());
let dur = std::time::Instant::now();
println!("pi is {}, dur = {:?}", pi_actor(), dur.elapsed());
}