lfrlock 0.2.2

A Lock-Free Read Lock where reads never block and writes are serialized using Mutex
Documentation
# LfrLock: 无锁读取锁 (Lock-Free Read Lock)


[![Crates.io](https://img.shields.io/crates/v/lfrlock)](https://crates.io/crates/lfrlock)
[![Documentation](https://docs.rs/lfrlock/badge.svg)](https://docs.rs/lfrlock)
[![License](https://img.shields.io/crates/l/lfrlock)](LICENSE-MIT)

一个高性能的无锁读取锁实现,读取操作永不阻塞,写入操作通过 Mutex 进行串行化。

[中文文档](README_CN.md) | [English](README.md)

> **注意**:若需要 SWMR (单写多读) 特化版本,请直接使用 [smr-swap]https://github.com/ShaoG-R/smr-swap
## 特性


- **无锁读取**: 读取操作是无等待(wait-free)的且永不阻塞,确保低延迟。
- **串行化写入**: 写入操作使用 `Mutex` 串行化,防止数据竞争。
- **统一接口**: 通过单一的 `LfrLock<T>` 类型同时支持读写操作,类似于 `std::sync::Mutex`- **使用简便**: 提供 `WriteGuard` 用于习惯的可变访问,在 drop 时自动提交更改。
- **安全并发**: 基于 `smr-swap` 构建,确保安全的内存回收和并发访问。

## 快速开始


### 安装


在你的 `Cargo.toml` 中添加:

```toml
[dependencies]
lfrlock = "0.2"
```

### 基本用法


```rust
use lfrlock::LfrLock;
use std::thread;

#[derive(Debug, Clone)]

struct Data {
    value: i32,
}

fn main() {
    // 创建一个新的 LfrLock
    let lock = LfrLock::new(Data { value: 0 });

    let lock_clone = lock.clone();
    let handle = thread::spawn(move || {
        // 读取数据(永不阻塞)
        let data = lock_clone.read();
        println!("Reader sees: {}", data.value);
    });

    // 使用 WriteGuard 写入数据(串行化)
    {
        let mut guard = lock.write();
        guard.value = 42;
    } // drop 时自动提交

    handle.join().unwrap();
    
    let data = lock.read();
    println!("Final value: {}", data.value);
}
```

### 共享访问 (多线程)


由于 `LfrLock` 不是 `Sync` 的(它包含线程本地读取者),因此无法通过 `Arc<LfrLock>` 共享。请从锁实例获取 `LfrLockFactory`(或直接创建一个),它是 `Sync` 和 `Clone` 的。

```rust
use lfrlock::LfrLock;
use std::sync::Arc;
use std::thread;

fn main() {
    // 在主线程创建锁
    let lock = LfrLock::new(0);
    
    // 创建用于共享的工厂 (Sync + Clone)
    let factory = lock.factory();
    let factory = Arc::new(factory);

    let mut handles = vec![];

    for i in 0..4 {
        let factory = factory.clone();
        handles.push(thread::spawn(move || {
            // 创建线程本地的锁实例
            let lock = factory.create();
            let val = lock.read();
            println!("Thread {} sees: {}", i, *val);
        }));
    }

    // 主线程仍然可以使用 'lock'
    lock.store(1);

    for h in handles {
        h.join().unwrap();
    }
}
```

## API 概览


### `LfrLock<T>`


结合了读取者和写入者功能的主类型。

#### 创建


- **`new(initial: T)`**: 创建一个带有初始值的新锁。
- **`From<T>`**: 支持 `LfrLock::from(value)``value.into()`- **`Default`**: 当 `T: Default` 时,支持 `LfrLock::default()`
#### 读取操作


- **`read() -> ReadGuard<T>`**: 获取无锁读取守卫。永不阻塞。
- **`get() -> T`**: 克隆并返回当前值。需要 `T: Clone`- **`map<F, U>(f: F) -> U`**: 对当前值应用闭包并返回转换结果。
- **`filter<F>(f: F) -> Option<ReadGuard<T>>`**: 条件读取,闭包返回 `true` 时返回 `Some(guard)`- **`factory() -> LfrLockFactory<T>`**: 创建一个在线程间共享锁的工厂。

#### 写入操作


- **`store(new_value: T)`**: 直接替换当前值。
- **`swap(new_value: T) -> T`**: 原子交换并返回旧值。需要 `T: Clone`- **`update<F>(f: F)`**: 使用闭包 `FnOnce(&T) -> T` 更新数据。
- **`update_and_fetch<F>(f: F) -> ReadGuard<T>`**: 更新并返回新值的守卫。
- **`fetch_and_update<F>(f: F) -> ReadGuard<T>`**: 返回旧值的守卫并更新。
- **`write() -> WriteGuard<T>`**: 获取写入锁并返回可变访问的守卫。需要 `T: Clone`- **`try_write() -> Option<WriteGuard<T>>`**: 尝试获取写入锁。

### `LfrLockFactory<T>`


用于创建 `LfrLock` 实例的工厂。`Sync` 且 `Clone`,适合跨线程共享。

- **`new(initial: T)`**: 创建一个带有初始值的新工厂。
- **`create() -> LfrLock<T>`**: 为当前线程创建一个新的 `LfrLock` 句柄。

### `WriteGuard<T>`


提供对数据的可变访问。

- **自动提交**: 当守卫被 drop 时,修改后的数据会被原子地换入。
- **Deref/DerefMut**: 透明地访问底层数据。

## 实现细节


`LfrLock` 内部使用 `smr-swap` 来管理状态。它将 `Swapper` 包裹在 `Mutex` 中以串行化写入,而 `SwapReader` 允许并发、无锁的读取。这种设计非常适合读多写少的场景,确保写入安全且原子化。

## 性能特性


在 Intel(R) Core(TM) i9-13900KS CPU @ 3.20GHz 上对比 `LfrLock`、`ArcSwap` 和 `std::sync::Mutex` 的基准测试结果。

### 基准测试摘要


| 场景 | LfrLock | ArcSwap | Mutex | 备注 |
|----------|---------|---------|-------|-------|
| **只读 (单线程)** | **0.75 ns** | 9.33 ns | 8.48 ns | **快约 12.4 倍** |
| **读密集 (并发)** (1:1000) | **180 µs** | 236 µs | 1.89 ms | 比 Mutex **快约 10.5 倍** |
| **读密集 (并发)** (1:100) | **179 µs** | 267 µs | 1.94 ms | 比 ArcSwap **快约 1.5 倍** |
| **读密集 (并发)** (1:10) | **220 µs** | 574 µs | 2.08 ms | 比 ArcSwap **快约 2.6 倍** |
| **写密集 (并发)** (16R:4W) | 1.31 ms | 3.20 ms | **1.27 ms** | Mutex 略快 |
| **写密集 (并发)** (8R:4W) | 1.14 ms | 3.05 ms | **0.94 ms** | Mutex 快约 18% |
| **写密集 (并发)** (4R:4W) | 1.15 ms | 2.96 ms | **0.76 ms** | Mutex 快约 34% |
| **创建 (new)** | 236 ns | 909 ns | **0.19 ns** | Mutex 极快 |
| **克隆 (clone)** | 80 ns | **8.75 ns** | **8.80 ns** | LfrLock 克隆开销较大 |

### 分析


- **读取性能**: `LfrLock` 提供无等待读取,延迟仅为纳秒级 (0.75ns),显著优于 `ArcSwap``Mutex` (~9ns)。
- **高并发读取**: 在混合负载(1:1000 到 1:10 写入比)中,`LfrLock` 保持稳定的性能 (~180-220µs),而 `ArcSwap` 在高写入率下性能显著下降 (至 ~574µs)。
- **写密集**: 在纯写密集场景中,`Mutex` 更快 (~18-34%),因为 `LfrLock` 涉及 RCU 类操作。`ArcSwap` 则明显较慢。
- **开销**: `LfrLock` 的克隆开销 (~94ns) 高于 `Arc` 克隆 (~9ns),因为它需要注册新的 epoch 读取者。但在创建方面,它比 `ArcSwap` 快约 3.2 倍。

## 许可证


本项目采用以下任一许可证授权:

 * Apache License, Version 2.0, ([LICENSE-APACHE]LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
 * MIT license ([LICENSE-MIT]LICENSE-MIT or http://opensource.org/licenses/MIT)

由你选择。