//! An interface for a transaction queue use std::collections::HashSet; use std::{cmp, fmt}; use rand::{self, Rng}; use Contribution; /// An interface to the transaction queue. A transaction queue is a structural part of /// `QueueingHoneyBadger` that manages enqueueing of transactions for a future batch and dequeueing /// of transactions to become part of a current batch. pub trait TransactionQueue: fmt::Debug + Default + Extend + Sync + Send { /// Checks whether the queue is empty. fn is_empty(&self) -> bool; /// Returns a new set of `amount` transactions, randomly chosen from the first `batch_size`. /// No transactions are removed from the queue. // TODO: Return references, once the `HoneyBadger` API accepts them. fn choose(&mut self, rng: &mut R, amount: usize, batch_size: usize) -> Vec; /// Removes the given transactions from the queue. fn remove_multiple<'a, I>(&mut self, txs: I) where I: IntoIterator, T: 'a + Contribution; } impl TransactionQueue for Vec where T: Clone + fmt::Debug + Sync + Send, { #[inline] fn is_empty(&self) -> bool { self.is_empty() } #[inline] fn remove_multiple<'a, I>(&mut self, txs: I) where I: IntoIterator, T: 'a + Contribution, { let tx_set: HashSet<_> = txs.into_iter().collect(); self.retain(|tx| !tx_set.contains(tx)); } // TODO: Return references, once the `HoneyBadger` API accepts them. Remove `Clone` bound. #[inline] fn choose(&mut self, rng: &mut R, amount: usize, batch_size: usize) -> Vec { let limit = cmp::min(batch_size, self.len()); let sample = match rand::seq::sample_iter(rng, self.iter().take(limit), amount) { Ok(choice) => choice, Err(choice) => choice, // Fewer than `amount` were available, which is fine. }; sample.into_iter().cloned().collect() } }