smr_swap/lib.rs
1#![cfg_attr(not(feature = "std"), no_std)]
2
3//! A minimal locking, version-based concurrent swap library.
4//!
5//! This library provides a mechanism to swap values atomically while allowing concurrent readers
6//! to access the old value until they are done. It uses `swmr-cell` for version-based garbage collection.
7//!
8//! # Example
9//!
10//! ```rust
11//! use smr_swap::SmrSwap;
12//! use std::thread;
13//!
14//! let mut swap = SmrSwap::new(0);
15//!
16//! // Get a thread-local reader
17//! let local = swap.local();
18//!
19//! // Writer stores a new value
20//! swap.store(1);
21//!
22//! // Read in another thread
23//! let local2 = swap.local();
24//! let handle = thread::spawn(move || {
25//! let guard = local2.load();
26//! assert_eq!(*guard, 1);
27//! });
28//!
29//! handle.join().unwrap();
30//! ```
31
32use core::fmt;
33use core::ops::Deref;
34use swmr_cell::SwmrCell;
35
36// Re-export for backward compatibility
37pub use swmr_cell::{LocalReader as CellLocalReader, PinGuard, SwmrReader as CellSwmrReader};
38
39/// Main entry point for the SMR swap library.
40///
41/// A single-writer, multi-reader swap container with version-based garbage collection.
42///
43/// SMR swap 库的主入口点。
44///
45/// 单写多读的交换容器,带有基于版本的垃圾回收。
46pub struct SmrSwap<T: 'static> {
47 cell: SwmrCell<T>,
48 local: LocalReader<T>,
49}
50
51/// A handle for creating `LocalReader`s that can be shared across threads.
52///
53/// Unlike `LocalReader`, which is `!Sync` and bound to a single thread,
54/// `SmrReader` is `Sync` and `Clone`. It acts as a factory for `LocalReader`s.
55///
56/// 可以跨线程共享的用于创建 `LocalReader` 的句柄。
57///
58/// 与 `!Sync` 且绑定到单个线程的 `LocalReader` 不同,
59/// `SmrReader` 是 `Sync` 和 `Clone` 的。它充当 `LocalReader` 的工厂。
60pub struct SmrReader<T: 'static> {
61 inner: CellSwmrReader<T>,
62}
63
64impl<T: 'static> SmrReader<T> {
65 /// Create a new `LocalReader` for the current thread.
66 ///
67 /// 为当前线程创建一个新的 `LocalReader`。
68 #[inline]
69 pub fn local(&self) -> LocalReader<T> {
70 LocalReader {
71 inner: self.inner.local(),
72 }
73 }
74}
75
76impl<T: 'static> Clone for SmrReader<T> {
77 #[inline]
78 fn clone(&self) -> Self {
79 Self {
80 inner: self.inner.clone(),
81 }
82 }
83}
84
85impl<T: 'static> fmt::Debug for SmrReader<T> {
86 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87 f.debug_struct("SmrReader").finish()
88 }
89}
90
91/// Thread-local reader handle, not Sync.
92///
93/// Each thread should create its own `LocalReader` via `SmrSwap::local()` and reuse it.
94/// `LocalReader` is `!Sync` and should not be shared between threads.
95///
96/// 线程本地的读取句柄,不是 Sync。
97///
98/// 每个线程应该通过 `SmrSwap::local()` 创建自己的 `LocalReader` 并重复使用。
99/// `LocalReader` 是 `!Sync` 的,不应在线程之间共享。
100pub struct LocalReader<T: 'static> {
101 inner: CellLocalReader<T>,
102}
103
104/// RAII guard for reading values.
105///
106/// Dereference to access the value. The value is protected until the guard is dropped.
107///
108/// 用于读取值的 RAII 守卫。
109///
110/// 解引用以访问值。在守卫被 drop 之前,值是受保护的。
111pub struct ReadGuard<'a, T: 'static> {
112 inner: PinGuard<'a, T>,
113}
114
115impl<'a, T> Deref for ReadGuard<'a, T> {
116 type Target = T;
117
118 #[inline(always)]
119 fn deref(&self) -> &T {
120 &*self.inner
121 }
122}
123
124impl<'a, T> Clone for ReadGuard<'a, T> {
125 #[inline]
126 fn clone(&self) -> Self {
127 ReadGuard {
128 inner: self.inner.clone(),
129 }
130 }
131}
132
133// ============================================================================
134// SmrSwap implementation
135// ============================================================================
136
137impl<T: 'static> SmrSwap<T> {
138 /// Create a new SMR container with the given initial value.
139 ///
140 /// 使用给定的初始值创建新的 SMR 容器。
141 #[inline]
142 pub fn new(initial: T) -> Self {
143 let cell = SwmrCell::builder()
144 .auto_reclaim_threshold(Some(4))
145 .build(initial);
146 let local = LocalReader {
147 inner: cell.local(),
148 };
149 Self { cell, local }
150 }
151
152 /// Create a new thread-local reader for this container.
153 ///
154 /// Each thread should create its own `LocalReader` and reuse it.
155 /// The `LocalReader` is `Send` but not `Sync`.
156 ///
157 /// 为此容器创建一个新的线程本地读取者。
158 ///
159 /// 每个线程应该创建自己的 `LocalReader` 并重复使用。
160 /// `LocalReader` 是 `Send` 但不是 `Sync`。
161 #[inline]
162 pub fn local(&self) -> LocalReader<T> {
163 LocalReader {
164 inner: self.cell.local(),
165 }
166 }
167
168 /// Create a new `SmrReader` that can be shared across threads.
169 ///
170 /// `SmrReader` is `Sync` + `Clone` and acts as a factory for `LocalReader`s.
171 /// This is useful for distributing reader creation capability to other threads.
172 ///
173 /// 创建一个新的 `SmrReader`,可以在线程之间共享。
174 ///
175 /// `SmrReader` 是 `Sync` + `Clone` 的,充当 `LocalReader` 的工厂。
176 /// 这对于将读者创建能力分发给其他线程很有用。
177 #[inline]
178 pub fn reader(&self) -> SmrReader<T> {
179 SmrReader {
180 inner: self.cell.reader(),
181 }
182 }
183
184 /// Store a new value, making it visible to readers.
185 ///
186 /// The old value is retired and will be garbage collected when safe.
187 ///
188 /// 存储新值,使其对读者可见。
189 ///
190 /// 旧值已退休,将在安全时被垃圾回收。
191 #[inline]
192 pub fn store(&mut self, new_value: T) {
193 self.cell.store(new_value);
194 }
195
196 /// Get a reference to the current value (writer-only, no pinning required).
197 ///
198 /// This is only accessible from the writer thread since `SmrSwap` is `!Sync`.
199 ///
200 /// 获取当前值的引用(仅写者可用,无需 pin)。
201 ///
202 /// 这只能从写者线程访问,因为 `SmrSwap` 是 `!Sync` 的。
203 #[inline]
204 pub fn get(&self) -> &T {
205 self.cell.get()
206 }
207
208 /// Update the value using a closure.
209 ///
210 /// The closure receives the current value and should return the new value.
211 /// This is equivalent to `swap.store(f(swap.get()))` but more ergonomic.
212 ///
213 /// 使用闭包更新值。
214 ///
215 /// 闭包接收当前值并应返回新值。
216 /// 这相当于 `swap.store(f(swap.get()))` 但更符合人体工程学。
217 #[inline]
218 pub fn update<F>(&mut self, f: F)
219 where
220 F: FnOnce(&T) -> T,
221 {
222 self.cell.update(f);
223 }
224
225 /// Get the current global version.
226 ///
227 /// The version is incremented each time `store()` is called.
228 ///
229 /// 获取当前全局版本。
230 ///
231 /// 每次调用 `store()` 时版本会增加。
232 #[inline]
233 pub fn version(&self) -> usize {
234 self.cell.version()
235 }
236
237 /// Get the number of retired objects waiting for garbage collection.
238 ///
239 /// 获取等待垃圾回收的已退休对象数量。
240 #[inline]
241 pub fn garbage_count(&self) -> usize {
242 self.cell.garbage_count()
243 }
244
245 /// Get a reference to the previously stored value, if any.
246 ///
247 /// Returns `None` if no previous value exists (i.e., only the initial value has been stored).
248 ///
249 /// 获取上一个存储值的引用(如果存在)。
250 ///
251 /// 如果不存在上一个值(即只存储了初始值),则返回 `None`。
252 #[inline]
253 pub fn previous(&self) -> Option<&T> {
254 self.cell.previous()
255 }
256
257 /// Manually trigger garbage collection.
258 ///
259 /// This is usually not necessary as garbage is collected automatically.
260 ///
261 /// 手动触发垃圾回收。
262 ///
263 /// 通常不需要,因为垃圾会自动回收。
264 #[inline]
265 pub fn collect(&mut self) {
266 self.cell.collect();
267 }
268
269 /// Read the current value with RAII guard.
270 ///
271 /// Returns a `ReadGuard` that can be dereferenced to access the value.
272 /// The value is protected until the guard is dropped.
273 ///
274 /// 使用 RAII 守卫读取当前值。
275 ///
276 /// 返回一个可以解引用来访问值的 `ReadGuard`。
277 /// 在守卫被 drop 之前,值是受保护的。
278 #[inline]
279 pub fn load(&self) -> ReadGuard<'_, T> {
280 self.local.load()
281 }
282
283 /// Load the current value and clone it.
284 ///
285 /// This is a convenience method equivalent to `self.load().cloned()`.
286 ///
287 /// # Example
288 ///
289 /// ```rust
290 /// use smr_swap::SmrSwap;
291 ///
292 /// let swap = SmrSwap::new(String::from("hello"));
293 ///
294 /// // Instead of: (*swap.load()).clone()
295 /// // Or: swap.load().cloned()
296 /// let value: String = swap.load_cloned();
297 /// assert_eq!(value, "hello");
298 /// ```
299 ///
300 /// 加载当前值并克隆它。
301 ///
302 /// 这是一个便捷方法,等同于 `self.load().cloned()`。
303 #[inline]
304 pub fn load_cloned(&self) -> T
305 where
306 T: Clone,
307 {
308 self.load().cloned()
309 }
310
311 /// Atomically swap the current value with a new one.
312 ///
313 /// Returns the old value.
314 ///
315 /// 原子地将当前值与新值交换。
316 ///
317 /// 返回旧的值。
318 #[inline]
319 pub fn swap(&mut self, new_value: T) -> T
320 where
321 T: Clone,
322 {
323 let old_value = self.cell.get().clone();
324 self.cell.store(new_value);
325 old_value
326 }
327
328 /// Apply a closure function to the current value and return the result.
329 ///
330 /// The closure receives a reference to the current value and returns a new value.
331 /// Returns a guard to the new value.
332 ///
333 /// 对当前值应用闭包函数并返回结果。
334 ///
335 /// 闭包接收当前值的引用,返回新值。
336 /// 返回新值的守卫。
337 #[inline]
338 pub fn update_and_fetch<F>(&mut self, f: F) -> ReadGuard<'_, T>
339 where
340 F: FnOnce(&T) -> T,
341 {
342 let new_value = f(self.cell.get());
343 self.cell.store(new_value);
344 self.local.load()
345 }
346
347 /// Apply a closure function to the current value with mutable access to both.
348 ///
349 /// The closure receives the current value and should return the new value.
350 /// Returns a guard to the old value (before update).
351 ///
352 /// 对当前值应用闭包函数,具有对两者的可变访问。
353 ///
354 /// 闭包接收当前值并应返回新值。
355 /// 返回旧值(更新前)的守卫。
356 #[inline]
357 pub fn fetch_and_update<F>(&mut self, f: F) -> ReadGuard<'_, T>
358 where
359 F: FnOnce(&T) -> T,
360 {
361 let old_guard = self.local.load();
362 let new_value = f(self.cell.get());
363 self.cell.store(new_value);
364 old_guard
365 }
366}
367
368// ============================================================================
369// LocalReader implementation
370// ============================================================================
371
372impl<T: 'static> LocalReader<T> {
373 /// Read the current value with RAII guard.
374 ///
375 /// Returns a `ReadGuard` that holds the pin and the reference.
376 /// The pin is automatically released when the guard is dropped.
377 ///
378 /// 使用 RAII 守卫读取当前值。
379 ///
380 /// 返回一个持有 pin 和引用的 `ReadGuard`。
381 /// 当守卫被 drop 时,pin 会自动释放。
382 #[inline]
383 pub fn load(&self) -> ReadGuard<'_, T> {
384 ReadGuard {
385 inner: self.inner.pin(),
386 }
387 }
388
389 /// Check if this reader is currently pinned.
390 ///
391 /// 检查此读者当前是否被 pin。
392 #[inline]
393 pub fn is_pinned(&self) -> bool {
394 self.inner.is_pinned()
395 }
396
397 /// Get the current global version.
398 ///
399 /// Note: This returns the global version, not the pinned version.
400 /// To get the pinned version, use `ReadGuard::version()`.
401 ///
402 /// 获取当前全局版本。
403 ///
404 /// 注意:这返回全局版本,而不是 pin 的版本。
405 /// 要获取 pin 的版本,请使用 `ReadGuard::version()`。
406 #[inline]
407 pub fn version(&self) -> usize {
408 self.inner.version()
409 }
410
411 /// Apply a closure function to the current value and transform the result.
412 ///
413 /// This method reads the current value, applies the closure to transform it,
414 /// and returns the transformed result.
415 ///
416 /// 对当前值应用闭包函数并转换结果。
417 ///
418 /// 这个方法读取当前值,应用闭包进行转换,并返回转换后的结果。
419 #[inline]
420 pub fn map<F, U>(&self, f: F) -> U
421 where
422 F: FnOnce(&T) -> U,
423 {
424 let guard = self.inner.pin();
425 f(&*guard)
426 }
427
428 /// Apply a closure function to the current value, returning Some if the closure returns true.
429 ///
430 /// 对当前值应用闭包函数,如果闭包返回 true 则返回 Some。
431 #[inline]
432 pub fn filter<F>(&self, f: F) -> Option<ReadGuard<'_, T>>
433 where
434 F: FnOnce(&T) -> bool,
435 {
436 let guard = self.inner.pin();
437 if f(&*guard) {
438 Some(ReadGuard { inner: guard })
439 } else {
440 None
441 }
442 }
443
444 /// Load the current value and clone it.
445 ///
446 /// This is a convenience method equivalent to `self.load().cloned()`.
447 ///
448 /// # Example
449 ///
450 /// ```rust
451 /// use smr_swap::SmrSwap;
452 ///
453 /// let swap = SmrSwap::new(String::from("hello"));
454 /// let local = swap.local();
455 ///
456 /// // Instead of: (*local.load()).clone()
457 /// // Or: local.load().cloned()
458 /// let value: String = local.load_cloned();
459 /// assert_eq!(value, "hello");
460 /// ```
461 ///
462 /// 加载当前值并克隆它。
463 ///
464 /// 这是一个便捷方法,等同于 `self.load().cloned()`。
465 #[inline]
466 pub fn load_cloned(&self) -> T
467 where
468 T: Clone,
469 {
470 self.load().cloned()
471 }
472
473 /// Create a new `SmrReader` from this `LocalReader`.
474 ///
475 /// `SmrReader` is `Sync` + `Clone` and acts as a factory for `LocalReader`s.
476 /// This is equivalent to calling `swap.reader()`, but using the `LocalReader`'s reference to the shared state.
477 ///
478 /// 从此 `LocalReader` 创建一个新的 `SmrReader`。
479 /// `SmrReader` 是 `Sync` + `Clone` 的,充当 `LocalReader` 的工厂。
480 /// 这相当于调用 `swap.reader()`,但使用 `LocalReader` 对共享状态的引用。
481 #[inline]
482 pub fn share(&self) -> SmrReader<T> {
483 SmrReader {
484 inner: self.inner.share(),
485 }
486 }
487
488 /// Convert this `LocalReader` into a `SmrReader`.
489 ///
490 /// This consumes the `LocalReader` and returns a `SmrReader`
491 /// that can be sent to another thread to create new `LocalReader`s.
492 ///
493 /// 将此 `LocalReader` 转换为 `SmrReader`。
494 /// 这会消耗 `LocalReader` 并返回一个 `SmrReader`,
495 /// 该 `SmrReader` 可以发送到另一个线程以创建新 `LocalReader`。
496 #[inline]
497 pub fn into_swmr(self) -> SmrReader<T> {
498 SmrReader {
499 inner: self.inner.into_swmr(),
500 }
501 }
502}
503
504impl<T: 'static> Clone for LocalReader<T> {
505 #[inline]
506 fn clone(&self) -> Self {
507 LocalReader {
508 inner: self.inner.clone(),
509 }
510 }
511}
512
513impl<T: 'static> fmt::Debug for LocalReader<T> {
514 #[inline]
515 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
516 f.debug_struct("LocalReader")
517 .field("is_pinned", &self.is_pinned())
518 .field("version", &self.version())
519 .finish()
520 }
521}
522
523// ============================================================================
524// ReadGuard additional implementations
525// ============================================================================
526
527impl<T: 'static> ReadGuard<'_, T> {
528 /// Get the version that this guard is pinned to.
529 ///
530 /// 获取此守卫被 pin 到的版本。
531 #[inline]
532 pub fn version(&self) -> usize {
533 self.inner.version()
534 }
535
536 /// Clone the inner value and return it.
537 ///
538 /// This is useful when you need to return the value instead of the guard.
539 ///
540 /// # Example
541 ///
542 /// ```rust
543 /// use smr_swap::SmrSwap;
544 ///
545 /// let swap = SmrSwap::new(42);
546 /// let value: i32 = swap.load().cloned();
547 /// assert_eq!(value, 42);
548 /// ```
549 ///
550 /// 克隆内部值并返回。
551 ///
552 /// 当你需要返回值而不是守卫时很有用。
553 #[inline]
554 pub fn cloned(&self) -> T
555 where
556 T: Clone,
557 {
558 self.deref().clone()
559 }
560
561 /// Convert the guard into the inner value by cloning.
562 ///
563 /// This consumes the guard and returns a clone of the inner value.
564 ///
565 /// 通过克隆将守卫转换为内部值。
566 ///
567 /// 这会消耗守卫并返回内部值的克隆。
568 #[inline]
569 pub fn into_inner(self) -> T
570 where
571 T: Clone,
572 {
573 self.deref().clone()
574 }
575}
576
577impl<T: 'static> AsRef<T> for ReadGuard<'_, T> {
578 #[inline]
579 fn as_ref(&self) -> &T {
580 self.deref()
581 }
582}
583
584impl<T: fmt::Debug + 'static> fmt::Debug for ReadGuard<'_, T> {
585 #[inline]
586 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
587 f.debug_struct("ReadGuard")
588 .field("value", &self.deref())
589 .field("version", &self.version())
590 .finish()
591 }
592}
593
594// ============================================================================
595// Standard Trait Implementations
596// 标准 trait 实现
597// ============================================================================
598
599impl<T: Default + 'static> Default for SmrSwap<T> {
600 /// Create a new SmrSwap with the default value.
601 ///
602 /// 使用默认值创建一个新的 SmrSwap。
603 #[inline]
604 fn default() -> Self {
605 Self::new(T::default())
606 }
607}
608
609impl<T: 'static> From<T> for SmrSwap<T> {
610 /// Create a new SmrSwap from a value.
611 ///
612 /// 从一个值创建一个新的 SmrSwap。
613 #[inline]
614 fn from(value: T) -> Self {
615 Self::new(value)
616 }
617}
618
619impl<T: fmt::Debug + 'static> fmt::Debug for SmrSwap<T> {
620 #[inline]
621 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
622 f.debug_struct("SmrSwap")
623 .field("value", self.get())
624 .field("version", &self.version())
625 .field("garbage_count", &self.garbage_count())
626 .finish()
627 }
628}
629
630#[cfg(test)]
631mod tests;