Skip to content

Commit d3a0a8a

Browse files
committed
Introduce Notifiers
Nrtofiers limits the lifetime of the inner lock.
1 parent e1df2af commit d3a0a8a

File tree

1 file changed

+33
-8
lines changed

1 file changed

+33
-8
lines changed

core/src/miner/miner.rs

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use ctypes::{BlockHash, BlockNumber, Header, TxHash};
3939
use cvm::ChainTimeInfo;
4040
use kvdb::KeyValueDB;
4141
use parking_lot::{Mutex, RwLock};
42-
use primitives::{Bytes, H256};
42+
use primitives::{Bytes, H256, U256};
4343
use std::borrow::Borrow;
4444
use std::collections::HashSet;
4545
use std::iter::once;
@@ -126,11 +126,38 @@ pub struct Miner {
126126
sealing_enabled: AtomicBool,
127127

128128
accounts: Option<Arc<AccountProvider>>,
129-
notifiers: RwLock<Vec<Box<dyn NotifyWork>>>,
129+
notifiers: Notifiers,
130130
malicious_users: RwLock<HashSet<Address>>,
131131
immune_users: RwLock<HashSet<Address>>,
132132
}
133133

134+
struct Notifiers {
135+
notifiers: RwLock<Vec<Box<dyn NotifyWork>>>,
136+
}
137+
138+
impl Notifiers {
139+
pub fn new(notifiers: Vec<Box<dyn NotifyWork>>) -> Self {
140+
Self {
141+
notifiers: RwLock::new(notifiers),
142+
}
143+
}
144+
145+
pub fn push(&self, notifier: Box<dyn NotifyWork>) {
146+
self.notifiers.write().push(notifier);
147+
}
148+
149+
pub fn is_empty(&self) -> bool {
150+
self.notifiers.read().is_empty()
151+
}
152+
153+
pub fn notify(&self, pow_hash: H256, target: U256) {
154+
// FIXME: Calling callbacks inside of lock lifetime may cause a deadlock.
155+
for notifier in self.notifiers.read().iter() {
156+
notifier.notify(pow_hash, target)
157+
}
158+
}
159+
}
160+
134161
struct SealingBlockLastRequest {
135162
block_number: Mutex<u64>,
136163
}
@@ -203,7 +230,7 @@ impl Params {
203230
impl Miner {
204231
/// Push listener that will handle new jobs
205232
pub fn add_work_listener(&self, notifier: Box<dyn NotifyWork>) {
206-
self.notifiers.write().push(notifier);
233+
self.notifiers.push(notifier);
207234
}
208235

209236
pub fn new(
@@ -254,7 +281,7 @@ impl Miner {
254281
options,
255282
sealing_enabled: AtomicBool::new(true),
256283
accounts,
257-
notifiers: RwLock::new(notifiers),
284+
notifiers: Notifiers::new(notifiers),
258285
malicious_users: RwLock::new(HashSet::new()),
259286
immune_users: RwLock::new(HashSet::new()),
260287
}
@@ -503,7 +530,7 @@ impl Miner {
503530
let is_new = original_work_hash.map_or(true, |h| *block.block().header().hash() != h);
504531
sealing_work.queue.push(block);
505532
// If push notifications are enabled we assume all work items are used.
506-
if !self.notifiers.read().is_empty() && is_new {
533+
if !self.notifiers.is_empty() && is_new {
507534
sealing_work.queue.use_last_ref();
508535
}
509536
(Some((pow_hash, score, number)), is_new)
@@ -520,9 +547,7 @@ impl Miner {
520547
if is_new {
521548
if let Some((pow_hash, score, _number)) = work {
522549
let target = self.engine.score_to_target(&score);
523-
for notifier in self.notifiers.read().iter() {
524-
notifier.notify(pow_hash, target)
525-
}
550+
self.notifiers.notify(pow_hash, target);
526551
}
527552
}
528553
}

0 commit comments

Comments
 (0)