1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
use std::{ sync::mpsc::Receiver, cell::Cell }; /// Water Bottle. /// /// The Bottle ***must*** be held and used, otherwise it will [`Shatter`]. /// /// Allows to access Water that was produced by melting Ice. /// /// [`Shatter`]: struct.Bottle.html#impl-Drop pub struct Bottle<W>(Receiver<W>, Cell<bool>); impl<W> Bottle<W> { pub(crate) fn new(water: Receiver<W>) -> Bottle<W> { Bottle(water, Cell::new(false)) } /// Opens the Bottle, granting access to Water. /// /// The Bottle is consumed in the process. /// /// # Blocking /// /// This operation blocks till the Heater is done melting Ice. /// /// # Panics /// /// * When the Bottle has already been opened. /// * When the Bottle is Poisoned<sup>1</sup>. Poisoning<sup>1</sup> happens when Heater /// melting the Ice fails. Irrecoverable. /// /// --- /// /// <sup>1</sup> - Not to be confused with [`Poisoning of the Mutex`], although Bottle is /// Poisoned because of a very similar reason - panic in a thread. /// /// [`Poisoning of the Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html#poisoning pub fn open(&self) -> W { if self.1.get() { panic!("Tried to open an already opened bottle"); } else { self.1.set(true); } self.0 .recv() .expect("Tried to open a Poisoned bottle") } } impl<T> Drop for Bottle<T> { /// Drops the Bottle. /// /// # Panics /// /// When Bottle is dropped without ever being used. This causes it to shatter. /// /// It is completely user's responsibility to ensure that bottle is not dropped without /// being used. fn drop(&mut self) { assert!(self.1.get(), "Bottle dropped without ever being opened *Shatters*"); } }