LoginSignup
13
5

More than 5 years have passed since last update.

RustでSingletonパターン

Posted at

はじめに

ここ(stack overflow | How do I create a global, mutable singleton?)から引用してます。

引用元では生ポインタ使ってますが、Rustっぽくないので、Optionで代用してます。

標準ライブラリのみでやる

標準ライブラリ以外の方法は上記参照

use std::sync::{Arc, Mutex, Once, ONCE_INIT};
use std::time::Duration;
use std::{mem, thread};

#[derive(Clone)]
struct SingletonReader {
    // 同時アクセスのための参照及びミューテックス
    inner: Arc<Mutex<u8>>,
}

fn singleton() -> Box<SingletonReader> {
    // 生ポインタ遣うのあんまり好きじゃないので、Optionで代用。
    static mut SINGLETON: Option<Box<SingletonReader>>=None;
    static ONCE: Once = ONCE_INIT;

    unsafe {
        ONCE.call_once(|| {
            // Singletonを作成する。ここは1回しか通らないらしい。なおStable
            let singleton = SingletonReader {
                inner: Arc::new(Mutex::new(0)),
            };

            // ヒープ領域に置いとく
            SINGLETON = Some(Box::new(singleton));
        });

        // ヒープにあるオブジェクトの参照をコピーして使う
        SINGLETON.clone().unwrap()
    }
}

fn main() {
    // スレッドで使う。
    let threads: Vec<_> = (0..=10)
        .map(|i| {
            thread::spawn(move || {
                thread::sleep(Duration::from_millis(i * 10));
                let s = singleton();
                let mut data = s.inner.lock().unwrap();
                *data += i as u8;
            })
        })
        .collect();

    // 値の変化を確認
    for _ in 0u8..20 {
        thread::sleep(Duration::from_millis(5));

        let s = singleton();
        let data = s.inner.lock().unwrap();
        println!("It is: {}", *data);
    }
    // 全体のスレッドが終わるまで待つ(多分大体終わってるはずだけど、念のためみたい)
    for thread in threads.into_iter() {
        thread.join().unwrap();
    }
}

おわり

13
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
5