@@ -10,160 +10,43 @@ mechanism for handling I/O notifications.
10
10
11
11
## Design
12
12
13
- This crate is built around two abstractions:
14
- - Event Manager
15
- - Event Subscriber
16
-
17
- The subscriber defines and registers an interest list with the event manager.
18
- The interest list represents the events that the subscriber wants to monitor.
19
-
20
- The Event Manager allows adding and removing subscribers, and provides
21
- APIs through which the subscribers can be updated in terms of events in their
22
- interest list. These actions are abstracted through the ` SubscriberOps ` trait.
23
-
24
- To interface with the Event Manager, the Event Subscribers need to provide an
25
- initialization function, and a callback for when events in the
26
- interest list become ready. The subscribers can update their interest list
27
- when handling ready events. These actions are abstracted through the
28
- ` EventSubscriber ` and ` MutEventSubscriber ` traits. They contain the same
29
- methods, but the former only requires immutable ` self ` borrows, whereas the
30
- latter requires mutable borrows. Any type implementing ` EventSubscriber `
31
- automatically implements ` MutEventSubscriber ` as well.
32
-
33
- A typical event-based application creates the event manager, registers
34
- subscribers, and then calls into the event manager's ` run ` function in a loop.
35
- Behind the scenes, the event manager calls into ` epoll::wait ` and maps the file
36
- descriptors in the ready list to the subscribers it manages. The event manager
37
- calls the subscriber's ` process ` function (its registered callback). When
38
- dispatching the events, the event manager creates a specialized object and
39
- passes it in the callback function so that the subscribers can use it to alter
40
- their interest list.
41
-
42
- ![ ] ( docs/event-manager.png )
13
+ This crate offers an abstraction (` EventManager ` ) over [ epoll] ( https://man7.org/linux/man-pages/man7/epoll.7.html ) that
14
+ allows for more ergonomic usage with many file descriptors.
15
+
16
+ The ` EventManager ` allows adding and removing file descriptors with a callback closure. The
17
+ ` EventManager ` interest list can also be modified within these callback closures.
18
+
19
+ A typical event-based application:
20
+
21
+ 1 . Creates the ` EventManager ` (` EventManager::default() ` ).
22
+ 2 . Registers file descriptors with (` EventManager::add ` ).
23
+ 3 . Calls ` EventManager::wait ` in a loop.
43
24
44
25
Read more in the [ design document] ( docs/DESIGN.md ) .
45
26
46
- ## Implementing an Event Subscriber
47
-
48
- The event subscriber has full control over the events that it monitors.
49
- The events need to be added to the event manager's loop as part of the
50
- ` init ` function. Adding events to the loop can return errors, and it is
51
- the responsibility of the subscriber to handle them.
52
-
53
- Similarly, the event subscriber is in full control of the ready events.
54
- When an event becomes ready, the event manager will call into the subscriber
55
- ` process ` function. The subscriber SHOULD handle the following events which
56
- are always returned when they occur (they don't need to be registered):
57
- - ` EventSet::ERROR ` - an error occurred on the monitor file descriptor.
58
- - ` EventSet::HANG_UP ` - hang up happened on the associated fd.
59
- - ` EventSet::READ_HANG_UP ` - hang up when the registered event is edge
60
- triggered.
61
-
62
- For more details about the error cases, you can check the
63
- [ ` epoll_ctl documentation ` ] ( https://www.man7.org/linux/man-pages/man2/epoll_ctl.2.html ) .
64
-
65
-
66
- ## Initializing the Event Manager
67
-
68
- The ` EventManager ` uses a generic type parameter which represents the
69
- subscriber type. The crate provides automatic implementations of
70
- ` EventSubscriber ` for ` Arc<T> ` and ` Rc<T> ` (for any ` T: EventSubscriber +?Sized ` ),
71
- together with automatic implementations of ` MutEventSubscriber ` for ` Mutex<T> `
72
- and ` RefCell<T> ` (for any ` T: MutEventSubscriber + ?Sized ` ). The generic type
73
- parameter enables either static or dynamic dispatch.
74
-
75
- This crate has no default features. The optional ` remote_endpoint `
76
- feature enables interactions with the ` EventManager ` from different threads
77
- without the need of more intrusive synchronization.
78
-
79
- ## Examples
80
-
81
- For closer to real life use cases, please check the examples in
82
- [ tests] ( tests ) .
83
-
84
- ### Basic Single Thread Subscriber
85
-
86
- #### Implementing a Basic Subscriber
87
-
88
- ``` rust
89
- use event_manager :: {EventOps , Events , MutEventSubscriber };
90
- use vmm_sys_util :: {eventfd :: EventFd , epoll :: EventSet };
91
-
92
- use std :: os :: unix :: io :: AsRawFd ;
93
- use std :: fmt :: {Display , Formatter , Result };
94
-
95
- pub struct CounterSubscriber {
96
- event_fd : EventFd ,
97
- counter : u64 ,
98
- }
99
-
100
- impl CounterSubscriber {
101
- pub fn new () -> Self {
102
- Self {
103
- event_fd : EventFd :: new (0 ). unwrap (),
104
- counter : 0 ,
105
- }
106
- }
107
- }
108
-
109
- impl MutEventSubscriber for CounterSubscriber {
110
- fn process (& mut self , events : Events , event_ops : & mut EventOps ) {
111
- match events . event_set () {
112
- EventSet :: IN => {
113
- self . counter += 1 ;
114
- }
115
- EventSet :: ERROR => {
116
- eprintln! (" Got error on the monitored event." );
117
- }
118
- EventSet :: HANG_UP => {
119
- event_ops . remove (events ). unwrap_or (
120
- eprintln! (" Encountered error during cleanup" )
121
- );
122
- panic! (" Cannot continue execution. Associated fd was closed." );
123
- }
124
- _ => {}
125
- }
126
- }
127
-
128
- fn init (& mut self , ops : & mut EventOps ) {
129
- ops . add (Events :: new (& self . event_fd, EventSet :: IN )). expect (" Cannot register event." );
130
- }
131
- }
132
- ```
133
-
134
- #### Adding Subscribers to the Event Manager
135
-
136
- ``` rust
137
- struct App {
138
- event_manager : EventManager <CounterSubscriber >,
139
- subscribers_id : Vec <SubscriberId >,
140
- }
141
-
142
- impl App {
143
- fn new () -> Self {
144
- Self {
145
- event_manager : EventManager :: <CounterSubscriber >:: new (). unwrap (),
146
- subscribers_id : vec! []
147
- }
148
- }
149
-
150
- fn add_subscriber (& mut self ) {
151
- let counter_subscriber = CounterSubscriber :: default ();
152
- let id = self . event_manager. add_subscriber (counter_subscriber );
153
- self . subscribers_id. push (id );
154
- }
155
-
156
- fn run (& mut self ) {
157
- let _ = self . event_manager. run_with_timeout (100 );
158
- }
159
- }
160
- ```
27
+ ## Implementing an event
28
+
29
+ Like ` epoll ` a file descriptor only monitors specific events.
30
+
31
+ The events ars specified when calling ` EventManager::add ` with ` vmm_sys_util::epoll::EventSet ` .
32
+
33
+ When an event becomes ready, the event manager will call the file descriptors callback closure.
34
+
35
+ The ` epoll ` events ` EPOLLRDHUP ` , ` EPOLLERR ` and ` EPOLLHUP ` (which correspond to
36
+ ` EventSet::READ_HANG_UP ` , ` EventSet::ERROR ` and ` EventSet::HANG_UP ` respectively) are documented to
37
+ always report, even when not specified by the user.
38
+
39
+ > epoll_wait(2) will always report for this event; it is not
40
+ > necessary to set it in events when calling epoll_ctl().
41
+
42
+ * https://man7.org/linux/man-pages/man2/epoll_ctl.2.html *
43
+
44
+ As such it is best practice to always handle the cases where the ` EventSet ` passed to the file
45
+ descriptor callback closure is ` EventSet::READ_HANG_UP ` , ` EventSet::ERROR ` or ` EventSet::HANG_UP ` .
161
46
162
47
## Development and Testing
163
48
164
- The ` event-manager ` is tested using unit tests, Rust integration tests and
165
- performance benchmarks. It leverages
166
- [ ` rust-vmm-ci ` ] ( https://github.com/rust-vmm/rust-vmm-ci ) for continuous
49
+ ` event-manager ` uses [ ` rust-vmm-ci ` ] ( https://github.com/rust-vmm/rust-vmm-ci ) for continuous
167
50
testing. All tests are run in the ` rustvmm/dev ` container.
168
51
169
52
More details on running the tests can be found in the
0 commit comments