1
- use crate :: { DisconnectSender , EventHandler , EventListener , EventReceiver } ;
1
+ use crate :: listener:: FinishProcessing ;
2
+ use crate :: { EventHandler , EventListener , EventReceiver } ;
2
3
use std:: thread;
4
+ use std:: thread:: JoinHandle ;
3
5
4
6
/// A listener which uses a channel to receive messages of type `Event`, and uses
5
- /// a thread to run the event handler (in [`crate:: ChannelEventListener::run_handler`].
7
+ /// a thread to run the event handler (in [`ChannelEventListener::run_handler`]) .
6
8
///
7
- /// The channels required to create an instance can be created by calling the [`crate::event_channel`]
8
- /// and [`crate::disconnect_channel `] functions .
9
+ /// The channel based receiver required to create an instance can be created by calling the
10
+ /// [`event_channel() `] function .
9
11
///
10
- /// The [`crate::Reporter`] associated with this event listener is the [`crate::ChannelReporter`].
12
+ /// The [`Reporter`] associated with this event listener is the [`ChannelReporter`].
13
+ ///
14
+ /// [`ChannelEventListener::run_handler`]: crate::ChannelEventListener::run_handler
15
+ /// [`event_channel()`]: crate::event_channel
16
+ /// [`Reporter`]: crate::Reporter
17
+ /// [`ChannelReporter`]: crate::ChannelReporter
11
18
pub struct ChannelEventListener < Event > {
12
- message_receiver : EventReceiver < Event > ,
13
- disconnect_sender : DisconnectSender ,
19
+ event_receiver : EventReceiver < Event > ,
14
20
}
15
21
16
22
impl < Event > ChannelEventListener < Event > {
17
23
/// Create a new channel based event listener.
18
24
///
19
- /// The channels required to create an instance can be created by calling the [`crate::event_channel`]
20
- /// and [`crate::disconnect_channel`] functions.
21
- pub fn new (
22
- message_receiver : EventReceiver < Event > ,
23
- disconnect_sender : DisconnectSender ,
24
- ) -> Self {
25
- Self {
26
- message_receiver,
27
- disconnect_sender,
28
- }
29
- }
30
-
31
- /// If you use `ChannelEventListener` by wrapping it, instead of using it directly,
32
- /// for example if you want to write your own `EventListener` implementation,
33
- /// you will need this `&EventReceiver` to receive events.
34
- ///
35
- /// ### Example
36
- ///
37
- /// **NB:** This example should **not** be used on its own! It does not contain a fully working listener!
38
- /// See [`crate::EventListener`] on how to implement your own listener instead.
39
- ///
40
- /// ```no_run
41
- /// // NB: This example is incomplete!
42
- /// // It does not contain a fully working listener!
43
- ///
44
- /// use storyteller::{ChannelEventListener, EventHandler, EventListener};
45
- ///
46
- /// struct MyEvent;
47
- ///
48
- /// struct WrappingListener {
49
- /// listener: ChannelEventListener<MyEvent>,
50
- /// }
51
- ///
52
- /// impl EventListener for WrappingListener {
53
- /// type Event = MyEvent;
54
- ///
55
- /// fn run_handler<H>(self, handler: H) where H: EventHandler<Event=Self::Event> {
56
- ///
57
- /// let disconnect_sender = self.listener.disconnect_sender();
58
- /// let message_receiver = self.listener.message_receiver(); // <---
59
- ///
60
- /// loop {
61
- /// if let Err(_) = message_receiver.recv() {
62
- /// disconnect_sender.acknowledge_disconnection().unwrap();
63
- /// }
64
- /// }
65
- /// }
66
- /// }
67
- /// ```
68
- pub fn message_receiver ( & self ) -> & EventReceiver < Event > {
69
- & self . message_receiver
70
- }
71
-
72
- /// If you use `ChannelEventListener` by wrapping it, instead of using it directly,
73
- /// for example if you want to write your own `EventListener` implementation,
74
- /// you will need this `&DisconnectSender` to acknowledge when a reporter disconnects.
75
- ///
76
- /// ### Example
77
- ///
78
- /// **NB:** This example should **not*** be used on its own! It does not contain a fully working listener!
79
- /// See [`crate::EventListener`] on how to implement your own listener instead.
80
- ///
81
- /// ```no_run
82
- /// // NB: This example is incomplete!
83
- /// // It does not contain a fully working listener!
84
- ///
85
- /// use storyteller::{ChannelEventListener, EventHandler, EventListener};
86
- ///
87
- /// struct MyEvent;
88
- ///
89
- /// struct WrappingListener {
90
- /// listener: ChannelEventListener<MyEvent>,
91
- /// }
25
+ /// The channel based receiver required to create an instance can be created by calling the
26
+ /// [`event_channel()`] function.
92
27
///
93
- /// impl EventListener for WrappingListener {
94
- /// type Event = MyEvent;
95
- ///
96
- /// fn run_handler<H>(self, handler: H) where H: EventHandler<Event=Self::Event> {
97
- ///
98
- /// let disconnect_sender = self.listener.disconnect_sender(); // <---
99
- /// let message_receiver = self.listener.message_receiver();
100
- ///
101
- /// loop {
102
- /// if let Err(_) = message_receiver.recv() {
103
- /// disconnect_sender.acknowledge_disconnection().unwrap();
104
- /// }
105
- /// }
106
- /// }
107
- /// }
108
- /// ```
109
- pub fn disconnect_sender ( & self ) -> & DisconnectSender {
110
- & self . disconnect_sender
28
+ /// [`event_channel()`]: crate::event_channel
29
+ pub fn new ( event_receiver : EventReceiver < Event > ) -> Self {
30
+ Self { event_receiver }
111
31
}
112
32
}
113
33
@@ -116,32 +36,68 @@ where
116
36
Event : Send + ' static ,
117
37
{
118
38
type Event = Event ;
39
+ type FinishProcessingHandle = ChannelFinalizeHandler ;
119
40
120
- fn run_handler < H > ( self , handler : H )
41
+ fn run_handler < H > ( & self , handler : H ) -> Self :: FinishProcessingHandle
121
42
where
122
- H : EventHandler < Event = Self :: Event > ,
43
+ H : EventHandler < Event = Self :: Event > + ' static ,
123
44
{
124
- thread:: spawn ( move || {
125
- let disconnect_sender = self . disconnect_sender ( ) ;
126
- let message_receiver = self . message_receiver ( ) ;
45
+ let event_receiver = self . event_receiver . clone ( ) ;
127
46
128
- loop {
129
- match message_receiver. recv ( ) {
47
+ let handle = thread:: spawn ( move || {
48
+ //
49
+ ' evl: loop {
50
+ match event_receiver. recv ( ) {
130
51
Ok ( message) => handler. handle ( message) ,
131
52
Err ( _disconnect) => {
132
53
handler. finish ( ) ;
133
-
134
- let _ack = disconnect_sender. acknowledge_disconnection ( ) ;
135
-
136
- #[ cfg( not( feature = "experimental_handle_disconnect_ack" ) ) ]
137
- {
138
- _ack. expect ( "Failed to send disconnect acknowledgement!" ) ;
139
- }
140
-
141
- break ;
54
+ break ' evl;
142
55
}
143
56
}
144
57
}
145
58
} ) ;
59
+
60
+ ChannelFinalizeHandler :: new ( handle)
61
+ }
62
+ }
63
+
64
+ /// A [`FinishProcessing`] implementation for the [`ChannelEventListener`].
65
+ /// Used to wait for the [`EventHandler`] ran by the `listener` to finish processing
66
+ /// events.
67
+ ///
68
+ /// ### Caution: Infinite looping
69
+ ///
70
+ /// Calling [`FinishProcessing::finish_processing`] without first disconnecting
71
+ /// the sender channel of the reporter will cause the program to be stuck in an infinite
72
+ /// loop.
73
+ ///
74
+ /// The reason for this is that disconnecting the channel causes the loop to process
75
+ /// a disconnect event, where we break out of the loop. If this disconnect does not
76
+ /// happen, the thread processing events will not be finished, and
77
+ /// [`FinishProcessing::finish_processing`] will block, since it waits for the thread
78
+ /// to be finished.
79
+ ///
80
+ /// To disconnect the sender channel of the reporter, call [`ChannelReporter::disconnect`].
81
+ ///
82
+ /// [`FinishProcessing`]: crate::FinishProcessing
83
+ /// [`EventHandler`]: crate::EventHandler
84
+ /// [`ChannelEventListener`]: crate::ChannelEventListener
85
+ /// [`ChannelReporter::disconnect`]: crate::ChannelReporter::disconnect
86
+ #[ must_use]
87
+ pub struct ChannelFinalizeHandler {
88
+ handle : JoinHandle < ( ) > ,
89
+ }
90
+
91
+ impl ChannelFinalizeHandler {
92
+ fn new ( handle : JoinHandle < ( ) > ) -> Self {
93
+ Self { handle }
94
+ }
95
+ }
96
+
97
+ impl FinishProcessing for ChannelFinalizeHandler {
98
+ type Err = ( ) ;
99
+
100
+ fn finish_processing ( self ) -> Result < ( ) , Self :: Err > {
101
+ self . handle . join ( ) . map_err ( |_| ( ) )
146
102
}
147
103
}
0 commit comments