4 releases
0.1.4 | Jan 23, 2023 |
---|---|
0.1.3 | Aug 16, 2021 |
0.1.2 | Aug 16, 2021 |
0.1.1 | Aug 16, 2021 |
0.1.0 |
|
#980 in Rust patterns
52KB
330 lines
Singleton Manager
Is a management service for Singleton Services. If there is a need for a service to keep its state across multiple threads, this singleton service can pull the services from a singleton storage.
Note: Singleton Manager itself is not thread-safe, so you need to make your service threadsafe.
Usage
Say we want to use a custom struct
as our singleton:
pub struct MyService {
message: String,
guard: Mutex<()>,
}
impl MyService {
pub fn set(&mut self, msg: &str) {
let mut _guard = self.guard.lock().expect("Failed to get guard");
self.message = msg.to_string();
}
pub fn get(&self) -> String {
let _guard = self.guard.lock();
self.message.clone()
}
}
Using object instance
if this is our service and we would now want to store it as a singleton, we can do this simply by:
SingletonManager::instance().set(
"my_service",
"MyService",
None,
Some(MyService {
message: "".to_string(),
guard: Mutex::new(()),
}),
)
.ok();
this will set the service and is now retrivable by using:
let service = SingletonManager::instance()
.get::<MyService>("my_service")
.expect("Failed to get service");
service.set("My Message");
let different_service = SingletonManager::instance()
.get::<MyService>("my_service")
.expect("Failed to get service");
assert_eq!("My Message".to_string(), different_service.get());
Full example
pub struct MyService {
message: String,
guard: Mutex<()>,
}
impl MyService {
pub fn set(&mut self, msg: &str) {
let mut _guard = self.guard.lock().expect("Failed to get guard");
self.message = msg.to_string();
}
pub fn get(&self) -> String {
let _guard = self.guard.lock();
self.message.clone()
}
}
fn main() {
SingletonManager::instance().set(
"my_service",
"MyService",
None,
Some(MyService {
message: "".to_string(),
guard: Mutex::new(()),
}),
)
.ok();
let service = SingletonManager::instance()
.get::<MyService>("my_service")
.expect("Failed to get service");
service.set("My Message");
let different_service = SingletonManager::instance()
.get::<MyService>("my_service")
.expect("Failed to get service");
assert_eq!("My Message".to_string(), different_service.get());
}
Using factory instance
It's possible to instantiate only on request by using a factory to create the service
SingletonManager::instance()
.set_factory(
"my_service_factory",
Box::new(|| {
Box::new(MyService {
message: "".to_string(),
guard: Mutex::new(()),
})
}),
)
.ok();
this will set the service and is now retrivable by using:
fn main() {
set_service();
let service = SingletonManager::instance()
.get::<MyService>("my_service_factory")
.expect("Failed to get service");
service.set("My Message");
let different_service = SingletonManager::instance()
.get::<MyService>("my_service_factory")
.expect("Failed to get service");
assert_eq!("My Message".to_string(), different_service.get());
}
Full Example
pub struct MyService {
message: String,
guard: Mutex<()>,
}
impl MyService {
pub fn set(&mut self, msg: &str) {
let mut _guard = self.guard.lock().expect("Failed to get guard");
self.message = msg.to_string();
}
pub fn get(&self) -> String {
let _guard = self.guard.lock();
self.message.clone()
}
}
fn main() {
SingletonManager::instance()
.set_factory(
"my_service_factory",
Box::new(|| {
Box::new(MyService {
message: "".to_string(),
guard: Mutex::new(()),
})
}),
)
.ok();
let service = SingletonManager::instance()
.get::<MyService>("my_service_factory")
.unwrap();
service.set("My Message");
let different_service = SingletonManager::instance()
.get::<MyService>("my_service_factory")
.unwrap();
assert_eq!("My Message".to_string(), different_service.get());
}
Contributions/Issues
Contributions are currently not opened as this is running from a private server. Issues can be opened at any time with a guest account on gitlab.nebula.technology.
Dependencies
~225KB