block_state_inner.rs

Overview

This file defines the BlockStateInner struct and implements concurrency-safe access patterns for managing the mutable state of a blockchain block. It encapsulates shared mutable access to an internal block state (AckiNackiBlockState) alongside a block identifier (BlockIdentifier). The primary functionality revolves around synchronized read and write access using a read-write lock (RwLock), enabling safe concurrent operations on the block state within multiple threads.

The file also provides trait implementations for hashing and equality comparison based on the block identifier. Additionally, it implements the Guarded, GuardedMut, and TryGuardedMut traits for the concurrency-safe access abstraction, which allow executing closures over immutable or mutable references of the inner state. Optional instrumentation for detecting long lock hold times is conditionally included via feature flags.

Structures and Traits

BlockStateInner

pub struct BlockStateInner {
    pub(super) block_identifier: BlockIdentifier,
    pub(super) shared_access: RwLock<AckiNackiBlockState>,
}

Trait Implementations

Hash for BlockStateInner

impl Hash for BlockStateInner {
    fn hash<H>(&self, state: &mut H)
    where
        H: Hasher,
    {
        self.block_identifier.hash(state)
    }
}

PartialEq and Eq for BlockStateInner

impl PartialEq for BlockStateInner {
    fn eq(&self, other: &Self) -> bool {
        self.block_identifier == other.block_identifier
    }
}

impl Eq for BlockStateInner {}

Concurrency and Guarded Access Traits

The file implements the following traits for Arc<BlockStateInner>, enabling safe concurrent access to the internal state:

These traits come from the crate::utilities::guarded module and provide controlled access via closures.

Guarded<AckiNackiBlockState>

impl Guarded<AckiNackiBlockState> for Arc<BlockStateInner> {
    #[track_caller]
    fn guarded<F, T>(&self, action: F) -> T
    where
        F: FnOnce(&AckiNackiBlockState) -> T,
    {
        let guard = self.shared_access.read();
        // Optional instrumentation for detecting long locks
        #[cfg(feature = "fail_on_long_lock")]
        let start = std::time::Instant::now();

        let result = action(&guard);

        drop(guard);

        #[cfg(feature = "fail_on_long_lock")]
        if start.elapsed() > std::time::Duration::from_millis(MAX_LOCK_TIME_MS) {
            eprintln!("{:?}", std::backtrace::Backtrace::force_capture());
            eprintln!("Block state lock has taken too long");
            // panic!("Block state lock has taken too long");
        }
        result
    }
}

Usage Example:

let block_state: Arc<BlockStateInner> = ...;
let block_id = block_state.guarded(|state| state.get_id());

GuardedMut<AckiNackiBlockState>

impl GuardedMut<AckiNackiBlockState> for Arc<BlockStateInner> {
    #[track_caller]
    fn guarded_mut<F, T>(&self, action: F) -> T
    where
        F: FnOnce(&mut AckiNackiBlockState) -> T,
    {
        let mut guard = self.shared_access.write();

        #[cfg(feature = "fail_on_long_lock")]
        let start = std::time::Instant::now();

        let result = guard.inner_guarded_mut(action);

        drop(guard);

        #[cfg(feature = "fail_on_long_lock")]
        if start.elapsed() > std::time::Duration::from_millis(MAX_LOCK_TIME_MS) {
            eprintln!("{:?}", std::backtrace::Backtrace::force_capture());
            panic!("Block state lock has taken too long");
        }

        result
    }
}

Usage Example:

block_state.guarded_mut(|state| {
    state.update_field(new_value);
});

TryGuardedMut<AckiNackiBlockState>

impl TryGuardedMut<AckiNackiBlockState> for Arc<BlockStateInner> {
    #[track_caller]
    fn try_guarded_mut<F, T>(&self, action: F) -> Option<T>
    where
        F: FnOnce(&mut AckiNackiBlockState) -> T,
    {
        self.shared_access.try_write().map(|mut guard| guard.inner_guarded_mut(action))
    }
}

Usage Example:

if let Some(result) = block_state.try_guarded_mut(|state| state.modify_something()) {
    // Mutation succeeded
} else {
    // Could not acquire lock for mutation
}

Implementation Details

Interaction with Other Components


Mermaid Diagram

classDiagram
class BlockStateInner {
-block_identifier: BlockIdentifier
-shared_access: RwLock<AckiNackiBlockState>
}
class ArcBlockStateInner {
+guarded()
+guarded_mut()
+try_guarded_mut()
}
BlockStateInner <.. ArcBlockStateInner : wraps
ArcBlockStateInner ..|> Guarded
ArcBlockStateInner ..|> GuardedMut
ArcBlockStateInner ..|> TryGuardedMut

This diagram illustrates the core struct BlockStateInner and its concurrency-safe access via Arc<BlockStateInner> implementing the guarded access traits. The private fields and the key methods for guarded access are highlighted, showing the encapsulation and trait-based interface.