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
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
use std::sync::mpsc::{
	self,
	Receiver,
	Sender,
	TryIter,
};

/// Slot represents a queue where data may be placed.
pub trait Slot<T> {
	/// Add new instance of data to the queue.
	///
	/// Return true if data was added or false if the other side is not interested
	/// in data receiving anymore (and never will be interested again).
	fn exec_for(
		&self,
		t: T,
	) -> bool;

	/// Creates [SlotProxy] for particular slot. The [SlotProxy] may be saved
	/// separatedly from the original [Slot] but still may be used to send new
	/// instance of data to the original [Slot]. [SlotProxy] do not provide
	/// any mechanism to retrive data from the queue.
	///
	/// Proxy created for another [SlotProxy] still will refer to the original [Slot].
	fn proxy(&self) -> SlotProxy<T>;
}


/// The main implementation for [Slot] trait. Allows to pull data from queue.
pub struct SlotImpl<T> {
	receiver: Receiver<T>,
	sender: Sender<T>,
}

impl<T> SlotImpl<T> {
	/// Creates new instance
	pub fn new() -> SlotImpl<T> {
		let (sender, receiver) = mpsc::channel();
		return SlotImpl {
			sender,
			receiver,
		};
	}

	/// Try to obtain next value from [SlotImpl]'s queue.
	pub fn next(&self) -> Option<T> {
		return self.receiver.try_recv().ok();
	}

	/// Return TryIter to access to the queue's content
	pub fn data_iter(&self) -> TryIter<T> {
		return self.receiver.try_iter();
	}

	/// Return last element from the queue
	pub fn last(&self) -> Option<T> {
		return self.data_iter().last();
	}

	/// Clean queue
	pub fn discard_pending(&self) {
		self.data_iter().last();
	}

	/// Add new data instance to the queue
	pub fn exec_for(
		&self,
		t: T,
	) -> bool {
		return match self.sender.send(t) {
			Ok(_) => {
				trace!("exec_for:ok");
				true
			},
			Err(e) => {
				warn!("exec_for:err:{:?}", e);
				false
			},
		};
	}

	/// Creates proxy which is refer to the [SlotImpl]
	pub fn proxy(&self) -> SlotProxy<T> {
		return SlotProxy {
			sender: self.sender.clone(),
		};
	}
}

impl<T> Slot<T> for SlotImpl<T> {
	fn exec_for(
		&self,
		t: T,
	) -> bool {
		return self.exec_for(t);
	}

	fn proxy(&self) -> SlotProxy<T> {
		return self.proxy();
	}
}

impl<T> Default for SlotImpl<T> {
	fn default() -> Self {
		return Self::new();
	}
}

/// [SlotProxy] may be used as independed reference to the original [Slot]'s queue.
#[derive(Clone)]
pub struct SlotProxy<T> {
	sender: Sender<T>,
}

impl<T> SlotProxy<T> {
	/// Create [SlotProxy] which is not coupled with any [SlotImpl]
	pub fn empty() -> SlotProxy<T> {
		let (sender, _) = mpsc::channel();
		return SlotProxy {
			sender,
		};
	}

	/// Put new data instance to the related [SlotImpl]'s queue
	pub fn exec_for(
		&self,
		t: T,
	) -> bool {
		return match self.sender.send(t) {
			Ok(_) => {
				trace!("exec_for:ok");
				true
			},
			Err(e) => {
				warn!("exec_for:err:{:?}", e);
				false
			},
		};
	}

	/// Create proxy which is refer to the same [SlotImpl]
	///
	/// It's improtant that [SlotProxy] doesn't organized in the chain. New
	/// [SlotProxy] will refer to the original [SlotImpl] and will not have any
	/// reference to the [SlotProxy].
	pub fn proxy(&self) -> SlotProxy<T> {
		return SlotProxy {
			sender: self.sender.clone(),
		};
	}
}

impl<T> Slot<T> for SlotProxy<T> {
	fn exec_for(
		&self,
		t: T,
	) -> bool {
		return self.exec_for(t);
	}

	fn proxy(&self) -> SlotProxy<T> {
		return self.proxy();
	}
}

impl<T> Default for SlotProxy<T> {
	fn default() -> Self {
		return Self::empty();
	}
}