176612720Slogin // Copyright (C) DragonOS Community longjin 276612720Slogin 376612720Slogin // This program is free software; you can redistribute it and/or 476612720Slogin // modify it under the terms of the GNU General Public License 576612720Slogin // as published by the Free Software Foundation; either version 2 676612720Slogin // of the License, or (at your option) any later version. 776612720Slogin 876612720Slogin // This program is distributed in the hope that it will be useful, 976612720Slogin // but WITHOUT ANY WARRANTY; without even the implied warranty of 1076612720Slogin // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1176612720Slogin // GNU General Public License for more details. 1276612720Slogin 1376612720Slogin // You should have received a copy of the GNU General Public License 1476612720Slogin // along with this program; if not, write to the Free Software 1576612720Slogin // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 1676612720Slogin // Or you can visit https://www.gnu.org/licenses/gpl-2.0.html 1776612720Slogin #![allow(dead_code)] 1876612720Slogin 1976612720Slogin use core::cell::UnsafeCell; 2076612720Slogin use core::fmt::Debug; 2176612720Slogin use core::mem::MaybeUninit; 2276612720Slogin use core::ops::{Deref, DerefMut}; 2376612720Slogin use core::sync::atomic::{AtomicBool, Ordering}; 2476612720Slogin 2576612720Slogin use super::spinlock::SpinLock; 2676612720Slogin 2776612720Slogin /// A wrapper around a value that is initialized lazily. 28*5c9a63dfSlogin pub struct Lazy<T> { 2976612720Slogin /// The lock that is used to ensure that only one thread calls the init function at the same time. 3076612720Slogin init_lock: SpinLock<()>, 3176612720Slogin /// The value that is initialized lazily. 3276612720Slogin value: UnsafeCell<MaybeUninit<T>>, 3376612720Slogin /// Whether the value has been initialized. 3476612720Slogin initialized: AtomicBool, 3576612720Slogin } 3676612720Slogin 37*5c9a63dfSlogin impl<T> Lazy<T> { 3876612720Slogin /// Creates a new `Lazy` value that will be initialized with the 3976612720Slogin /// result of the closure `init`. new() -> Lazy<T>4076612720Slogin pub const fn new() -> Lazy<T> { 4176612720Slogin Lazy { 4276612720Slogin value: UnsafeCell::new(MaybeUninit::uninit()), 4376612720Slogin initialized: AtomicBool::new(false), 4476612720Slogin init_lock: SpinLock::new(()), 4576612720Slogin } 4676612720Slogin } 4776612720Slogin 4876612720Slogin /// Returns true if the value has been initialized. 4976612720Slogin #[inline(always)] initialized(&self) -> bool5076612720Slogin pub fn initialized(&self) -> bool { 5176612720Slogin let initialized = self.initialized.load(Ordering::Acquire); 5276612720Slogin if initialized { 5376612720Slogin return true; 5476612720Slogin } 5576612720Slogin return false; 5676612720Slogin } 5776612720Slogin 5876612720Slogin /// Ensures that this lazy value is initialized. If the value has not 5976612720Slogin /// yet been initialized, this will raise a panic. 6076612720Slogin #[inline(always)] ensure(&self)6176612720Slogin pub fn ensure(&self) { 6276612720Slogin if self.initialized() { 6376612720Slogin return; 6476612720Slogin } 6576612720Slogin panic!("Lazy value was not initialized"); 6676612720Slogin } 6776612720Slogin init(&self, value: T)6876612720Slogin pub fn init(&self, value: T) { 6976612720Slogin assert!(!self.initialized()); 7076612720Slogin 7176612720Slogin // We need this lock to ensure that only one thread calls the init function at the same time. 7276612720Slogin let _init_guard = self.init_lock.lock(); 7376612720Slogin // Check again, in case another thread initialized it while we were waiting for the lock. 7476612720Slogin let initialized = self.initialized(); 7576612720Slogin if initialized { 7676612720Slogin return; 7776612720Slogin } 7876612720Slogin unsafe { 7976612720Slogin (*self.value.get()).as_mut_ptr().write(value); 8076612720Slogin } 8176612720Slogin self.initialized.store(true, Ordering::Release); 8276612720Slogin } 8376612720Slogin /// Forces the evaluation of this lazy value and returns a reference to 8476612720Slogin /// the result. This is equivalent to the `Deref` impl, but is explicit. 8576612720Slogin /// This will initialize the value if it has not yet been initialized. get(&self) -> &T8676612720Slogin pub fn get(&self) -> &T { 8776612720Slogin self.ensure(); 8876612720Slogin return unsafe { self.get_unchecked() }; 8976612720Slogin } 9076612720Slogin 9176612720Slogin /// Returns a reference to the value if it has been initialized. 9276612720Slogin /// Otherwise, returns `None`. try_get(&self) -> Option<&T>9376612720Slogin pub fn try_get(&self) -> Option<&T> { 9476612720Slogin if self.initialized() { 9576612720Slogin return Some(unsafe { self.get_unchecked() }); 9676612720Slogin } 9776612720Slogin return None; 9876612720Slogin } 9976612720Slogin 10076612720Slogin /// Forces the evaluation of this lazy value and returns a mutable 10176612720Slogin /// reference to the result. This is equivalent to the `DerefMut` impl, 10276612720Slogin /// but is explicit. This will initialize the value if it has not yet 10376612720Slogin /// been initialized. get_mut(&mut self) -> &mut T10476612720Slogin pub fn get_mut(&mut self) -> &mut T { 10576612720Slogin self.ensure(); 10676612720Slogin return unsafe { self.get_mut_unchecked() }; 10776612720Slogin } 10876612720Slogin 10976612720Slogin #[inline(always)] get_unchecked(&self) -> &T11076612720Slogin pub unsafe fn get_unchecked(&self) -> &T { 11176612720Slogin return &*(*self.value.get()).as_ptr(); 11276612720Slogin } 11376612720Slogin 11476612720Slogin #[inline(always)] get_mut_unchecked(&mut self) -> &mut T11576612720Slogin pub unsafe fn get_mut_unchecked(&mut self) -> &mut T { 11676612720Slogin return &mut *(*self.value.get()).as_mut_ptr(); 11776612720Slogin } 11876612720Slogin } 11976612720Slogin 120*5c9a63dfSlogin impl<T> Deref for Lazy<T> { 12176612720Slogin type Target = T; 12276612720Slogin 12376612720Slogin #[inline(always)] deref(&self) -> &T12476612720Slogin fn deref(&self) -> &T { 12576612720Slogin return self.get(); 12676612720Slogin } 12776612720Slogin } 12876612720Slogin 129*5c9a63dfSlogin impl<T> DerefMut for Lazy<T> { 13076612720Slogin #[inline(always)] deref_mut(&mut self) -> &mut T13176612720Slogin fn deref_mut(&mut self) -> &mut T { 13276612720Slogin return self.get_mut(); 13376612720Slogin } 13476612720Slogin } 13576612720Slogin 136*5c9a63dfSlogin impl<T: Debug> Debug for Lazy<T> { fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result13776612720Slogin fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { 13876612720Slogin if let Some(value) = self.try_get() { 13976612720Slogin return write!(f, "Lazy({:?})", value); 14076612720Slogin } else { 14176612720Slogin return write!(f, "Lazy(uninitialized)"); 14276612720Slogin } 14376612720Slogin } 14476612720Slogin } 14576612720Slogin 146*5c9a63dfSlogin impl<T> Drop for Lazy<T> { drop(&mut self)14776612720Slogin fn drop(&mut self) { 14876612720Slogin if self.initialized() { 14976612720Slogin unsafe { 15076612720Slogin (*self.value.get()).as_mut_ptr().drop_in_place(); 15176612720Slogin } 15276612720Slogin } 15376612720Slogin } 15476612720Slogin } 155*5c9a63dfSlogin 156*5c9a63dfSlogin unsafe impl<T: Send + Sync> Sync for Lazy<T> {} 157*5c9a63dfSlogin unsafe impl<T: Send> Send for Lazy<T> {} 158