-
Notifications
You must be signed in to change notification settings - Fork 1
/
13_2_fake_google_search_async.rs
78 lines (63 loc) · 2.05 KB
/
13_2_fake_google_search_async.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//! Based on Go example
//! [slide 46: "Google Search 2.0"](https://talks.golang.org/2012/concurrency.slide#46)
//!
//! Run the Web, Image, and Video searches concurrently, and wait for all results.
//!
//! No locks. No condition variables. No callbacks.
//!
use async_std::task;
use futures::channel::mpsc::channel;
use futures::sink::SinkExt;
use futures::stream::StreamExt;
use std::time;
mod helpers;
struct FakeSearch<'a> {
kind: &'a str,
}
impl<'a> FakeSearch<'a> {
const fn new(kind: &'a str) -> Self {
Self { kind }
}
async fn call(&self, query: &str) -> String {
task::sleep(helpers::rand_duration(0, 100)).await;
format!("{} result for {}", self.kind, query)
}
}
static WEB: FakeSearch = FakeSearch::new("web");
static IMAGE: FakeSearch = FakeSearch::new("image");
static VIDEO: FakeSearch = FakeSearch::new("video");
async fn google(query: &str) -> Vec<String> {
let mut results = Vec::new();
let (sender, mut receiver) = channel(0);
let searches: [&FakeSearch; 3] = [&WEB, &IMAGE, &VIDEO];
for search in &searches {
// Clone values so they can be safely transferred across the threads
let search = search.to_owned();
let query = query.to_owned();
let mut sender = sender.to_owned();
task::spawn(async move {
// Perform the search
let result = search.call(&query).await;
// Send the result back over the channel
sender.send(result).await.unwrap();
});
}
// Drop the original sender so channel will close when all search tasks
// have completed
drop(sender);
// Aggregate results until the channel closes
while let Some(result) = receiver.next().await {
results.push(result);
}
results
}
fn main() {
task::block_on(async_main());
}
async fn async_main() {
let start = time::Instant::now();
let results = google("rust lang").await;
let elapsed = start.elapsed();
println!("Result: {:#?}", results);
println!("Elapsed: {}ms", helpers::to_millis(elapsed));
}