Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  static_init.rs   Sprache: unbekannt

 
// SPDX-License-Identifier: Apache-2.0 OR MIT

#![allow(clippy::undocumented_unsafe_blocks)]
#![cfg_attr(feature = "alloc", feature(allocator_api))]
#![cfg_attr(not(RUSTC_LINT_REASONS_IS_STABLE), feature(lint_reasons))]
#![allow(unused_imports)]

use core::{
    cell::{Cell, UnsafeCell},
    mem::MaybeUninit,
    ops,
    pin::Pin,
    time::Duration,
};
use pin_init::*;
#[cfg(feature = "std")]
use std::{
    sync::Arc,
    thread::{sleep, Builder},
};

#[allow(unused_attributes)]
mod mutex;
use mutex::*;

pub struct StaticInit<T, I> {
    cell: UnsafeCell<MaybeUninit<T>>,
    init: Cell<Option<I>>,
    lock: SpinLock,
    present: Cell<bool>,
}

unsafe impl<T: Sync, I> Sync for StaticInit<T, I> {}
unsafe impl<T: Send, I> Send for StaticInit<T, I> {}

impl<T, I: PinInit<T>> StaticInit<T, I> {
    pub const fn new(init: I) -> Self {
        Self {
            cell: UnsafeCell::new(MaybeUninit::uninit()),
            init: Cell::new(Some(init)),
            lock: SpinLock::new(),
            present: Cell::new(false),
        }
    }
}

impl<T, I: PinInit<T>> ops::Deref for StaticInit<T, I> {
    type Target = T;
    fn deref(&self) -> &Self::Target {
        if self.present.get() {
            unsafe { (*self.cell.get()).assume_init_ref() }
        } else {
            println!("acquire spinlock on static init");
            let _guard = self.lock.acquire();
            println!("rechecking present...");
            std::thread::sleep(std::time::Duration::from_millis(200));
            if self.present.get() {
                return unsafe { (*self.cell.get()).assume_init_ref() };
            }
            println!("doing init");
            let ptr = self.cell.get().cast::<T>();
            match self.init.take() {
                Some(f) => unsafe { f.__pinned_init(ptr).unwrap() },
                None => unsafe { core::hint::unreachable_unchecked() },
            }
            self.present.set(true);
            unsafe { (*self.cell.get()).assume_init_ref() }
        }
    }
}

pub struct CountInit;

unsafe impl PinInit<CMutex<usize>> for CountInit {
    unsafe fn __pinned_init(
        self,
        slot: *mut CMutex<usize>,
    ) -> Result<(), core::convert::Infallible> {
        let init = CMutex::new(0);
        std::thread::sleep(std::time::Duration::from_millis(1000));
        unsafe { init.__pinned_init(slot) }
    }
}

pub static COUNT: StaticInit<CMutex<usize>, CountInit> = StaticInit::new(CountInit);

fn main() {
    #[cfg(feature = "std")]
    {
        let mtx: Pin<Arc<CMutex<usize>>> = Arc::pin_init(CMutex::new(0)).unwrap();
        let mut handles = vec![];
        let thread_count = 20;
        let workload = 1_000;
        for i in 0..thread_count {
            let mtx = mtx.clone();
            handles.push(
                Builder::new()
                    .name(format!("worker #{i}"))
                    .spawn(move || {
                        for _ in 0..workload {
                            *COUNT.lock() += 1;
                            std::thread::sleep(std::time::Duration::from_millis(10));
                            *mtx.lock() += 1;
                            std::thread::sleep(std::time::Duration::from_millis(10));
                            *COUNT.lock() += 1;
                        }
                        println!("{i} halfway");
                        sleep(Duration::from_millis((i as u64) * 10));
                        for _ in 0..workload {
                            std::thread::sleep(std::time::Duration::from_millis(10));
                            *mtx.lock() += 1;
                        }
                        println!("{i} finished");
                    })
                    .expect("should not fail"),
            );
        }
        for h in handles {
            h.join().expect("thread panicked");
        }
        println!("{:?}, {:?}", &*mtx.lock(), &*COUNT.lock());
        assert_eq!(*mtx.lock(), workload * thread_count * 2);
    }
}

[ Dauer der Verarbeitung: 0.20 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge