prism3_concurrent/
lock.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025.
4 *    3-Prism Co. Ltd.
5 *
6 *    All rights reserved.
7 *
8 ******************************************************************************/
9//! # Lock Wrappers
10//!
11//! Provides wrapper functionality for synchronous and asynchronous locks,
12//! for safely accessing shared data in both synchronous and asynchronous environments.
13//!
14//! # Author
15//!
16//! Haixing Hu
17
18use std::sync::{Arc, Mutex, RwLock};
19use tokio::sync::{Mutex as AsyncMutex, RwLock as AsyncRwLock};
20
21/// Synchronous Mutex Wrapper
22///
23/// Provides an encapsulation of synchronous mutex for protecting shared data
24/// in synchronous environments. Supports safe access and modification of shared
25/// data across multiple threads.
26///
27/// # Features
28///
29/// - Synchronously acquires locks, may block threads
30/// - Supports trying to acquire locks (non-blocking)
31/// - Thread-safe, supports multi-threaded sharing
32/// - Automatic lock management through RAII ensures proper lock release
33///
34/// # Usage Example
35///
36/// ```rust,ignore
37/// use prism3_concurrent::ArcMutex;
38/// use std::sync::Arc;
39///
40/// let counter = ArcMutex::new(0);
41/// let counter = Arc::new(counter);
42///
43/// // Synchronously modify data
44/// counter.with_lock(|c| {
45///     *c += 1;
46///     println!("Counter: {}", *c);
47/// });
48///
49/// // Try to acquire lock
50/// if let Some(value) = counter.try_with_lock(|c| *c) {
51///     println!("Current value: {}", value);
52/// }
53/// ```
54///
55/// # Author
56///
57/// Haixing Hu
58///
59pub struct ArcMutex<T> {
60    inner: Arc<Mutex<T>>,
61}
62
63impl<T> ArcMutex<T> {
64    /// Creates a new synchronous mutex lock
65    ///
66    /// # Arguments
67    ///
68    /// * `data` - The data to be protected
69    ///
70    /// # Returns
71    ///
72    /// Returns a new `ArcMutex` instance
73    ///
74    /// # Example
75    ///
76    /// ```rust,ignore
77    /// use prism3_concurrent::ArcMutex;
78    ///
79    /// let lock = ArcMutex::new(42);
80    /// ```
81    pub fn new(data: T) -> Self {
82        Self {
83            inner: Arc::new(Mutex::new(data)),
84        }
85    }
86
87    /// Acquires the lock and executes an operation
88    ///
89    /// Synchronously acquires the lock, executes the provided closure, and then
90    /// automatically releases the lock. This is the recommended usage pattern as it
91    /// ensures proper lock release.
92    ///
93    /// # Arguments
94    ///
95    /// * `f` - The closure to be executed while holding the lock
96    ///
97    /// # Returns
98    ///
99    /// Returns the result of executing the closure
100    ///
101    /// # Example
102    ///
103    /// ```rust,ignore
104    /// use prism3_concurrent::ArcMutex;
105    ///
106    /// let counter = ArcMutex::new(0);
107    ///
108    /// let result = counter.with_lock(|c| {
109    ///     *c += 1;
110    ///     *c
111    /// });
112    ///
113    /// println!("Counter value: {}", result);
114    /// ```
115    pub fn with_lock<F, R>(&self, f: F) -> R
116    where
117        F: FnOnce(&mut T) -> R,
118    {
119        let mut guard = self.inner.lock().unwrap();
120        f(&mut *guard)
121    }
122
123    /// Attempts to acquire the lock
124    ///
125    /// Attempts to immediately acquire the lock. If the lock is already held by
126    /// another thread, returns `None`. This is a non-blocking operation.
127    ///
128    /// # Arguments
129    ///
130    /// * `f` - The closure to be executed while holding the lock
131    ///
132    /// # Returns
133    ///
134    /// * `Some(R)` - If the lock was successfully acquired and the closure executed
135    /// * `None` - If the lock is already held by another thread
136    ///
137    /// # Example
138    ///
139    /// ```rust,ignore
140    /// use prism3_concurrent::ArcMutex;
141    ///
142    /// let counter = ArcMutex::new(0);
143    ///
144    /// // Try to acquire lock
145    /// if let Some(value) = counter.try_with_lock(|c| *c) {
146    ///     println!("Current value: {}", value);
147    /// } else {
148    ///     println!("Lock is busy");
149    /// }
150    /// ```
151    pub fn try_with_lock<F, R>(&self, f: F) -> Option<R>
152    where
153        F: FnOnce(&mut T) -> R,
154    {
155        if let Ok(mut guard) = self.inner.try_lock() {
156            Some(f(&mut *guard))
157        } else {
158            None
159        }
160    }
161}
162
163impl<T> Clone for ArcMutex<T> {
164    /// Clones the synchronous mutex
165    ///
166    /// Creates a new `ArcMutex` instance that shares the same underlying lock
167    /// with the original instance. This allows multiple threads to hold references
168    /// to the same lock simultaneously.
169    fn clone(&self) -> Self {
170        Self {
171            inner: Arc::clone(&self.inner),
172        }
173    }
174}
175
176/// Synchronous Read-Write Lock Wrapper
177///
178/// Provides an encapsulation of synchronous read-write lock, supporting multiple
179/// read operations or a single write operation. Read operations can execute
180/// concurrently, while write operations have exclusive access.
181///
182/// # Features
183///
184/// - Supports multiple concurrent read operations
185/// - Write operations have exclusive access, mutually exclusive with read operations
186/// - Synchronously acquires locks, may block threads
187/// - Thread-safe, supports multi-threaded sharing
188/// - Automatic lock management through RAII ensures proper lock release
189///
190/// # Use Cases
191///
192/// Suitable for read-heavy scenarios such as caching, configuration management, etc.
193///
194/// # Usage Example
195///
196/// ```rust,ignore
197/// use prism3_concurrent::ArcRwLock;
198/// use std::sync::Arc;
199///
200/// let data = ArcRwLock::new(String::from("Hello"));
201/// let data = Arc::new(data);
202///
203/// // Multiple read operations can execute concurrently
204/// data.with_read_lock(|s| {
205///     println!("Read: {}", s);
206/// });
207///
208/// // Write operations have exclusive access
209/// data.with_write_lock(|s| {
210///     s.push_str(" World!");
211///     println!("Write: {}", s);
212/// });
213/// ```
214///
215/// # Author
216///
217/// Haixing Hu
218///
219pub struct ArcRwLock<T> {
220    inner: Arc<RwLock<T>>,
221}
222
223impl<T> ArcRwLock<T> {
224    /// Creates a new synchronous read-write lock
225    ///
226    /// # Arguments
227    ///
228    /// * `data` - The data to be protected
229    ///
230    /// # Returns
231    ///
232    /// Returns a new `ArcRwLock` instance
233    ///
234    /// # Example
235    ///
236    /// ```rust,ignore
237    /// use prism3_concurrent::ArcRwLock;
238    ///
239    /// let rw_lock = ArcRwLock::new(vec![1, 2, 3]);
240    /// ```
241    pub fn new(data: T) -> Self {
242        Self {
243            inner: Arc::new(RwLock::new(data)),
244        }
245    }
246
247    /// Acquires the read lock and executes an operation
248    ///
249    /// Synchronously acquires the read lock, executes the provided closure, and then
250    /// automatically releases the lock. Multiple read operations can execute concurrently.
251    ///
252    /// # Arguments
253    ///
254    /// * `f` - The closure to be executed while holding the read lock, can only read data
255    ///
256    /// # Returns
257    ///
258    /// Returns the result of executing the closure
259    ///
260    /// # Example
261    ///
262    /// ```rust,ignore
263    /// use prism3_concurrent::ArcRwLock;
264    ///
265    /// let data = ArcRwLock::new(vec![1, 2, 3]);
266    ///
267    /// let length = data.with_read_lock(|v| v.len());
268    /// println!("Vector length: {}", length);
269    /// ```
270    pub fn with_read_lock<F, R>(&self, f: F) -> R
271    where
272        F: FnOnce(&T) -> R,
273    {
274        let guard = self.inner.read().unwrap();
275        f(&*guard)
276    }
277
278    /// Acquires the write lock and executes an operation
279    ///
280    /// Synchronously acquires the write lock, executes the provided closure, and then
281    /// automatically releases the lock. Write operations have exclusive access, mutually
282    /// exclusive with read operations.
283    ///
284    /// # Arguments
285    ///
286    /// * `f` - The closure to be executed while holding the write lock, can modify data
287    ///
288    /// # Returns
289    ///
290    /// Returns the result of executing the closure
291    ///
292    /// # Example
293    ///
294    /// ```rust,ignore
295    /// use prism3_concurrent::ArcRwLock;
296    ///
297    /// let data = ArcRwLock::new(vec![1, 2, 3]);
298    ///
299    /// data.with_write_lock(|v| {
300    ///     v.push(4);
301    ///     println!("Added element, new length: {}", v.len());
302    /// });
303    /// ```
304    pub fn with_write_lock<F, R>(&self, f: F) -> R
305    where
306        F: FnOnce(&mut T) -> R,
307    {
308        let mut guard = self.inner.write().unwrap();
309        f(&mut *guard)
310    }
311}
312
313impl<T> Clone for ArcRwLock<T> {
314    /// Clones the synchronous read-write lock
315    ///
316    /// Creates a new `ArcRwLock` instance that shares the same underlying lock
317    /// with the original instance. This allows multiple threads to hold references
318    /// to the same lock simultaneously.
319    fn clone(&self) -> Self {
320        Self {
321            inner: Arc::clone(&self.inner),
322        }
323    }
324}
325
326/// Asynchronous Mutex Wrapper
327///
328/// Provides an encapsulation of asynchronous mutex for protecting shared data
329/// in asynchronous environments. Supports safe access and modification of shared
330/// data across multiple asynchronous tasks.
331///
332/// # Features
333///
334/// - Asynchronously acquires locks, does not block threads
335/// - Supports trying to acquire locks (non-blocking)
336/// - Thread-safe, supports multi-threaded sharing
337/// - Automatic lock management through RAII ensures proper lock release
338///
339/// # Usage Example
340///
341/// ```rust,ignore
342/// use prism3_concurrent::ArcAsyncMutex;
343/// use std::sync::Arc;
344///
345/// #[tokio::main]
346/// async fn main() {
347///     let counter = ArcAsyncMutex::new(0);
348///     let counter = Arc::new(counter);
349///
350///     // Asynchronously modify data
351///     counter.with_lock(|c| {
352///         *c += 1;
353///         println!("Counter: {}", *c);
354///     }).await;
355///
356///     // Try to acquire lock
357///     if let Some(value) = counter.try_with_lock(|c| *c) {
358///         println!("Current value: {}", value);
359///     }
360/// }
361/// ```
362///
363/// # Author
364///
365/// Haixing Hu
366///
367pub struct ArcAsyncMutex<T> {
368    inner: Arc<AsyncMutex<T>>,
369}
370
371impl<T> ArcAsyncMutex<T> {
372    /// Creates a new asynchronous mutex lock
373    ///
374    /// # Arguments
375    ///
376    /// * `data` - The data to be protected
377    ///
378    /// # Returns
379    ///
380    /// Returns a new `ArcAsyncMutex` instance
381    ///
382    /// # Example
383    ///
384    /// ```rust,ignore
385    /// use prism3_concurrent::ArcAsyncMutex;
386    ///
387    /// let lock = ArcAsyncMutex::new(42);
388    /// ```
389    pub fn new(data: T) -> Self {
390        Self {
391            inner: Arc::new(AsyncMutex::new(data)),
392        }
393    }
394
395    /// Acquires the lock and executes an operation
396    ///
397    /// Asynchronously acquires the lock, executes the provided closure, and then
398    /// automatically releases the lock. This is the recommended usage pattern as it
399    /// ensures proper lock release.
400    ///
401    /// # Arguments
402    ///
403    /// * `f` - The closure to be executed while holding the lock
404    ///
405    /// # Returns
406    ///
407    /// Returns the result of executing the closure
408    ///
409    /// # Example
410    ///
411    /// ```rust,ignore
412    /// use prism3_concurrent::ArcAsyncMutex;
413    ///
414    /// #[tokio::main]
415    /// async fn main() {
416    ///     let counter = ArcAsyncMutex::new(0);
417    ///
418    ///     let result = counter.with_lock(|c| {
419    ///         *c += 1;
420    ///         *c
421    ///     }).await;
422    ///
423    ///     println!("Counter value: {}", result);
424    /// }
425    /// ```
426    pub async fn with_lock<F, R>(&self, f: F) -> R
427    where
428        F: FnOnce(&mut T) -> R,
429    {
430        let mut guard = self.inner.lock().await;
431        f(&mut *guard)
432    }
433
434    /// Attempts to acquire the lock
435    ///
436    /// Attempts to immediately acquire the lock. If the lock is already held by
437    /// another task, returns `None`. This is a non-blocking operation.
438    ///
439    /// # Arguments
440    ///
441    /// * `f` - The closure to be executed while holding the lock
442    ///
443    /// # Returns
444    ///
445    /// * `Some(R)` - If the lock was successfully acquired and the closure executed
446    /// * `None` - If the lock is already held by another task
447    ///
448    /// # Example
449    ///
450    /// ```rust,ignore
451    /// use prism3_concurrent::ArcAsyncMutex;
452    ///
453    /// let counter = ArcAsyncMutex::new(0);
454    ///
455    /// // Try to acquire lock
456    /// if let Some(value) = counter.try_with_lock(|c| *c) {
457    ///     println!("Current value: {}", value);
458    /// } else {
459    ///     println!("Lock is busy");
460    /// }
461    /// ```
462    pub fn try_with_lock<F, R>(&self, f: F) -> Option<R>
463    where
464        F: FnOnce(&mut T) -> R,
465    {
466        if let Ok(mut guard) = self.inner.try_lock() {
467            Some(f(&mut *guard))
468        } else {
469            None
470        }
471    }
472}
473
474impl<T> Clone for ArcAsyncMutex<T> {
475    /// Clones the asynchronous mutex
476    ///
477    /// Creates a new `ArcAsyncMutex` instance that shares the same underlying lock
478    /// with the original instance. This allows multiple tasks to hold references
479    /// to the same lock simultaneously.
480    fn clone(&self) -> Self {
481        Self {
482            inner: Arc::clone(&self.inner),
483        }
484    }
485}
486
487/// Asynchronous Read-Write Lock Wrapper
488///
489/// Provides an encapsulation of asynchronous read-write lock, supporting multiple
490/// read operations or a single write operation. Read operations can execute
491/// concurrently, while write operations have exclusive access.
492///
493/// # Features
494///
495/// - Supports multiple concurrent read operations
496/// - Write operations have exclusive access, mutually exclusive with read operations
497/// - Asynchronously acquires locks, does not block threads
498/// - Thread-safe, supports multi-threaded sharing
499/// - Automatic lock management through RAII ensures proper lock release
500///
501/// # Use Cases
502///
503/// Suitable for read-heavy scenarios such as caching, configuration management, etc.
504///
505/// # Usage Example
506///
507/// ```rust,ignore
508/// use prism3_concurrent::ArcAsyncRwLock;
509/// use std::sync::Arc;
510///
511/// #[tokio::main]
512/// async fn main() {
513///     let data = ArcAsyncRwLock::new(String::from("Hello"));
514///     let data = Arc::new(data);
515///
516///     // Multiple read operations can execute concurrently
517///     data.with_read_lock(|s| {
518///         println!("Read: {}", s);
519///     }).await;
520///
521///     // Write operations have exclusive access
522///     data.with_write_lock(|s| {
523///         s.push_str(" World!");
524///         println!("Write: {}", s);
525///     }).await;
526/// }
527/// ```
528///
529/// # Author
530///
531/// Haixing Hu
532///
533pub struct ArcAsyncRwLock<T> {
534    inner: Arc<AsyncRwLock<T>>,
535}
536
537impl<T> ArcAsyncRwLock<T> {
538    /// Creates a new asynchronous read-write lock
539    ///
540    /// # Arguments
541    ///
542    /// * `data` - The data to be protected
543    ///
544    /// # Returns
545    ///
546    /// Returns a new `ArcAsyncRwLock` instance
547    ///
548    /// # Example
549    ///
550    /// ```rust,ignore
551    /// use prism3_concurrent::ArcAsyncRwLock;
552    ///
553    /// let rw_lock = ArcAsyncRwLock::new(vec![1, 2, 3]);
554    /// ```
555    pub fn new(data: T) -> Self {
556        Self {
557            inner: Arc::new(AsyncRwLock::new(data)),
558        }
559    }
560
561    /// Acquires the read lock and executes an operation
562    ///
563    /// Asynchronously acquires the read lock, executes the provided closure, and then
564    /// automatically releases the lock. Multiple read operations can execute concurrently.
565    ///
566    /// # Arguments
567    ///
568    /// * `f` - The closure to be executed while holding the read lock, can only read data
569    ///
570    /// # Returns
571    ///
572    /// Returns the result of executing the closure
573    ///
574    /// # Example
575    ///
576    /// ```rust,ignore
577    /// use prism3_concurrent::ArcAsyncRwLock;
578    ///
579    /// #[tokio::main]
580    /// async fn main() {
581    ///     let data = ArcAsyncRwLock::new(vec![1, 2, 3]);
582    ///
583    ///     let length = data.with_read_lock(|v| v.len()).await;
584    ///     println!("Vector length: {}", length);
585    /// }
586    /// ```
587    pub async fn with_read_lock<F, R>(&self, f: F) -> R
588    where
589        F: FnOnce(&T) -> R,
590    {
591        let guard = self.inner.read().await;
592        f(&*guard)
593    }
594
595    /// Acquires the write lock and executes an operation
596    ///
597    /// Asynchronously acquires the write lock, executes the provided closure, and then
598    /// automatically releases the lock. Write operations have exclusive access, mutually
599    /// exclusive with read operations.
600    ///
601    /// # Arguments
602    ///
603    /// * `f` - The closure to be executed while holding the write lock, can modify data
604    ///
605    /// # Returns
606    ///
607    /// Returns the result of executing the closure
608    ///
609    /// # Example
610    ///
611    /// ```rust,ignore
612    /// use prism3_concurrent::ArcAsyncRwLock;
613    ///
614    /// #[tokio::main]
615    /// async fn main() {
616    ///     let data = ArcAsyncRwLock::new(vec![1, 2, 3]);
617    ///
618    ///     data.with_write_lock(|v| {
619    ///         v.push(4);
620    ///         println!("Added element, new length: {}", v.len());
621    ///     }).await;
622    /// }
623    /// ```
624    pub async fn with_write_lock<F, R>(&self, f: F) -> R
625    where
626        F: FnOnce(&mut T) -> R,
627    {
628        let mut guard = self.inner.write().await;
629        f(&mut *guard)
630    }
631}
632
633impl<T> Clone for ArcAsyncRwLock<T> {
634    /// Clones the asynchronous read-write lock
635    ///
636    /// Creates a new `ArcAsyncRwLock` instance that shares the same underlying lock
637    /// with the original instance. This allows multiple tasks to hold references
638    /// to the same lock simultaneously.
639    fn clone(&self) -> Self {
640        Self {
641            inner: Arc::clone(&self.inner),
642        }
643    }
644}