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}