Fix race condition in Accountant::apply_payment()
This commit is contained in:
parent
736d3eabae
commit
1acd2aa8cf
|
@ -33,14 +33,21 @@ pub type Result<T> = result::Result<T, AccountingError>;
|
||||||
|
|
||||||
/// Commit funds to the 'to' party.
|
/// Commit funds to the 'to' party.
|
||||||
fn apply_payment(balances: &RwLock<HashMap<PublicKey, AtomicIsize>>, payment: &Payment) {
|
fn apply_payment(balances: &RwLock<HashMap<PublicKey, AtomicIsize>>, payment: &Payment) {
|
||||||
|
// First we check balances with a read lock to maximize potential parallelization.
|
||||||
if balances.read().unwrap().contains_key(&payment.to) {
|
if balances.read().unwrap().contains_key(&payment.to) {
|
||||||
let bals = balances.read().unwrap();
|
let bals = balances.read().unwrap();
|
||||||
bals[&payment.to].fetch_add(payment.tokens as isize, Ordering::Relaxed);
|
bals[&payment.to].fetch_add(payment.tokens as isize, Ordering::Relaxed);
|
||||||
} else {
|
} else {
|
||||||
|
// Now we know the key wasn't present a nanosecond ago, but it might be there
|
||||||
|
// by the time we aquire a write lock, so we'll have to check again.
|
||||||
let mut bals = balances.write().unwrap();
|
let mut bals = balances.write().unwrap();
|
||||||
|
if bals.contains_key(&payment.to) {
|
||||||
|
bals[&payment.to].fetch_add(payment.tokens as isize, Ordering::Relaxed);
|
||||||
|
} else {
|
||||||
bals.insert(payment.to, AtomicIsize::new(payment.tokens as isize));
|
bals.insert(payment.to, AtomicIsize::new(payment.tokens as isize));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Accountant {
|
pub struct Accountant {
|
||||||
balances: RwLock<HashMap<PublicKey, AtomicIsize>>,
|
balances: RwLock<HashMap<PublicKey, AtomicIsize>>,
|
||||||
|
|
Loading…
Reference in New Issue