CODESAMPLE

Multiton - Rust

Share on:

The Multiton pattern ensures that only a specific number of instances of a class exist. It’s a relaxed version of the Singleton pattern, allowing for a limited concurrency or distribution of instances. This Rust implementation uses a static mutable vector to store the instances and a Mutex to provide thread-safe access. The instance() method retrieves an instance based on a key; if one doesn’t exist, it creates it, respecting the maximum allowed count. Rust’s ownership and borrowing rules, combined with Mutex, naturally enforce safety when dealing with shared mutable state, making this a clean and effective approach.

use std::sync::{Mutex, Once};

struct MultitonInstance {
    id: u32,
}

impl MultitonInstance {
    fn new(id: u32) -> Self {
        MultitonInstance { id }
    }

    fn print_id(&self) {
        println!("Instance ID: {}", self.id);
    }
}

struct Multiton {
    instances: Mutex<Vec<MultitonInstance>>,
    max_instances: u32,
    next_id: Mutex<u32>,
    init: Once,
}

impl Multiton {
    fn new(max_instances: u32) -> Self {
        Multiton {
            instances: Mutex::new(Vec::new()),
            max_instances,
            next_id: Mutex::new(0),
            init: Once::new(),
        }
    }

    fn instance(&self, id: u32) -> Result<MultitonInstance, String> {
        self.init.call_once(|| {
            // Initialization logic can go here if needed.
        });

        let mut instances = self.instances.lock().unwrap();
        let mut next_id = self.next_id.lock().unwrap();

        if instances.len() < self.max_instances as usize {
            if *next_id < self.max_instances {
                let new_instance = MultitonInstance::new(*next_id);
                instances.push(new_instance);
                *next_id += 1;
                Ok(instances.iter().find(|i| i.id == *next_id -1).unwrap().clone())
            } else {
                Err("Maximum instances reached".to_string())
            }
        } else {
           
            if instances.iter().any(|i| i.id == id) {
                Ok(instances.iter().find(|i| i.id == id).unwrap().clone()) 
            } else {
                Err("Maximum instances reached".to_string())
            }
        }
    }
}

fn main() {
    let multiton = Multiton::new(3);

    match multiton.instance(0) {
        Ok(instance) => instance.print_id(),
        Err(e) => println!("{}", e),
    }
    match multiton.instance(1) {
        Ok(instance) => instance.print_id(),
        Err(e) => println!("{}", e),
    }
    match multiton.instance(2) {
        Ok(instance) => instance.print_id(),
        Err(e) => println!("{}", e),
    }
    match multiton.instance(3) {
        Ok(instance) => instance.print_id(),
        Err(e) => println!("{}", e),
    }
    match multiton.instance(0) {
        Ok(instance) => instance.print_id(),
        Err(e) => println!("{}", e),
    }
}