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
use std::sync::mpsc::{sync_channel, Receiver, SyncSender};
use threadpool::ThreadPool;
/**
A StringFuture can perform diffing in a background thread.
Doing get() on a future that isn't done yet will block until the result is
available.
*/
pub(crate) struct StringFuture {
// This field is only valid if we're done with the result_receiver (next
// field)
result: String,
// If available, get() will await a result on this receiver, then populate
// the result field and return it
result_receiver: Option<Receiver<String>>,
}
impl StringFuture {
/// Create an already-finished future
pub fn from_string(result: String) -> StringFuture {
return StringFuture {
result,
result_receiver: None,
};
}
pub fn from_function(
f: impl FnOnce() -> String + Send + 'static,
thread_pool: &ThreadPool,
) -> StringFuture {
// Create a String channel
let (sender, receiver): (SyncSender<String>, Receiver<String>) = sync_channel(1);
// Start diffing in a thread
thread_pool.execute(move || {
// Call the function
let result = f();
// Done, channel the result!
sender.send(result).unwrap();
});
return StringFuture {
result: "".to_string(),
result_receiver: Some(receiver),
};
}
#[allow(clippy::wrong_self_convention)]
pub fn is_empty(&mut self) -> bool {
return self.get().is_empty();
}
pub fn get(&mut self) -> &str {
// If the result is still pending...
if let Some(receiver) = &self.result_receiver {
// ... wait for it
self.result = receiver.recv().unwrap();
self.result_receiver = None;
}
return &self.result;
}
}