ice_threads/
bottle.rs

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