Singleton Design Pattern
The Singleton pattern ensures that a class has only one instance and provides a global point of access to it. This is useful when exactly one object is needed to coordinate actions across the system.
use std::sync::{Arc, Mutex}; use std::thread; struct Singleton { data: i32, } impl Singleton { fn new() -> Self { Singleton { data: 0 } } fn get_instance() -> Arc<Mutex<Singleton>> { static mut SINGLETON: Option<Arc<Mutex<Singleton>>> = None; static ONCE: std::sync::Once = std::sync::Once::new(); unsafe { ONCE.call_once(|| { let singleton = Singleton::new(); SINGLETON = Some(Arc::new(Mutex::new(singleton))); }); SINGLETON.clone().unwrap() } } fn increment(&mut self) { self.data += 1; } fn get_data(&self) -> i32 { self.data } } fn main() { let singleton = Singleton::get_instance(); // Acquire the lock in the main thread { let mut instance = singleton.lock().unwrap(); instance.increment(); println!("Main thread data: {}", instance.get_data()); } // The lock is released here when `instance` goes out of scope let singleton_clone1 = Arc::clone(&singleton); let singleton_clone2 = Arc::clone(&singleton); let handle1 = thread::spawn(move || { let mut instance1 = singleton_clone1.lock().unwrap(); instance1.increment(); println!("Thread 1 data: {}", instance1.get_data()); }); let handle2 = thread::spawn(move || { let mut instance2 = singleton_clone2.lock().unwrap(); instance2.increment(); println!("Thread 2 data: {}", instance2.get_data()); }); handle1.join().unwrap(); handle2.join().unwrap(); // Acquire the lock again in the main thread { let instance = singleton.lock().unwrap(); println!("Final data: {}", instance.get_data()); } }
- Singleton Struct: Defines the structure of the singleton with a single field
value
. - new() Method: Creates a new instance of the singleton wrapped in
Arc
andMutex
for thread safety. - get_instance() Method: Provides a global point of access to the singleton instance. It uses
std::sync::Once
to ensure that the instance is only created once. - set_value() and get_value() Methods: Allow modification and retrieval of the singleton's value.
- main() Function: Demonstrates the usage of the singleton in a multi-threaded context.
This example ensures that only one instance of Singleton
is created and shared across threads safely.