use super::{
BlockId, BlockMetadata, BlockRegistrationHandle, RegisteredBlock, SequenceHash, UpgradeFn,
};
use crate::metrics::BlockPoolMetrics;
use std::sync::{Arc, Weak};
pub struct ImmutableBlock<T: BlockMetadata> {
block: Arc<dyn RegisteredBlock<T>>,
upgrade_fn: UpgradeFn<T>,
metrics: Option<Arc<BlockPoolMetrics>>,
}
#[derive(Clone)]
pub struct WeakBlock<T: BlockMetadata> {
sequence_hash: SequenceHash,
block: Weak<dyn RegisteredBlock<T>>,
upgrade_fn: UpgradeFn<T>,
metrics: Option<Arc<BlockPoolMetrics>>,
}
impl<T: BlockMetadata> ImmutableBlock<T> {
pub(crate) fn new(
block: Arc<dyn RegisteredBlock<T>>,
upgrade_fn: UpgradeFn<T>,
metrics: Option<Arc<BlockPoolMetrics>>,
) -> Self {
if let Some(ref m) = metrics {
m.inc_inflight_immutable();
}
Self {
block,
upgrade_fn,
metrics,
}
}
pub fn downgrade(&self) -> WeakBlock<T> {
WeakBlock {
sequence_hash: self.sequence_hash(),
block: Arc::downgrade(&self.block),
upgrade_fn: self.upgrade_fn.clone(),
metrics: self.metrics.clone(),
}
}
pub fn block_id(&self) -> BlockId {
self.block.block_id()
}
pub fn sequence_hash(&self) -> SequenceHash {
self.block.sequence_hash()
}
pub fn registration_handle(&self) -> BlockRegistrationHandle {
self.block.registration_handle().clone()
}
pub fn use_count(&self) -> usize {
Arc::strong_count(&self.block)
}
}
impl<T: BlockMetadata> Clone for ImmutableBlock<T> {
fn clone(&self) -> Self {
if let Some(ref m) = self.metrics {
m.inc_inflight_immutable();
}
Self {
block: self.block.clone(),
upgrade_fn: self.upgrade_fn.clone(),
metrics: self.metrics.clone(),
}
}
}
impl<T: BlockMetadata> Drop for ImmutableBlock<T> {
#[inline]
fn drop(&mut self) {
if let Some(ref m) = self.metrics {
m.dec_inflight_immutable();
}
}
}
impl<T: BlockMetadata> std::fmt::Debug for ImmutableBlock<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ImmutableBlock")
.field("block_id", &self.block_id())
.field("sequence_hash", &self.sequence_hash())
.finish()
}
}
impl<T: BlockMetadata> WeakBlock<T> {
pub fn upgrade(&self) -> Option<ImmutableBlock<T>> {
if let Some(block) = self.block.upgrade() {
return Some(ImmutableBlock::new(
block,
self.upgrade_fn.clone(),
self.metrics.clone(),
));
}
if let Some(block) = (self.upgrade_fn)(self.sequence_hash) {
return Some(ImmutableBlock::new(
block,
self.upgrade_fn.clone(),
self.metrics.clone(),
));
}
None
}
pub fn sequence_hash(&self) -> SequenceHash {
self.sequence_hash
}
}
impl<T: BlockMetadata> std::fmt::Debug for WeakBlock<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("WeakBlock")
.field("sequence_hash", &self.sequence_hash())
.finish()
}
}