+???
+- My employer is hiring.
+- It's a pretty cool employer...
+
+---
+## "Normal" [userspace] programs
+
+.big[
+1. Parse args.
+2. Read input.
+3. Do stuff.
+4. Write results as output.
+]
+
+---
+class: pizza
+background-image: url(img/pizza.jpg)
+background-size: 100%
+
+--
+```bash
+# orderpizza --crust-type=thin \
+ --toppings=cheese,pepperoni,mushrooms
+```
+
+--
+```perl
+# source code of the orderpizza program
+
+my $order = get_order_from_args(@ARGV);
+
+my $ingredients = gather_ingredients($order);
+
+my $pizza = prepare_and_bake($order, $ingredentials);
+
+print($pizza);
+```
+
+???
+But some programs are long-lived.
+
+---
+## Event-driven programs
+
+.big[
+1. Events happen.
+2. When events happen, some code runs and does something.
+]
+
+???
+At it's core, event-driven programming is this simple.
+
+But there are some complications and things to knows, which is why this talk exists.
+
+---
+class: center, middle
+
+![Help desk](img/helpdesk.jpg)
+
+.small[
+Image by Soniachat8.
+This image is licensed under the [Creative Commons Attribution-Share Alike 4.0 International](https://creativecommons.org/licenses/by-sa/4.0/deed.en) license.
+]
+
+---
+name: graph-eventloop
+class: center, middle
+
+## Event loop
+
+![Event loop](img/eventloop.svg)
+
+???
+We'll refine this model as we go.
+
+---
+class: ex-hwinterrupts
+
+## Hardware interrupts
+
+```bash
+# cat /proc/interrupts
+ CPU0 CPU1
+ 0: 51 0 IR-IO-APIC 2-edge timer
+ 1: 685006 5 IR-IO-APIC 1-edge i8042
+ 8: 0 0 IR-IO-APIC 8-edge rtc0
+ 9: 1724419 6314 IR-IO-APIC 9-fasteoi acpi
+ 12: 12300601 138 IR-IO-APIC 12-edge i8042
+ 16: 0 0 IR-IO-APIC 16-fasteoi i801_smbus
+ 120: 0 0 DMAR-MSI 0-edge dmar0
+ 121: 0 0 DMAR-MSI 1-edge dmar1
+ 122: 7009890 45112 IR-PCI-MSI 327680-edge xhci_hcd
+ 123: 44 3 IR-PCI-MSI 360448-edge mei_me
+ 124: 509 0 IR-PCI-MSI 1048576-edge rtsx_pci
+ 125: 80130 0 IR-PCI-MSI 2621440-edge nvme0q0, nvme0q1
+ 126: 121892439 2961357 IR-PCI-MSI 32768-edge i915
+ 127: 49 100 IR-PCI-MSI 514048-edge snd_hda_intel:card0
+ 128: 0 79412 IR-PCI-MSI 2621441-edge nvme0q2
+
+...
+```
+
+???
+When a HW interrupt happens, the appropriate code to run is locate in the interrupt service routine
+
+---
+class: ex-pressenter
+
+## Your first event-driven program
+
+.middle[
+```perl
+print "Press <Enter> to continue.";
+<STDIN>;
+
+handle_enter_keypress_event();
+```
+]
+
+---
+class: ex-pressenter
+
+## Your first event-driven program
+
+.middle[
+```perl
+print "Press <Enter> to continue.";
+*<STDIN>;
+
+handle_enter_keypress_event();
+```
+]
+
+.big[
+- Wait for an event
+]
+
+---
+class: ex-pressenter
+
+## Your first event-driven program
+
+.middle[
+```perl
+print "Press <Enter> to continue.";
+*<STDIN>;
+
+handle_enter_keypress_event();
+```
+]
+
+.big[
+- Wait for an event
+- Event source
+]
+
+---
+class: ex-pressenter
+
+## Your first event-driven program
+
+.middle[
+```perl
+print "Press <Enter> to continue.";
+<STDIN>;
+
+*handle_enter_keypress_event();
+```
+]
+
+.big[
+- Wait for an event
+- Event source
+- Event handler
+]
+
+---
+class: ex-signals
+
+## Signals
+
+```perl
+use POSIX;
+
+$SIG{USR1} = sub { handle_usr1_signal_event() };
+$SIG{ALRM} = sub { handle_timer_event() };
+$SIG{QUIT} = sub { exit() };
+
+alarm(3);
+
+while (1) { POSIX::pause() }
+```
+
+---
+class: ex-signals
+
+## Signals
+
+```perl
+use POSIX;
+
+*$SIG{USR1} = sub { handle_usr1_signal_event() };
+*$SIG{ALRM} = sub { handle_timer_event() };
+*$SIG{QUIT} = sub { exit() };
+
+alarm(3);
+
+while (1) { POSIX::pause() }
+```
+
+???
+Notice that this program is capable of handling more than just one event handler at a time.
+
+---
+class: ex-signals
+
+## Signals
+
+```perl
+use POSIX;
+
+$SIG{USR1} = sub { handle_usr1_signal_event() };
+$SIG{ALRM} = sub { handle_timer_event() };
+$SIG{QUIT} = sub { exit() };
+
+alarm(3);
+
+*while (1) { POSIX::pause() }
+```
+
+.big[
+- Program yields time to the kernel
+]
+
+???
+This example has a loop, but it's not really doing anything.
+
+But actually it is doing something very important: It's yielding its processing time to the kernel.
+
+And kernel informs the program of events.
+
+You might be able to use `sleep` as well, but some implementations of libc
+in the past have implemented `sleep` using `alarm`.
+
+Don't know how common that is nowadays, but old habbits...
+
+---
+class: ex-gui
+
+## Graphical user interface example
+
+```perl
+use Gtk3 '-init';
+
+my $window = Gtk3::Window->new;
+
+$window->signal_connect('key-press-event' => \&handle_keypress_event);
+$window->signal_connect('delete-event' => \&Gtk3::main_quit);
+
+$window->show_all;
+
+Gtk3::main();
+```
+
+???
+A user interface happens to be a good place to use evented code because humans are spontaneous and unpredictable.
+
+---
+class: ex-gui
+
+## Graphical user interface example
+
+```perl
+use Gtk3 '-init';
+
+my $window = Gtk3::Window->new;
+
+*$window->signal_connect('key-press-event' => \&handle_keypress_event);
+*$window->signal_connect('delete-event' => \&Gtk3::main_quit);
+
+$window->show_all;
+
+Gtk3::main();
+```
+
+.big[
+- Event handlers
+]
+
+---
+class: ex-gui
+
+## Graphical user interface example
+
+```perl
+use Gtk3 '-init';
+
+my $window = Gtk3::Window->new;
+
+$window->signal_connect('key-press-event' => \&handle_keypress_event);
+$window->signal_connect('delete-event' => \&Gtk3::main_quit);
+
+$window->show_all;
+
+*Gtk3::main();
+```
+
+.big[
+- Event handlers
+- Yield and wait for events
+]
+
+---
+class: event-types
+
+## Types of events
+
+- IO
+
+???
+Data available on a socket, or a new connection.
+
+Server or client, data across a wire cannot typically be relied upon to arrive in a predictable fashion, so an
+event-driven architect makes a lot of sense for network applications.
+
+--
+- Signals
+
+???
+As far as my program is concerned, it can receive a signal or message from another program at any time.
+
+--
+- Timer
+
+???
+If I need something to happen to happen in five minutes or at a specific absolute time, using the idea of an alarm clock
+is tempting. I can set an alarm and pretend that the clock itself is a source of events.
+
+--
+- User input
+
+???
+Human beings of course are masters of spontaneity.
+
+Are they going to press a button on the keyboard next, or move the mouse? If my program is connected to a microphone,
+maybe the human is going to start talking to the program. The program has to be ready for anything, so defining and
+accepting "events" for all the different ways that a human can interact with the program is a good way to go.
+
+--
+- Anything that can happen spontaneously in the real world.
+
+???
+Lots of other external systems (besides humans) can "generate" events.
+
+Lot of this requires kernel facilities. Speaking of which, how are these types of things implemented?
+
+---
+class: syscalls
+
+## How event-driven userspace code works
+
+### syscalls
+
+- [`pause`](http://man.he.net/man2/pause) - Sleeps until signal
+
+--
+- [`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
+
+--
+- [`clock_gettime`](http://man.he.net/man2/clock_gettime) - What time is it now?
+
+---
+class: center, middle
+
+## Reactor pattern
+
+---
+## Reactor pattern
+
+.big[
+- Queues events asynchronously.
+- Demultiplexes and dispatches synchronously.
+]
+
+---
+name: graph-reactor
+class: center, middle
+
+## Reactor pattern
+
+![Reactor](img/reactor.svg)
+
+---
+class: ex-basicreactor1
+
+## Using a reactor
+
+```perl
+my $reactor = My::Reactor->new;
+
+# Set up event handlers
+$reactor->slurp_file($filepath, \&handle_slurp_event);
+$reactor->timer(5, \&handle_timer_event);
+$reactor->listen($socket, \&handle_new_connect_event);
+...
+
+$reactor->run_loop;
+```
+
+---
+class: ex-basicreactor2
+
+## The basic reactor implementation
+
+```perl
+our $timers = [...];
+our $io_handles = [...];
+
+while (1) {
+ my $next_timer = find_next_timer($timers);
+
+ poll($io_handles, $next_timer->time_from_now);
+
+ handle_ready_io_handles($io_handles);
+ handle_expired_timers($timers);
+}
+```
+
+???
+Of course, you don't actually need to know anything about which syscalls are used and how a reactor actually works to do
+event-driven programming. (and if any of this is going over your head, that's fine.)
+
+But I'm covering it because I think it's good for you.
+
+---
+class: ex-basicreactor2
+
+## The basic reactor implementation
+
+```perl
+our $timers = [...];
+our $io_handles = [...];
+
+while (1) {
+ my $next_timer = find_next_timer($timers);
+
+* poll($io_handles, $next_timer->time_from_now);
+
+ handle_ready_io_handles($io_handles);
+ handle_expired_timers($timers);
+}
+```
+
+---
+## Reactor examples on CPAN
+
+.big[
+- [`POE::Loop::IO_Poll`](https://metacpan.org/source/POE::Loop::IO_Poll)
+- [`POE::Loop::Select`](https://metacpan.org/source/POE::Loop::Select)
+- [`AnyEvent::Loop`](https://metacpan.org/source/AnyEvent::Loop)
+- [`IO::Async::Loop::Poll`](https://metacpan.org/source/IO::Async::Loop::Poll)
+- [`IO::Async::Loop::Select`](https://metacpan.org/source/IO::Async::Loop::Select)
+- [`Mojo::Reactor::Poll`](https://metacpan.org/source/Mojo::Reactor::Poll)
+]
+
+???
+These links, which will be available to you with the slides, link directly to the source code of these modules on
+metacpan so you can take a look at how they work.
+
+---
+## Reactors
+
+.col.big[
+- [`Cocoa::EventLoop`](https://metacpan.org/pod/Cocoa::EventLoop)
+- [`EV`](https://metacpan.org/pod/EV)
+- [`Event::Lib`](https://metacpan.org/pod/Event::Lib)
+- [`Event`](https://metacpan.org/pod/Event)
+- [`FLTK`](https://metacpan.org/pod/FLTK)
+]
+.col.big[
+- [`Glib`](https://metacpan.org/pod/Glib), [`Gtk`](https://metacpan.org/pod/Gtk), [`Gtk2`](https://metacpan.org/pod/Gtk2)
+- [`Tk`](https://metacpan.org/pod/Tk)
+- [`UV`](https://metacpan.org/pod/UV)
+- [`Wx`](https://metacpan.org/pod/Wx)
+- probably more...
+]
+
+???
+I'm not going to go over any of these.
+
+- You can use any one of these directly.
+- Some of that are better than others (obvious).
+- Which one you choose may depend one what you're building.
+ - If you're building a GUI, your choice is made for you.
+ - High-concurrency network application, `EV` is a good choice.
+
+But actually you may not need to pick one...
+
+---
+class: center, middle
+
+## Reactor "front ends"
+
+???
+By my count there are four main front ends.
+
+---
+## Reactor "front ends"
+
+.big[
+- [**`POE`**](https://metacpan.org/pod/POE) - Portable multitasking and networking framework for any event loop (or Perl, Objects, and Events)
+- [**`IO::Async`**](https://metacpan.org/pod/IO::Async) - Asynchronous event-driven programming
+- [**`Mojo::IOLoop`**](https://metacpan.org/pod/Mojo::IOLoop) - Minimalistic event loop
+- [**`AnyEvent`**](https://metacpan.org/pod/AnyEvent) - The DBI of event loop programming
+]
+
+???
+The benefit of using one of these rather than the reactors themselves is that your code will automatically work with any
+of a number of supported reactors.
+
+---
+class: ex-poe
+
+## `POE`
+
+```perl
+use POE;
+use Time::HiRes qw(time);
+
+POE::Session->create(
+ inline_states => {
+ _start => sub {
+ $_[KERNEL]->delay(tick => 5);
+ },
+
+ tick => \&handle_timer_event,
+ },
+);
+
+POE::Kernel->run;
+```
+
+???
+POE:
+- The oldest, released 1998
+- Parallel processing was it's primary use.
+
+---
+class: ex-poe
+
+## `POE`
+
+```perl
+*use POE;
+use Time::HiRes qw(time);
+
+POE::Session->create(
+ inline_states => {
+ _start => sub {
+ $_[KERNEL]->delay(tick => 5);
+ },
+
+ tick => \&handle_timer_event,
+ },
+);
+
+POE::Kernel->run;
+```
+
+???
+Using `POE` will implicitly load all the modules you'll need to actually do anything.
+- In this case, `POE::Session` and `POE::Kernel`.
+
+---
+class: ex-poe
+
+## `POE`
+
+```perl
+use POE;
+use Time::HiRes qw(time);
+
+POE::Session->create(
+ inline_states => {
+ _start => sub {
+ $_[KERNEL]->delay(tick => 5);
+ },
+
+ tick => \&handle_timer_event,
+ },
+);
+
+*POE::Kernel->run;
+```
+
+???
+Run the reactor.
+
+In POE, the kernel is the thing that manages processes AKA sessions.
+
+---
+class: ex-poe
+
+## `POE`
+
+```perl
+use POE;
+use Time::HiRes qw(time);
+
+*POE::Session->create(
+* inline_states => {
+* _start => sub {
+* $_[KERNEL]->delay(tick => 5);
+* },
+*
+* tick => \&handle_timer_event,
+* },
+*);
+
+POE::Kernel->run;
+```
+
+???
+
+Sessions can be created to do stuff.
+
+---
+class: ex-ioasync
+
+## `IO::Async`
+
+```perl
+use IO::Async::Loop;
+use IO::Async::Timer::Countdown;
+
+my $loop = IO::Async::Loop->new;
+
+my $timer = IO::Async::Timer::Countdown->new(
+ delay => 5, # seconds
+ on_expire => \&handle_timer_event,
+);
+$timer->start;
+
+$loop->add($timer);
+
+$loop->run;
+```
+
+---
+class: ex-ioasync
+
+## `IO::Async`
+
+```perl
+use IO::Async::Loop;
+use IO::Async::Timer::Countdown;
+
+*my $loop = IO::Async::Loop->new;
+
+my $timer = IO::Async::Timer::Countdown->new(
+ delay => 5, # seconds
+ on_expire => \&handle_timer_event,
+);
+$timer->start;
+
+$loop->add($timer);
+
+$loop->run;
+```
+
+???
+Create the loop
+- IO::Async doesn't seem to have a concept of a "default" loop.
+ - The user has control over starting the loop, as usual, but it does mean that modules can't really register
+ themselves.