concurrent_avl_tree 0.1.0

Lock-free readable AVL tree with epoch-based reclamation and background batch rebalancing.
Documentation
//! # Batch Operation Collector
//!
//! Thread-safe buffer for deferred tree modification requests.
//!
//! ## License & Attribution
//! SPDX-License-Identifier: MIT | Author: Dzulkifli Anwar | Version: 0.1.0 | Date: 2026-04-30

use std::sync::Mutex;

/// # Operation Type Enum
///
/// Categorical indicator for batch modification intent.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum OperationType {
    /// Add key-value pair to tree structure.
    Insert,
    /// Remove key from tree structure.
    Delete,
}

/// # Batch Entry Descriptor
///
/// Atomic operation descriptor for tree mutation.
///
/// ## Description
/// Carries operation type, target key, and optional value payload.
/// Serialization occurs before builder invocation.
#[derive(Debug, Clone)]
pub struct BatchEntry<K, V> {
    /// Mutation intent.
    pub operation_type: OperationType,
    /// Target key for insertion or deletion.
    pub target_key: K,
    /// Optional payload for insertion operations.
    pub target_value: Option<V>,
}

/// # Concurrent Batch Collector
///
/// Protects internal vector with mutex. Sorts entries before extraction.
///
/// ## Invariant
/// `entries.is_empty() == true` immediately after `extract_and_sort` return.
///
/// ## Thread Safety
/// `append_operation` requires internal mutex. `extract_and_sort` requires external serialization.
pub struct BatchCollector<K, V> {
    entries: Mutex<Vec<BatchEntry<K, V>>>,
}

impl<K, V> Default for BatchCollector<K, V> {
    fn default() -> Self {
        Self { entries: Mutex::new(Vec::new()) }
    }
}

impl<K: PartialOrd, V> BatchCollector<K, V> {
    /// # Append Mutation Request
    ///
    /// Stores operation metadata in internal buffer.
    ///
    /// ## Parameters
    /// - `entry`: Fully populated entry descriptor.
    ///
    /// ## Panics
    /// Panics if internal mutex is poisoned (indicates panic in another thread holding the lock).
    ///
    /// ## Thread Safety
    /// Thread-safe via internal mutex.
    pub fn append_operation(&self, entry: BatchEntry<K, V>) {
        let mut guard = self.entries.lock().unwrap();
        guard.push(entry);
    }

    /// # Extract and Sort Pending Operations
    ///
    /// Returns internal buffer sorted by ascending target key. Clears storage.
    ///
    /// ## Returns
    /// Sorted vector of `BatchEntry<K, V>`.
    ///
    /// ## Panics
    /// Panics if internal mutex is poisoned (indicates panic in another thread holding the lock).
    ///
    /// ## Thread Safety
    /// Not thread-safe. Caller must serialize invocations.
    pub fn extract_and_sort(&self) -> Vec<BatchEntry<K, V>> {
        let mut guard = self.entries.lock().unwrap();
        let mut extracted = std::mem::take(&mut *guard);
        extracted.sort_by(|a, b| {
            a.target_key.partial_cmp(&b.target_key).unwrap_or(std::cmp::Ordering::Equal)
        });
        extracted
    }
}