Skip to content

Commit ff6a44f

Browse files
Wu Yu WeiStjepan Glavina
Wu Yu Wei
authored and
Stjepan Glavina
committed
Use once_cell instead of lazy_static (#416)
`once_cell` provides a neat way of initializing lazy singletons without macro. This PR use `sync::Lazy` to streamline same pattern proposed in related rust RFC. Resolve #406
1 parent da795de commit ff6a44f

File tree

5 files changed

+60
-66
lines changed

5 files changed

+60
-66
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ crossbeam-utils = "0.6.6"
3333
futures-core-preview = "=0.3.0-alpha.19"
3434
futures-io-preview = "=0.3.0-alpha.19"
3535
futures-timer = "1.0.2"
36-
lazy_static = "1.4.0"
3736
log = { version = "0.4.8", features = ["kv_unstable"] }
3837
memchr = "2.2.1"
3938
mio = "0.6.19"
4039
mio-uds = "0.6.7"
4140
num_cpus = "1.10.1"
41+
once_cell = "1.2.0"
4242
pin-utils = "0.1.0-alpha.4"
4343
slab = "0.4.2"
4444
kv-log-macro = "1.0.4"

src/net/driver/mod.rs

+16-18
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use std::fmt;
22
use std::sync::{Arc, Mutex};
33

4-
use lazy_static::lazy_static;
54
use mio::{self, Evented};
5+
use once_cell::sync::Lazy;
66
use slab::Slab;
77

88
use crate::io;
@@ -100,25 +100,23 @@ impl Reactor {
100100
// }
101101
}
102102

103-
lazy_static! {
104-
/// The state of the global networking driver.
105-
static ref REACTOR: Reactor = {
106-
// Spawn a thread that waits on the poller for new events and wakes up tasks blocked on I/O
107-
// handles.
108-
std::thread::Builder::new()
109-
.name("async-net-driver".to_string())
110-
.spawn(move || {
111-
// If the driver thread panics, there's not much we can do. It is not a
112-
// recoverable error and there is no place to propagate it into so we just abort.
113-
abort_on_panic(|| {
114-
main_loop().expect("async networking thread has panicked");
115-
})
103+
/// The state of the global networking driver.
104+
static REACTOR: Lazy<Reactor> = Lazy::new(|| {
105+
// Spawn a thread that waits on the poller for new events and wakes up tasks blocked on I/O
106+
// handles.
107+
std::thread::Builder::new()
108+
.name("async-net-driver".to_string())
109+
.spawn(move || {
110+
// If the driver thread panics, there's not much we can do. It is not a
111+
// recoverable error and there is no place to propagate it into so we just abort.
112+
abort_on_panic(|| {
113+
main_loop().expect("async networking thread has panicked");
116114
})
117-
.expect("cannot start a thread driving blocking tasks");
115+
})
116+
.expect("cannot start a thread driving blocking tasks");
118117

119-
Reactor::new().expect("cannot initialize reactor")
120-
};
121-
}
118+
Reactor::new().expect("cannot initialize reactor")
119+
});
122120

123121
/// Waits on the poller for new events and wakes up tasks blocked on I/O handles.
124122
fn main_loop() -> io::Result<()> {

src/task/blocking.rs

+22-22
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::thread;
55
use std::time::Duration;
66

77
use crossbeam_channel::{bounded, Receiver, Sender};
8-
use lazy_static::lazy_static;
8+
use once_cell::sync::Lazy;
99

1010
use crate::task::task::{JoinHandle, Tag};
1111
use crate::utils::abort_on_panic;
@@ -19,30 +19,30 @@ struct Pool {
1919
receiver: Receiver<async_task::Task<Tag>>,
2020
}
2121

22-
lazy_static! {
23-
static ref POOL: Pool = {
24-
for _ in 0..2 {
25-
thread::Builder::new()
26-
.name("async-blocking-driver".to_string())
27-
.spawn(|| abort_on_panic(|| {
22+
static POOL: Lazy<Pool> = Lazy::new(|| {
23+
for _ in 0..2 {
24+
thread::Builder::new()
25+
.name("async-blocking-driver".to_string())
26+
.spawn(|| {
27+
abort_on_panic(|| {
2828
for task in &POOL.receiver {
2929
task.run();
3030
}
31-
}))
32-
.expect("cannot start a thread driving blocking tasks");
33-
}
34-
35-
// We want to use an unbuffered channel here to help
36-
// us drive our dynamic control. In effect, the
37-
// kernel's scheduler becomes the queue, reducing
38-
// the number of buffers that work must flow through
39-
// before being acted on by a core. This helps keep
40-
// latency snappy in the overall async system by
41-
// reducing bufferbloat.
42-
let (sender, receiver) = bounded(0);
43-
Pool { sender, receiver }
44-
};
45-
}
31+
})
32+
})
33+
.expect("cannot start a thread driving blocking tasks");
34+
}
35+
36+
// We want to use an unbuffered channel here to help
37+
// us drive our dynamic control. In effect, the
38+
// kernel's scheduler becomes the queue, reducing
39+
// the number of buffers that work must flow through
40+
// before being acted on by a core. This helps keep
41+
// latency snappy in the overall async system by
42+
// reducing bufferbloat.
43+
let (sender, receiver) = bounded(0);
44+
Pool { sender, receiver }
45+
});
4646

4747
// Create up to MAX_THREADS dynamic blocking task worker threads.
4848
// Dynamic threads will terminate themselves if they don't

src/task/pool.rs

+19-21
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::thread;
33

44
use crossbeam_deque::{Injector, Stealer, Worker};
55
use kv_log_macro::trace;
6-
use lazy_static::lazy_static;
6+
use once_cell::sync::Lazy;
77

88
use super::sleepers::Sleepers;
99
use super::task;
@@ -111,28 +111,26 @@ impl Pool {
111111

112112
#[inline]
113113
pub(crate) fn get() -> &'static Pool {
114-
lazy_static! {
115-
static ref POOL: Pool = {
116-
let num_threads = num_cpus::get().max(1);
117-
let mut stealers = Vec::new();
114+
static POOL: Lazy<Pool> = Lazy::new(|| {
115+
let num_threads = num_cpus::get().max(1);
116+
let mut stealers = Vec::new();
118117

119-
// Spawn worker threads.
120-
for _ in 0..num_threads {
121-
let worker = Worker::new_fifo();
122-
stealers.push(worker.stealer());
118+
// Spawn worker threads.
119+
for _ in 0..num_threads {
120+
let worker = Worker::new_fifo();
121+
stealers.push(worker.stealer());
123122

124-
thread::Builder::new()
125-
.name("async-task-driver".to_string())
126-
.spawn(|| abort_on_panic(|| worker::main_loop(worker)))
127-
.expect("cannot start a thread driving tasks");
128-
}
123+
thread::Builder::new()
124+
.name("async-task-driver".to_string())
125+
.spawn(|| abort_on_panic(|| worker::main_loop(worker)))
126+
.expect("cannot start a thread driving tasks");
127+
}
129128

130-
Pool {
131-
injector: Injector::new(),
132-
stealers,
133-
sleepers: Sleepers::new(),
134-
}
135-
};
136-
}
129+
Pool {
130+
injector: Injector::new(),
131+
stealers,
132+
sleepers: Sleepers::new(),
133+
}
134+
});
137135
&*POOL
138136
}

src/task/task_local.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::future::Future;
55
use std::sync::atomic::{AtomicUsize, Ordering};
66
use std::sync::Mutex;
77

8-
use lazy_static::lazy_static;
8+
use once_cell::sync::Lazy;
99

1010
use super::worker;
1111
use crate::utils::abort_on_panic;
@@ -174,9 +174,7 @@ impl<T: Send + 'static> LocalKey<T> {
174174
fn key(&self) -> usize {
175175
#[cold]
176176
fn init(key: &AtomicUsize) -> usize {
177-
lazy_static! {
178-
static ref COUNTER: Mutex<usize> = Mutex::new(1);
179-
}
177+
static COUNTER: Lazy<Mutex<usize>> = Lazy::new(|| Mutex::new(1));
180178

181179
let mut counter = COUNTER.lock().unwrap();
182180
let prev = key.compare_and_swap(0, *counter, Ordering::AcqRel);

0 commit comments

Comments
 (0)