Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::cell::UnsafeCell;
- pub struct OnceCell<T> {
- inner: UnsafeCell<Option<T>>,
- }
- impl<T> OnceCell<T> {
- pub fn new() -> OnceCell<T> { OnceCell { inner: UnsafeCell::new(None) } }
- pub fn get(&self) -> Option<&T> {
- unsafe { &*self.inner.get() }.as_ref()
- }
- pub fn set(&self, value: T) -> Result<(), T> {
- let slot = unsafe { &mut *self.inner.get() };
- if slot.is_some() {
- return Err(value);
- }
- *slot = Some(value);
- Ok(())
- }
- // UB!!!
- pub fn get_or_init(&self, f: impl FnOnce() -> T) -> &T {
- let slot = unsafe { &mut *self.inner.get() };
- match slot {
- None => {
- *slot = Some(f());
- slot.as_ref().unwrap()
- }
- Some(val) => val,
- }
- }
- }
- pub fn main() {
- let cell: OnceCell<Box<i32>> = OnceCell::new();
- let mut r1: Option<&i32> = None;
- let r2: &i32 = cell.get_or_init(|| {
- r1 = Some(cell.get_or_init(|| Box::new(1)));
- // r1 = Some(&*cell.get_or_init(|| Box::new(1)));
- Box::new(2)
- });
- let r1: &i32 = r1.unwrap();
- println!("{} {}", r1, r2);
- }
- /*
- result is like
- ~/rust ❯❯❯ ./once_cell
- -1317687192 2
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement