1use may::go;
2use may::sync::mpsc;
3use may_actor::Actor;
4
5const TOTAL_NUM: usize = 100_000_000;
6const WORK_LOAD: usize = 10000;
7const ACTOR_NUMBER: usize = 100;
8
9#[inline]
10fn pow_of_minus_one(pow: usize) -> f64 {
11 if pow & 1 != 0 {
12 -1.0
13 } else {
14 1.0
15 }
16}
17
18#[inline]
19fn calc_work(start: usize, end: usize) -> f64 {
20 let mut sum = 0.0;
21 let mut divisor = 2 * start + 1;
22 for i in start..end {
23 sum += pow_of_minus_one(i) / divisor as f64;
24 divisor += 2;
25 }
26 sum
27}
28
29fn pi() -> f64 {
31 calc_work(0, TOTAL_NUM) * 4.0
32}
33
34fn pi_coroutine() -> f64 {
36 let works = TOTAL_NUM / WORK_LOAD;
37 let (tx, rx) = mpsc::channel();
38
39 let mut start = 0;
40 for _ in 0..works {
41 let tx = tx.clone();
42 let end = start + WORK_LOAD;
43 go!(move || tx.send(calc_work(start, end)).unwrap());
44 start = end;
45 }
46
47 let mut sum = 0.0;
48 for _ in 0..works {
49 sum += rx.recv().unwrap();
50 }
51 sum * 4.0
52}
53
54fn pi_actor() -> f64 {
56 const WORKS: usize = TOTAL_NUM / WORK_LOAD;
57
58 struct Worker;
59 impl Worker {
60 fn work(&self, master: Actor<Master>, start: usize, end: usize) {
61 let data = calc_work(start, end);
62 master.call(move |me| me.recv_data(data));
63 }
64 }
65
66 struct Master {
67 pi: f64,
68 count: usize,
69 tx: mpsc::Sender<f64>,
70 }
71
72 impl Master {
73 fn start(&self) {
74 let mut workers = Vec::with_capacity(ACTOR_NUMBER);
76 for _ in 0..ACTOR_NUMBER {
77 workers.push(Actor::new(Worker));
78 }
79
80 let mut start = 0;
82 for i in 0..WORKS {
83 let end = start + WORK_LOAD;
84 let master = unsafe { Actor::from(self) };
85 workers[i % ACTOR_NUMBER].call(move |me| me.work(master, start, end));
86 start = end;
87 }
88 }
89
90 fn recv_data(&mut self, data: f64) {
91 self.pi += data;
92 self.count += 1;
93 if self.count == WORKS {
94 self.tx.send(self.pi).unwrap();
95 }
96 }
97 }
98
99 let (tx, rx) = mpsc::channel();
100
101 let master = Actor::new(Master {
103 pi: 0.0,
104 count: 0,
105 tx: tx,
106 });
107
108 master.call(|me| me.start());
109
110 rx.recv().unwrap() * 4.0
111}
112
113fn main() {
114 may::config().set_workers(4);
115 let dur = std::time::Instant::now();
116 println!("pi is {}, dur = {:?}", pi(), dur.elapsed());
117 let dur = std::time::Instant::now();
118 println!("pi is {}, dur = {:?}", pi_coroutine(), dur.elapsed());
119 let dur = std::time::Instant::now();
120 println!("pi is {}, dur = {:?}", pi_actor(), dur.elapsed());
121}