#lock-free #high-performance #transaction #optimistic #confirmation-based

transactional

A simple optimistic lock-free confirmation-based transactional model for Rust

3 releases (breaking)

Uses new Rust 2024

new 0.3.0 Apr 29, 2025
0.2.0 Apr 29, 2025
0.1.0 Apr 29, 2025

#194 in Concurrency

Download history 132/week @ 2025-04-23

132 downloads per month

Custom license

23KB
333 lines

transactional

A simple optimistic lock-free confirmation-based transactional model for Rust.

Overview and Terminology

This crate implements a model that allows the modification of a value, seeks confirmation through a callback to a lambda, and only commits the change if there are no objections, all without strict isolation from other concurrent operations.

This model is referred to as an optimistic confirmation-based transactional model or a confirmation-based commit protocol.

Here’s a breakdown of the key characteristics and terminology:

  • Non-isolated: The model does not guarantee isolation from other concurrent transactions, meaning other operations could see intermediate or uncommitted changes, or the underlying data could change before final confirmation.

  • Transactional: The process is grouped as a transaction, but with relaxed isolation guarantees. It may operate at a low isolation level such as READ UNCOMMITTED or READ COMMITTED, which allow for dirty or non-repeatable reads.

  • Confirmation step: Before the transaction is finalized (committed), there is an explicit confirmation phase-often implemented as a "pending" or "provisional" state-where complaints or objections can be raised.

  • Commit-on-no-objection: Only after the confirmation phase passes without objections is the change actually applied (committed).

    This pattern is sometimes seen in collaborative or distributed systems where consensus or user approval is needed before finalizing a change, but strict isolation is not enforced for performance or usability reasons.

    Common terms for such models include:

  • Optimistic transaction with confirmation

  • Provisional commit with confirmation

  • Confirmation-based commit protocol

  • Two-phase commit with external confirmation (if the confirmation step is formalized as a phase in the commit process)

    It is not a standard ACID transaction due to the lack of isolation, and the confirmation step differentiates it from simple optimistic concurrency control, which typically checks for conflicts at commit time without explicit confirmation.

    In summary, the most precise description would be a confirmation-based transactional model with relaxed or non-isolated semantics.

Features

  • For synchronous, non-concurrent use only
  • Lightweight, clone-free, lock-free, and extremely fast

Concurrency

Not designed for concurrent use. It will intentionally panic if used concurrently. Thread-local your transactional state for thread safety. See this example:

use std::thread;
use std::cell::RefCell;
use transactional::prelude::*;

thread_local! {
    static LOCAL_STATE: RefCell<State<i32>> = RefCell::new(State::new(0));
}

// Safe usage: each thread accesses its own instance
thread::spawn(|| {
    LOCAL_STATE.with(|state| {
        let mut state = state.borrow_mut();
        // Use state safely within this thread
    });
});

Installation

Through the transactional crate.

cargo add transactional

Or add this to your Cargo.toml:

[dependencies]
transactional = "*"

Usage

Basic example:

use transactional::prelude::*;

let mut state = State::new(10);

// Define a validation function
let validate = |prev: Option<&i32>, curr: Option<&i32>| -> Result<(), UserError> {
    match (prev, curr) {
        (Some(p), Some(c)) if *c > *p => Ok(()),
        _ => Err("Value must increase".into()),
    }
};

// This will succeed because 20 > 10
let result = state.transact(Some(20)).commit_if_ok(validate);
assert!(result.is_ok());

// This would fail because 5 < 20
let result = state.transact(Some(5)).commit_if_ok(validate);
assert!(result.is_err());

// This will bypass checks
state.transact(Some(3)).commit();
assert_eq!(state.get(), Some(&3));

Requirements

  • Rust 2024 edition

Development

To contribute to this project:

  1. Clone the repository
  2. Install dependencies with cargo build
  3. Run tests with cargo test

The Makefile has all the relevant engneering actions as targets.

License

This project is licensed under the GNU Lesser General Public License v2.1 (LGPL-2.1). See the LICENSE file for details.

Contributing

Contributions are welcome. Feel free to submit a Pull Request.

Dependencies

~220–660KB
~15K SLoC