1 // Original work Copyright (c) 2014 The Rust Project Developers 2 // Modified work Copyright (c) 2016-2018 Nikita Pekin and the lazycell contributors 3 // See the README.md file at the top-level directory of this distribution. 4 // 5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or 6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license 7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your 8 // option. This file may not be copied, modified, or distributed 9 // except according to those terms. 10 11 #![deny(missing_docs)] 12 #![allow(unused)] 13 14 //! This crate provides a `LazyCell` struct which acts as a lazily filled 15 //! `Cell`. 16 //! 17 //! With a `RefCell`, the inner contents cannot be borrowed for the lifetime of 18 //! the entire object, but only of the borrows returned. A `LazyCell` is a 19 //! variation on `RefCell` which allows borrows to be tied to the lifetime of 20 //! the outer object. 21 //! 22 //! `AtomicLazyCell` is a variant that uses an atomic variable to manage 23 //! coordination in a thread-safe fashion. The limitation of an `AtomicLazyCell` 24 //! is that after it is initialized, it can't be modified. 25 26 use std::cell::UnsafeCell; 27 use std::mem; 28 use std::sync::atomic::{AtomicUsize, Ordering}; 29 30 /// A lazily filled `Cell`, with mutable contents. 31 /// 32 /// A `LazyCell` is completely frozen once filled, **unless** you have `&mut` 33 /// access to it, in which case `LazyCell::borrow_mut` may be used to mutate the 34 /// contents. 35 #[derive(Debug, Default)] 36 pub struct LazyCell<T> { 37 inner: UnsafeCell<Option<T>>, 38 } 39 40 impl<T> LazyCell<T> { 41 /// Creates a new, empty, `LazyCell`. 42 pub fn new() -> LazyCell<T> { 43 LazyCell { inner: UnsafeCell::new(None) } 44 } 45 46 /// Put a value into this cell. 47 /// 48 /// This function will return `Err(value)` is the cell is already full. 49 pub fn fill(&self, value: T) -> Result<(), T> { 50 let slot = unsafe { &mut *self.inner.get() }; 51 if slot.is_some() { 52 return Err(value); 53 } 54 *slot = Some(value); 55 56 Ok(()) 57 } 58 59 /// Put a value into this cell. 60 /// 61 /// Note that this function is infallible but requires `&mut self`. By 62 /// requiring `&mut self` we're guaranteed that no active borrows to this 63 /// cell can exist so we can always fill in the value. This may not always 64 /// be usable, however, as `&mut self` may not be possible to borrow. 65 /// 66 /// # Return value 67 /// 68 /// This function returns the previous value, if any. 69 pub fn replace(&mut self, value: T) -> Option<T> { 70 mem::replace(unsafe { &mut *self.inner.get() }, Some(value)) 71 } 72 73 /// Test whether this cell has been previously filled. 74 pub fn filled(&self) -> bool { 75 self.borrow().is_some() 76 } 77 78 /// Borrows the contents of this lazy cell for the duration of the cell 79 /// itself. 80 /// 81 /// This function will return `Some` if the cell has been previously 82 /// initialized, and `None` if it has not yet been initialized. find_minlength(const REAL_PCRE * re,const pcre_uchar * code,const pcre_uchar * startcode,int options,recurse_check * recurses,int * countptr)83 pub fn borrow(&self) -> Option<&T> { 84 unsafe { &*self.inner.get() }.as_ref() 85 } 86 87 /// Borrows the contents of this lazy cell mutably for the duration of the cell 88 /// itself. 89 /// 90 /// This function will return `Some` if the cell has been previously 91 /// initialized, and `None` if it has not yet been initialized. 92 pub fn borrow_mut(&mut self) -> Option<&mut T> { 93 unsafe { &mut *self.inner.get() }.as_mut() 94 } 95 96 /// Borrows the contents of this lazy cell for the duration of the cell 97 /// itself. 98 /// 99 /// If the cell has not yet been filled, the cell is first filled using the 100 /// function provided. 101 /// 102 /// # Panics 103 /// 104 /// Panics if the cell becomes filled as a side effect of `f`. 105 pub fn borrow_with<F: FnOnce() -> T>(&self, f: F) -> &T { 106 if let Some(value) = self.borrow() { 107 return value; 108 } 109 let value = f(); 110 if self.fill(value).is_err() { 111 panic!("borrow_with: cell was filled by closure") 112 } 113 self.borrow().unwrap() 114 } 115 116 /// Borrows the contents of this `LazyCell` mutably for the duration of the 117 /// cell itself. 118 /// 119 /// If the cell has not yet been filled, the cell is first filled using the 120 /// function provided. 121 /// 122 /// # Panics 123 /// 124 /// Panics if the cell becomes filled as a side effect of `f`. 125 pub fn borrow_mut_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T { 126 if !self.filled() { 127 let value = f(); 128 if self.fill(value).is_err() { 129 panic!("borrow_mut_with: cell was filled by closure") 130 } 131 } 132 133 self.borrow_mut().unwrap() 134 } 135 136 /// Same as `borrow_with`, but allows the initializing function to fail. 137 /// 138 /// # Panics 139 /// 140 /// Panics if the cell becomes filled as a side effect of `f`. 141 pub fn try_borrow_with<E, F>(&self, f: F) -> Result<&T, E> 142 where F: FnOnce() -> Result<T, E> 143 { 144 if let Some(value) = self.borrow() { 145 return Ok(value); 146 } 147 let value = f()?; 148 if self.fill(value).is_err() { 149 panic!("try_borrow_with: cell was filled by closure") 150 } 151 Ok(self.borrow().unwrap()) 152 } 153 154 /// Same as `borrow_mut_with`, but allows the initializing function to fail. 155 /// 156 /// # Panics 157 /// 158 /// Panics if the cell becomes filled as a side effect of `f`. 159 pub fn try_borrow_mut_with<E, F>(&mut self, f: F) -> Result<&mut T, E> 160 where F: FnOnce() -> Result<T, E> 161 { 162 if self.filled() { 163 return Ok(self.borrow_mut().unwrap()); 164 } 165 let value = f()?; 166 if self.fill(value).is_err() { 167 panic!("try_borrow_mut_with: cell was filled by closure") 168 } 169 Ok(self.borrow_mut().unwrap()) 170 } 171 172 /// Consumes this `LazyCell`, returning the underlying value. 173 pub fn into_inner(self) -> Option<T> { 174 // Rust 1.25 changed UnsafeCell::into_inner() from unsafe to safe 175 // function. This unsafe can be removed when supporting Rust older than 176 // 1.25 is not needed. 177 #[allow(unused_unsafe)] 178 unsafe { self.inner.into_inner() } 179 } 180 } 181 182 impl<T: Copy> LazyCell<T> { 183 /// Returns a copy of the contents of the lazy cell. 184 /// 185 /// This function will return `Some` if the cell has been previously initialized, 186 /// and `None` if it has not yet been initialized. 187 pub fn get(&self) -> Option<T> { 188 unsafe { *self.inner.get() } 189 } 190 } 191 192 // Tracks the AtomicLazyCell inner state 193 const NONE: usize = 0; 194 const LOCK: usize = 1; 195 const SOME: usize = 2; 196 197 /// A lazily filled and thread-safe `Cell`, with frozen contents. 198 #[derive(Debug, Default)] 199 pub struct AtomicLazyCell<T> { 200 inner: UnsafeCell<Option<T>>, 201 state: AtomicUsize, 202 } 203 204 impl<T> AtomicLazyCell<T> { 205 /// Creates a new, empty, `AtomicLazyCell`. 206 pub fn new() -> AtomicLazyCell<T> { 207 Self { 208 inner: UnsafeCell::new(None), 209 state: AtomicUsize::new(NONE), 210 } 211 } 212 213 /// Put a value into this cell. 214 /// 215 /// This function will return `Err(value)` is the cell is already full. 216 pub fn fill(&self, t: T) -> Result<(), T> { 217 if NONE != self.state.compare_and_swap(NONE, LOCK, Ordering::Acquire) { 218 return Err(t); 219 } 220 221 unsafe { *self.inner.get() = Some(t) }; 222 223 if LOCK != self.state.compare_and_swap(LOCK, SOME, Ordering::Release) { 224 panic!("unable to release lock"); 225 } 226 227 Ok(()) 228 } 229 230 /// Put a value into this cell. 231 /// 232 /// Note that this function is infallible but requires `&mut self`. By 233 /// requiring `&mut self` we're guaranteed that no active borrows to this 234 /// cell can exist so we can always fill in the value. This may not always 235 /// be usable, however, as `&mut self` may not be possible to borrow. 236 /// 237 /// # Return value 238 /// 239 /// This function returns the previous value, if any. 240 pub fn replace(&mut self, value: T) -> Option<T> { 241 match mem::replace(self.state.get_mut(), SOME) { 242 NONE | SOME => {} 243 _ => panic!("cell in inconsistent state"), 244 } 245 mem::replace(unsafe { &mut *self.inner.get() }, Some(value)) 246 } 247 248 /// Test whether this cell has been previously filled. 249 pub fn filled(&self) -> bool { 250 self.state.load(Ordering::Acquire) == SOME 251 } 252 253 /// Borrows the contents of this lazy cell for the duration of the cell 254 /// itself. 255 /// 256 /// This function will return `Some` if the cell has been previously 257 /// initialized, and `None` if it has not yet been initialized. 258 pub fn borrow(&self) -> Option<&T> { 259 match self.state.load(Ordering::Acquire) { 260 SOME => unsafe { &*self.inner.get() }.as_ref(), 261 _ => None, 262 } 263 } 264 265 /// Consumes this `LazyCell`, returning the underlying value. 266 pub fn into_inner(self) -> Option<T> { 267 // Rust 1.25 changed UnsafeCell::into_inner() from unsafe to safe 268 // function. This unsafe can be removed when supporting Rust older than 269 // 1.25 is not needed. 270 #[allow(unused_unsafe)] 271 unsafe { self.inner.into_inner() } 272 } 273 } 274 275 impl<T: Copy> AtomicLazyCell<T> { 276 /// Returns a copy of the contents of the lazy cell. 277 /// 278 /// This function will return `Some` if the cell has been previously initialized, 279 /// and `None` if it has not yet been initialized. 280 pub fn get(&self) -> Option<T> { 281 match self.state.load(Ordering::Acquire) { 282 SOME => unsafe { *self.inner.get() }, 283 _ => None, 284 } 285 } 286 } 287 288 unsafe impl<T: Sync + Send> Sync for AtomicLazyCell<T> {} 289 290 unsafe impl<T: Send> Send for AtomicLazyCell<T> {} 291 292 #[cfg(test)] 293 mod tests { 294 use super::{AtomicLazyCell, LazyCell}; 295 296 #[test] 297 fn test_borrow_from_empty() { 298 let lazycell: LazyCell<usize> = LazyCell::new(); 299 300 let value = lazycell.borrow(); 301 assert_eq!(value, None); 302 303 let value = lazycell.get(); 304 assert_eq!(value, None); 305 } 306 307 #[test] 308 fn test_fill_and_borrow() { 309 let lazycell = LazyCell::new(); 310 311 assert!(!lazycell.filled()); 312 lazycell.fill(1).unwrap(); 313 assert!(lazycell.filled()); 314 315 let value = lazycell.borrow(); 316 assert_eq!(value, Some(&1)); 317 318 let value = lazycell.get(); 319 assert_eq!(value, Some(1)); 320 } 321 322 #[test] 323 fn test_borrow_mut() { 324 let mut lazycell = LazyCell::new(); 325 assert!(lazycell.borrow_mut().is_none()); 326 327 lazycell.fill(1).unwrap(); 328 assert_eq!(lazycell.borrow_mut(), Some(&mut 1)); 329 330 *lazycell.borrow_mut().unwrap() = 2; 331 assert_eq!(lazycell.borrow_mut(), Some(&mut 2)); 332 333 // official way to reset the cell 334 lazycell = LazyCell::new(); 335 assert!(lazycell.borrow_mut().is_none()); 336 } 337 338 #[test] 339 fn test_already_filled_error() { 340 let lazycell = LazyCell::new(); 341 342 lazycell.fill(1).unwrap(); 343 assert_eq!(lazycell.fill(1), Err(1)); 344 } 345 346 #[test] 347 fn test_borrow_with() { 348 let lazycell = LazyCell::new(); 349 350 let value = lazycell.borrow_with(|| 1); 351 assert_eq!(&1, value); 352 } 353 354 #[test] 355 fn test_borrow_with_already_filled() { 356 let lazycell = LazyCell::new(); 357 lazycell.fill(1).unwrap(); 358 359 let value = lazycell.borrow_with(|| 1); 360 assert_eq!(&1, value); 361 } 362 363 #[test] 364 fn test_borrow_with_not_called_when_filled() { 365 let lazycell = LazyCell::new(); 366 367 lazycell.fill(1).unwrap(); 368 369 let value = lazycell.borrow_with(|| 2); 370 assert_eq!(&1, value); 371 } 372 373 #[test] 374 #[should_panic] 375 fn test_borrow_with_sound_with_reentrancy() { 376 // Kudos to dbaupp for discovering this issue 377 // https://www.reddit.com/r/rust/comments/5vs9rt/lazycell_a_rust_library_providing_a_lazilyfilled/de527xm/ 378 let lazycell: LazyCell<Box<i32>> = LazyCell::new(); 379 380 let mut reference: Option<&i32> = None; 381 382 lazycell.borrow_with(|| { 383 let _ = lazycell.fill(Box::new(1)); 384 reference = lazycell.borrow().map(|r| &**r); 385 Box::new(2) 386 }); 387 } 388 389 #[test] 390 fn test_borrow_mut_with() { 391 let mut lazycell = LazyCell::new(); 392 393 { 394 let value = lazycell.borrow_mut_with(|| 1); 395 assert_eq!(&mut 1, value); 396 *value = 2; 397 } 398 assert_eq!(&2, lazycell.borrow().unwrap()); 399 } 400 401 #[test] 402 fn test_borrow_mut_with_already_filled() { 403 let mut lazycell = LazyCell::new(); 404 lazycell.fill(1).unwrap(); 405 406 let value = lazycell.borrow_mut_with(|| 1); 407 assert_eq!(&1, value); 408 } 409 410 #[test] 411 fn test_borrow_mut_with_not_called_when_filled() { 412 let mut lazycell = LazyCell::new(); 413 414 lazycell.fill(1).unwrap(); 415 416 let value = lazycell.borrow_mut_with(|| 2); 417 assert_eq!(&1, value); 418 } 419 420 #[test] 421 fn test_try_borrow_with_ok() { 422 let lazycell = LazyCell::new(); 423 let result = lazycell.try_borrow_with::<(), _>(|| Ok(1)); 424 assert_eq!(result, Ok(&1)); 425 } 426 427 #[test] 428 fn test_try_borrow_with_err() { 429 let lazycell = LazyCell::<()>::new(); 430 let result = lazycell.try_borrow_with(|| Err(1)); 431 assert_eq!(result, Err(1)); 432 } 433 434 #[test] 435 fn test_try_borrow_with_already_filled() { 436 let lazycell = LazyCell::new(); 437 lazycell.fill(1).unwrap(); 438 let result = lazycell.try_borrow_with::<(), _>(|| unreachable!()); 439 assert_eq!(result, Ok(&1)); 440 } 441 442 #[test] 443 #[should_panic] 444 fn test_try_borrow_with_sound_with_reentrancy() { 445 let lazycell: LazyCell<Box<i32>> = LazyCell::new(); 446 447 let mut reference: Option<&i32> = None; 448 449 let _ = lazycell.try_borrow_with::<(), _>(|| { 450 let _ = lazycell.fill(Box::new(1)); 451 reference = lazycell.borrow().map(|r| &**r); 452 Ok(Box::new(2)) 453 }); 454 } 455 456 #[test] 457 fn test_try_borrow_mut_with_ok() { 458 let mut lazycell = LazyCell::new(); 459 { 460 let result = lazycell.try_borrow_mut_with::<(), _>(|| Ok(1)); 461 assert_eq!(result, Ok(&mut 1)); 462 *result.unwrap() = 2; 463 } 464 assert_eq!(&mut 2, lazycell.borrow().unwrap()); 465 } 466 467 #[test] 468 fn test_try_borrow_mut_with_err() { 469 let mut lazycell = LazyCell::<()>::new(); 470 let result = lazycell.try_borrow_mut_with(|| Err(1)); 471 assert_eq!(result, Err(1)); 472 } 473 474 #[test] 475 fn test_try_borrow_mut_with_already_filled() { 476 let mut lazycell = LazyCell::new(); 477 lazycell.fill(1).unwrap(); 478 let result = lazycell.try_borrow_mut_with::<(), _>(|| unreachable!()); 479 assert_eq!(result, Ok(&mut 1)); 480 } 481 482 #[test] 483 fn test_into_inner() { 484 let lazycell = LazyCell::new(); 485 486 lazycell.fill(1).unwrap(); 487 let value = lazycell.into_inner(); 488 assert_eq!(value, Some(1)); 489 } 490 491 #[test] 492 fn test_atomic_borrow_from_empty() { 493 let lazycell: AtomicLazyCell<usize> = AtomicLazyCell::new(); 494 495 let value = lazycell.borrow(); 496 assert_eq!(value, None); 497 498 let value = lazycell.get(); 499 assert_eq!(value, None); 500 } 501 502 #[test] 503 fn test_atomic_fill_and_borrow() { 504 let lazycell = AtomicLazyCell::new(); 505 506 assert!(!lazycell.filled()); 507 lazycell.fill(1).unwrap(); 508 assert!(lazycell.filled()); 509 510 let value = lazycell.borrow(); 511 assert_eq!(value, Some(&1)); 512 513 let value = lazycell.get(); 514 assert_eq!(value, Some(1)); 515 } 516 517 #[test] 518 fn test_atomic_already_filled_panic() { 519 let lazycell = AtomicLazyCell::new(); 520 521 lazycell.fill(1).unwrap(); 522 assert_eq!(1, lazycell.fill(1).unwrap_err()); 523 } 524 525 #[test] 526 fn test_atomic_into_inner() { 527 let lazycell = AtomicLazyCell::new(); 528 529 lazycell.fill(1).unwrap(); 530 let value = lazycell.into_inner(); 531 assert_eq!(value, Some(1)); 532 } 533 534 #[test] 535 fn normal_replace() { 536 let mut cell = LazyCell::new(); 537 assert_eq!(cell.fill(1), Ok(())); 538 assert_eq!(cell.replace(2), Some(1)); 539 assert_eq!(cell.replace(3), Some(2)); 540 assert_eq!(cell.borrow(), Some(&3)); 541 542 let mut cell = LazyCell::new(); 543 assert_eq!(cell.replace(2), None); 544 } 545 546 #[test] 547 fn atomic_replace() { 548 let mut cell = AtomicLazyCell::new(); 549 assert_eq!(cell.fill(1), Ok(())); 550 assert_eq!(cell.replace(2), Some(1)); 551 assert_eq!(cell.replace(3), Some(2)); 552 assert_eq!(cell.borrow(), Some(&3)); 553 } 554 } 555