]> Dogcows Code - chaz/talk-event-driven-programming-in-perl/blob - slides.html
9eae8008ce65f65a0a2751af948d93738c50c4ee
[chaz/talk-event-driven-programming-in-perl] / slides.html
1 <!DOCTYPE html>
2 <html><head><meta charset="utf-8"><title>Event-driven Programming in Perl</title><link rel="stylesheet" href="css/common.css"><link rel="stylesheet" href="css/slides.css"></head><body><textarea id="source">
3
4 class: center, middle
5 name: title
6
7 # Event-driven Programming in Perl
8
9 Charles McGarvey
10
11 ???
12 - Hi. I'm Charles McGarvey.
13 - Been a Perl programmer for a long time...
14
15 ---
16 class: center, middle
17 name: bluehost
18
19 ???
20 - My employer is hiring.
21 - It's a pretty cool employer...
22
23 ---
24 ## "Normal" [userspace] programs
25
26 .big[
27 1. Parse args.
28 2. Read input.
29 3. Do stuff.
30 4. Write results as output.
31 ]
32
33 ---
34 class: pizza
35 background-image: url(img/pizza.jpg)
36 background-size: 100%
37
38 --
39 ```bash
40 # orderpizza --crust-type=thin \
41 --toppings=cheese,pepperoni,mushrooms
42 ```
43
44 --
45 ```perl
46 # source code of the orderpizza program
47
48 my $order = get_order_from_args(@ARGV);
49
50 my $ingredients = gather_ingredients($order);
51
52 my $pizza = prepare_and_bake($order, $ingredentials);
53
54 print($pizza);
55 ```
56
57 ---
58 ## Event-driven programs
59
60 .big[
61 1. Events happen.
62 2. When events happen, some code runs and does something.
63 ]
64
65 ???
66 At it's core, event-driven programming is this simple.
67
68 But there are some complications and things to knows, which is why this talk exists.
69
70 ---
71 class: center, middle
72
73 ![Event loop](img/eventloop.svg)
74
75 ???
76 We'll refine this model as we go.
77
78 ---
79 class: ex-hwinterrupts
80
81 ## Hardware interrupts
82
83 ```bash
84 # cat /proc/interrupts
85 CPU0 CPU1
86 0: 51 0 IR-IO-APIC 2-edge timer
87 1: 685006 5 IR-IO-APIC 1-edge i8042
88 8: 0 0 IR-IO-APIC 8-edge rtc0
89 9: 1724419 6314 IR-IO-APIC 9-fasteoi acpi
90 12: 12300601 138 IR-IO-APIC 12-edge i8042
91 16: 0 0 IR-IO-APIC 16-fasteoi i801_smbus
92 120: 0 0 DMAR-MSI 0-edge dmar0
93 121: 0 0 DMAR-MSI 1-edge dmar1
94 122: 7009890 45112 IR-PCI-MSI 327680-edge xhci_hcd
95 123: 44 3 IR-PCI-MSI 360448-edge mei_me
96 124: 509 0 IR-PCI-MSI 1048576-edge rtsx_pci
97 125: 80130 0 IR-PCI-MSI 2621440-edge nvme0q0, nvme0q1
98 126: 121892439 2961357 IR-PCI-MSI 32768-edge i915
99 127: 49 100 IR-PCI-MSI 514048-edge snd_hda_intel:card0
100 128: 0 79412 IR-PCI-MSI 2621441-edge nvme0q2
101
102 ...
103 ```
104
105 ???
106 When a HW interrupt happens, the appropriate code to run is locate in the interrupt service routine
107
108 ---
109 class: ex-pressenter
110
111 ## Your first event-driven program
112
113 .middle[
114 ```perl
115 print "Press <Enter> to continue.";
116 <STDIN>;
117
118 handle_enter_keypress_event();
119 ```
120 ]
121
122 ---
123 class: ex-pressenter
124
125 ## Your first event-driven program
126
127 .middle[
128 ```perl
129 print "Press <Enter> to continue.";
130 *<STDIN>;
131
132 handle_enter_keypress_event();
133 ```
134 ]
135
136 .big[
137 - Wait for an event
138 ]
139
140 ---
141 class: ex-pressenter
142
143 ## Your first event-driven program
144
145 .middle[
146 ```perl
147 print "Press <Enter> to continue.";
148 *<STDIN>;
149
150 handle_enter_keypress_event();
151 ```
152 ]
153
154 .big[
155 - Wait for an event
156 - Event source
157 ]
158
159 ---
160 class: ex-pressenter
161
162 ## Your first event-driven program
163
164 .middle[
165 ```perl
166 print "Press <Enter> to continue.";
167 <STDIN>;
168
169 *handle_enter_keypress_event();
170 ```
171 ]
172
173 .big[
174 - Wait for an event
175 - Event source
176 - Event handler
177 ]
178
179 ---
180 class: ex-signals
181
182 ## Signals
183
184 ```perl
185 use POSIX;
186
187 $SIG{USR1} = sub { handle_usr1_signal_event() };
188 $SIG{ALRM} = sub { handle_timer_event() };
189 $SIG{QUIT} = sub { exit() };
190
191 alarm(3);
192
193 while (1) { POSIX::pause() }
194 ```
195
196 ---
197 class: ex-signals
198
199 ## Signals
200
201 ```perl
202 use POSIX;
203
204 *$SIG{USR1} = sub { handle_usr1_signal_event() };
205 *$SIG{ALRM} = sub { handle_timer_event() };
206 *$SIG{QUIT} = sub { exit() };
207
208 alarm(3);
209
210 while (1) { POSIX::pause() }
211 ```
212
213 ???
214 Notice that this program is capable of handling more than just one event handler at a time.
215
216 ---
217 class: ex-signals
218
219 ## Signals
220
221 ```perl
222 use POSIX;
223
224 $SIG{USR1} = sub { handle_usr1_signal_event() };
225 $SIG{ALRM} = sub { handle_timer_event() };
226 $SIG{QUIT} = sub { exit() };
227
228 alarm(3);
229
230 *while (1) { POSIX::pause() }
231 ```
232
233 .big[
234 - Program yields time to the kernel
235 ]
236
237 ???
238 This example has a loop, but it's not really doing anything.
239
240 But actually it is doing something very important: It's yielding its processing time to the kernel.
241
242 And kernel informs the program of events.
243
244 You might be able to use `sleep` as well, but some implementations of libc
245 in the past have implemented `sleep` using `alarm`.
246
247 Don't know how common that is nowadays, but old habbits...
248
249 ---
250 class: ex-gui
251
252 ## Graphical user interface example
253
254 ```perl
255 use Gtk3 '-init';
256
257 my $window = Gtk3::Window->new;
258
259 $window->signal_connect('key-press-event' => \&handle_keypress_event);
260 $window->signal_connect('delete-event' => \&Gtk3::main_quit);
261
262 $window->show_all;
263
264 Gtk3::main();
265 ```
266
267 ???
268 A user interface happens to be a good place to use evented code because humans are spontaneous and unpredictable.
269
270 ---
271 class: ex-gui
272
273 ## Graphical user interface example
274
275 ```perl
276 use Gtk3 '-init';
277
278 my $window = Gtk3::Window->new;
279
280 *$window->signal_connect('key-press-event' => \&handle_keypress_event);
281 *$window->signal_connect('delete-event' => \&Gtk3::main_quit);
282
283 $window->show_all;
284
285 Gtk3::main();
286 ```
287
288 .big[
289 - Event handlers
290 ]
291
292 ---
293 class: ex-gui
294
295 ## Graphical user interface example
296
297 ```perl
298 use Gtk3 '-init';
299
300 my $window = Gtk3::Window->new;
301
302 $window->signal_connect('key-press-event' => \&handle_keypress_event);
303 $window->signal_connect('delete-event' => \&Gtk3::main_quit);
304
305 $window->show_all;
306
307 *Gtk3::main();
308 ```
309
310 .big[
311 - Event handlers
312 - Yield and wait for events
313 ]
314
315 ---
316 class: event-types
317
318 ## Types of events
319
320 - IO
321
322 ???
323 Data available on a socket, or a new connection.
324
325 Server or client, data across a wire cannot typically be relied upon to arrive in a predictable fashion, so an
326 event-driven architect makes a lot of sense for network applications.
327
328 --
329 - Signals
330
331 ???
332 As far as my program is concerned, it can receive a signal or message from another program at any time.
333
334 --
335 - Timer
336
337 ???
338 If I need something to happen to happen in five minutes or at a specific absolute time, using the idea of an alarm clock
339 is tempting. I can set an alarm and pretend that the clock itself is a source of events.
340
341 --
342 - User input
343
344 ???
345 Human beings of course are masters of spontaneity.
346
347 Are they going to press a button on the keyboard next, or move the mouse? If my program is connected to a microphone,
348 maybe the human is going to start talking to the program. The program has to be ready for anything, so defining and
349 accepting "events" for all the different ways that a human can interact with the program is a good way to go.
350
351 --
352 - Anything that can happen spontaneously in the real world.
353
354 ???
355 Lots of other external systems (besides humans) can "generate" events.
356
357 Lot of this requires kernel facilities. Speaking of which, how are these types of things implemented?
358
359 ---
360 class: syscalls
361
362 ## How event-driven userspace code works
363
364 ### syscalls
365
366 - [`pause`](http://man.he.net/man2/pause) - Sleeps until signal
367 - [`select`](http://man.he.net/man2/select), [`poll`](http://man.he.net/man2/poll), [`epoll`](http://man.he.net/man7/epoll), [`kqueue`](https://www.freebsd.org/cgi/man.cgi?format=ascii&sektion=2&query=kqueue) - Monitor multiple file descriptors
368 - [`clock_gettime`](http://man.he.net/man2/clock_gettime) - What time is it now?
369
370 ---
371 class: ex-basicreactor
372
373 ## The basic reactor
374
375 ```perl
376 our $timers = [...];
377 our $io_handles = [...];
378
379 while (1) {
380 my $next_timer = find_next_timer($timers);
381
382 poll($io_handles, $next_timer->time_from_now);
383
384 handle_ready_io_handles($io_handles);
385 handle_expired_timers($timers);
386 }
387 ```
388
389 ---
390
391 ## Reactor examples on CPAN
392
393 .big[
394 - [`POE::Loop::IO_Poll`](https://metacpan.org/source/POE::Loop::IO_Poll)
395 - [`POE::Loop::Select`](https://metacpan.org/source/POE::Loop::Select)
396 - [`AnyEvent::Loop`](https://metacpan.org/source/AnyEvent::Loop)
397 - [`IO::Async::Loop::Poll`](https://metacpan.org/source/IO::Async::Loop::Poll)
398 - [`IO::Async::Loop::Select`](https://metacpan.org/source/IO::Async::Loop::Select)
399 - [`Mojo::Reactor::Poll`](https://metacpan.org/source/Mojo::Reactor::Poll)
400 ]
401
402 ---
403 class: center, middle
404 name: conclusion
405
406 ## Conclusion:
407
408 ### Perl is fun.
409
410 ---
411 class: center, middle
412 name: last
413
414 ### Thanks.
415
416 </textarea><script src="https://gnab.github.io/remark/downloads/remark-latest.min.js"></script><script>var slideshow = remark.create({countIncrementalSlides: true, highlightLanguage: '', highlightLines: true, highlightStyle: 'hybrid', ratio: '16:9', /*slideNumberFormat: '',*/ navigation: {scroll: false, touch: false, click: false}})</script><script src="js/common.js"></script><script src="js/slides.js"></script></body></html>
417 <!-- vim: set ts=4 sts=4 sw=4 tw=120 et ft=markdown nowrap: -->
This page took 0.052718 seconds and 3 git commands to generate.