aboutsummaryrefslogtreecommitdiff
path: root/vendor/once_cell/examples
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/once_cell/examples')
-rw-r--r--vendor/once_cell/examples/bench.rs28
-rw-r--r--vendor/once_cell/examples/bench_acquire.rs39
-rw-r--r--vendor/once_cell/examples/lazy_static.rs36
-rw-r--r--vendor/once_cell/examples/reentrant_init_deadlocks.rs14
-rw-r--r--vendor/once_cell/examples/regex.rs49
-rw-r--r--vendor/once_cell/examples/test_synchronization.rs38
6 files changed, 204 insertions, 0 deletions
diff --git a/vendor/once_cell/examples/bench.rs b/vendor/once_cell/examples/bench.rs
new file mode 100644
index 0000000..e680125
--- /dev/null
+++ b/vendor/once_cell/examples/bench.rs
@@ -0,0 +1,28 @@
+use std::mem::size_of;
+
+use once_cell::sync::OnceCell;
+
+const N_THREADS: usize = 32;
+const N_ROUNDS: usize = 100_000_000;
+
+static CELL: OnceCell<usize> = OnceCell::new();
+
+fn main() {
+ let start = std::time::Instant::now();
+ let threads =
+ (0..N_THREADS).map(|i| std::thread::spawn(move || thread_main(i))).collect::<Vec<_>>();
+ for thread in threads {
+ thread.join().unwrap();
+ }
+ println!("{:?}", start.elapsed());
+ println!("size_of::<OnceCell<()>>() = {:?}", size_of::<OnceCell<()>>());
+ println!("size_of::<OnceCell<bool>>() = {:?}", size_of::<OnceCell<bool>>());
+ println!("size_of::<OnceCell<u32>>() = {:?}", size_of::<OnceCell<u32>>());
+}
+
+fn thread_main(i: usize) {
+ for _ in 0..N_ROUNDS {
+ let &value = CELL.get_or_init(|| i);
+ assert!(value < N_THREADS)
+ }
+}
diff --git a/vendor/once_cell/examples/bench_acquire.rs b/vendor/once_cell/examples/bench_acquire.rs
new file mode 100644
index 0000000..1518047
--- /dev/null
+++ b/vendor/once_cell/examples/bench_acquire.rs
@@ -0,0 +1,39 @@
+//! Benchmark the overhead that the synchronization of `OnceCell::get` causes.
+//! We do some other operations that write to memory to get an imprecise but somewhat realistic
+//! measurement.
+
+use once_cell::sync::OnceCell;
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+const N_THREADS: usize = 16;
+const N_ROUNDS: usize = 1_000_000;
+
+static CELL: OnceCell<usize> = OnceCell::new();
+static OTHER: AtomicUsize = AtomicUsize::new(0);
+
+fn main() {
+ let start = std::time::Instant::now();
+ let threads =
+ (0..N_THREADS).map(|i| std::thread::spawn(move || thread_main(i))).collect::<Vec<_>>();
+ for thread in threads {
+ thread.join().unwrap();
+ }
+ println!("{:?}", start.elapsed());
+ println!("{:?}", OTHER.load(Ordering::Relaxed));
+}
+
+#[inline(never)]
+fn thread_main(i: usize) {
+ // The operations we do here don't really matter, as long as we do multiple writes, and
+ // everything is messy enough to prevent the compiler from optimizing the loop away.
+ let mut data = [i; 128];
+ let mut accum = 0usize;
+ for _ in 0..N_ROUNDS {
+ let _value = CELL.get_or_init(|| i + 1);
+ let k = OTHER.fetch_add(data[accum & 0x7F] as usize, Ordering::Relaxed);
+ for j in data.iter_mut() {
+ *j = (*j).wrapping_add(accum);
+ accum = accum.wrapping_add(k);
+ }
+ }
+}
diff --git a/vendor/once_cell/examples/lazy_static.rs b/vendor/once_cell/examples/lazy_static.rs
new file mode 100644
index 0000000..3cdb19f
--- /dev/null
+++ b/vendor/once_cell/examples/lazy_static.rs
@@ -0,0 +1,36 @@
+extern crate once_cell;
+
+use once_cell::sync::{Lazy, OnceCell};
+use std::collections::HashMap;
+
+static HASHMAP: Lazy<HashMap<u32, &'static str>> = Lazy::new(|| {
+ let mut m = HashMap::new();
+ m.insert(0, "foo");
+ m.insert(1, "bar");
+ m.insert(2, "baz");
+ m
+});
+
+// Same, but completely without macros
+fn hashmap() -> &'static HashMap<u32, &'static str> {
+ static INSTANCE: OnceCell<HashMap<u32, &'static str>> = OnceCell::new();
+ INSTANCE.get_or_init(|| {
+ let mut m = HashMap::new();
+ m.insert(0, "foo");
+ m.insert(1, "bar");
+ m.insert(2, "baz");
+ m
+ })
+}
+
+fn main() {
+ // First access to `HASHMAP` initializes it
+ println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
+
+ // Any further access to `HASHMAP` just returns the computed value
+ println!("The entry for `1` is \"{}\".", HASHMAP.get(&1).unwrap());
+
+ // The same works for function-style:
+ assert_eq!(hashmap().get(&0), Some(&"foo"));
+ assert_eq!(hashmap().get(&1), Some(&"bar"));
+}
diff --git a/vendor/once_cell/examples/reentrant_init_deadlocks.rs b/vendor/once_cell/examples/reentrant_init_deadlocks.rs
new file mode 100644
index 0000000..af4b5b7
--- /dev/null
+++ b/vendor/once_cell/examples/reentrant_init_deadlocks.rs
@@ -0,0 +1,14 @@
+fn main() {
+ let cell = once_cell::sync::OnceCell::<u32>::new();
+ cell.get_or_init(|| {
+ cell.get_or_init(|| 1);
+ 2
+ });
+}
+
+/// Dummy test to make it seem hang when compiled as `--test`
+/// See https://github.com/matklad/once_cell/issues/79
+#[test]
+fn dummy_test() {
+ std::thread::sleep(std::time::Duration::from_secs(4));
+}
diff --git a/vendor/once_cell/examples/regex.rs b/vendor/once_cell/examples/regex.rs
new file mode 100644
index 0000000..4c4c2ea
--- /dev/null
+++ b/vendor/once_cell/examples/regex.rs
@@ -0,0 +1,49 @@
+use std::{str::FromStr, time::Instant};
+
+use regex::Regex;
+
+macro_rules! regex {
+ ($re:literal $(,)?) => {{
+ static RE: once_cell::sync::OnceCell<regex::Regex> = once_cell::sync::OnceCell::new();
+ RE.get_or_init(|| regex::Regex::new($re).unwrap())
+ }};
+}
+
+fn slow() {
+ let s = r##"13.28.24.13 - - [10/Mar/2016:19:29:25 +0100] "GET /etc/lib/pChart2/examples/index.php?Action=View&Script=../../../../cnf/db.php HTTP/1.1" 404 151 "-" "HTTP_Request2/2.2.1 (http://pear.php.net/package/http_request2) PHP/5.3.16""##;
+
+ let mut total = 0;
+ for _ in 0..1000 {
+ let re = Regex::new(
+ r##"^(\S+) (\S+) (\S+) \[([^]]+)\] "([^"]*)" (\d+) (\d+) "([^"]*)" "([^"]*)"$"##,
+ )
+ .unwrap();
+ let size = usize::from_str(re.captures(s).unwrap().get(7).unwrap().as_str()).unwrap();
+ total += size;
+ }
+ println!("{}", total);
+}
+
+fn fast() {
+ let s = r##"13.28.24.13 - - [10/Mar/2016:19:29:25 +0100] "GET /etc/lib/pChart2/examples/index.php?Action=View&Script=../../../../cnf/db.php HTTP/1.1" 404 151 "-" "HTTP_Request2/2.2.1 (http://pear.php.net/package/http_request2) PHP/5.3.16""##;
+
+ let mut total = 0;
+ for _ in 0..1000 {
+ let re: &Regex = regex!(
+ r##"^(\S+) (\S+) (\S+) \[([^]]+)\] "([^"]*)" (\d+) (\d+) "([^"]*)" "([^"]*)"$"##,
+ );
+ let size = usize::from_str(re.captures(s).unwrap().get(7).unwrap().as_str()).unwrap();
+ total += size;
+ }
+ println!("{}", total);
+}
+
+fn main() {
+ let t = Instant::now();
+ slow();
+ println!("slow: {:?}", t.elapsed());
+
+ let t = Instant::now();
+ fast();
+ println!("fast: {:?}", t.elapsed());
+}
diff --git a/vendor/once_cell/examples/test_synchronization.rs b/vendor/once_cell/examples/test_synchronization.rs
new file mode 100644
index 0000000..0d54f98
--- /dev/null
+++ b/vendor/once_cell/examples/test_synchronization.rs
@@ -0,0 +1,38 @@
+//! Test if the OnceCell properly synchronizes.
+//! Needs to be run in release mode.
+//!
+//! We create a `Vec` with `N_ROUNDS` of `OnceCell`s. All threads will walk the `Vec`, and race to
+//! be the first one to initialize a cell.
+//! Every thread adds the results of the cells it sees to an accumulator, which is compared at the
+//! end.
+//! All threads should end up with the same result.
+
+use once_cell::sync::OnceCell;
+
+const N_THREADS: usize = 32;
+const N_ROUNDS: usize = 1_000_000;
+
+static CELLS: OnceCell<Vec<OnceCell<usize>>> = OnceCell::new();
+static RESULT: OnceCell<usize> = OnceCell::new();
+
+fn main() {
+ let start = std::time::Instant::now();
+ CELLS.get_or_init(|| vec![OnceCell::new(); N_ROUNDS]);
+ let threads =
+ (0..N_THREADS).map(|i| std::thread::spawn(move || thread_main(i))).collect::<Vec<_>>();
+ for thread in threads {
+ thread.join().unwrap();
+ }
+ println!("{:?}", start.elapsed());
+ println!("No races detected");
+}
+
+fn thread_main(i: usize) {
+ let cells = CELLS.get().unwrap();
+ let mut accum = 0;
+ for cell in cells.iter() {
+ let &value = cell.get_or_init(|| i);
+ accum += value;
+ }
+ assert_eq!(RESULT.get_or_init(|| accum), &accum);
+}