LenCachingMutex (#9988)

New util LenCachingMutex can be used in place of a Mutex, when working
with collections, or other types with a len() method. When
the Guard is dropped, the value returned from len() is stored
into an AtomicUsize and can be queried using load_len() without
needing to lock the Mutex. Implementations for ```Vec``` and
```VecDeque```.

Now used in [Verification](4ded4181a6/ethcore/src/verification/queue/mod.rs (L196)) so that calls to ```VerificationQueue.queue_info()```
no longer require locks.
This commit is contained in:
mattrutherford
2018-12-04 14:30:52 +00:00
committed by GitHub
parent 4ded4181a6
commit ec886ddefb
6 changed files with 170 additions and 11 deletions

View File

@@ -112,6 +112,7 @@ extern crate journaldb;
extern crate serde;
#[cfg(any(test, feature = "json-tests", feature = "test-helpers"))]
extern crate tempdir;
extern crate len_caching_mutex;
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))]
extern crate hardware_wallet;

View File

@@ -29,6 +29,7 @@ use io::*;
use error::{BlockError, ImportErrorKind, ErrorKind, Error};
use engines::EthEngine;
use client::ClientIoMessage;
use len_caching_mutex::LenCachingMutex;
use self::kind::{BlockLike, Kind};
@@ -195,9 +196,9 @@ impl QueueSignal {
struct Verification<K: Kind> {
// All locks must be captured in the order declared here.
unverified: Mutex<VecDeque<K::Unverified>>,
verifying: Mutex<VecDeque<Verifying<K>>>,
verified: Mutex<VecDeque<K::Verified>>,
unverified: LenCachingMutex<VecDeque<K::Unverified>>,
verifying: LenCachingMutex<VecDeque<Verifying<K>>>,
verified: LenCachingMutex<VecDeque<K::Verified>>,
bad: Mutex<HashSet<H256>>,
sizes: Sizes,
check_seal: bool,
@@ -207,9 +208,9 @@ impl<K: Kind> VerificationQueue<K> {
/// Creates a new queue instance.
pub fn new(config: Config, engine: Arc<EthEngine>, message_channel: IoChannel<ClientIoMessage>, check_seal: bool) -> Self {
let verification = Arc::new(Verification {
unverified: Mutex::new(VecDeque::new()),
verifying: Mutex::new(VecDeque::new()),
verified: Mutex::new(VecDeque::new()),
unverified: LenCachingMutex::new(VecDeque::new()),
verifying: LenCachingMutex::new(VecDeque::new()),
verified: LenCachingMutex::new(VecDeque::new()),
bad: Mutex::new(HashSet::new()),
sizes: Sizes {
unverified: AtomicUsize::new(0),
@@ -332,7 +333,7 @@ impl<K: Kind> VerificationQueue<K> {
return;
}
wait.wait(&mut unverified);
wait.wait(unverified.inner_mut());
}
if let State::Exit = *state.0.lock() {
@@ -453,7 +454,7 @@ impl<K: Kind> VerificationQueue<K> {
pub fn flush(&self) {
let mut unverified = self.verification.unverified.lock();
while !unverified.is_empty() || !self.verification.verifying.lock().is_empty() {
self.empty.wait(&mut unverified);
self.empty.wait(unverified.inner_mut());
}
}
@@ -595,18 +596,18 @@ impl<K: Kind> VerificationQueue<K> {
use std::mem::size_of;
let (unverified_len, unverified_bytes) = {
let len = self.verification.unverified.lock().len();
let len = self.verification.unverified.load_len();
let size = self.verification.sizes.unverified.load(AtomicOrdering::Acquire);
(len, size + len * size_of::<K::Unverified>())
};
let (verifying_len, verifying_bytes) = {
let len = self.verification.verifying.lock().len();
let len = self.verification.verifying.load_len();
let size = self.verification.sizes.verifying.load(AtomicOrdering::Acquire);
(len, size + len * size_of::<Verifying<K>>())
};
let (verified_len, verified_bytes) = {
let len = self.verification.verified.lock().len();
let len = self.verification.verified.load_len();
let size = self.verification.sizes.verified.load(AtomicOrdering::Acquire);
(len, size + len * size_of::<K::Verified>())
};