]> Dogcows Code - chaz/talk-event-driven-programming-in-perl/commitdiff
add more sections
authorCharles McGarvey <cmcgarvey@bluehost.com>
Sun, 17 Jun 2018 20:01:40 +0000 (14:01 -0600)
committerCharles McGarvey <cmcgarvey@bluehost.com>
Sun, 17 Jun 2018 20:01:40 +0000 (14:01 -0600)
.gitignore
Makefile
abstract.txt
app.psgi [new file with mode: 0644]
css/common.css
css/slides.css
img/bluehost.png
img/eventloop.dot [new file with mode: 0644]
img/pizza.jpg [new file with mode: 0644]
notes.txt
slides.html

index 54294125892f0830a13ae25077783deb536e7437..b0b0f730d1dc0771f07a3bce7cc384b5753574fb 100644 (file)
@@ -1,2 +1,4 @@
+*.pdf
+/img/eventloop.svg
 /remark.min.js
 /slides-offline.html
index 272b370a4a3920059caccc26bfe081b6f4e557b4..2af1c47f39c5676a0e582d02f44b718b2d108319 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -25,7 +25,7 @@ run-offline: offline
        $(DOT) -Tsvg -o$@ $<
 
 $(SLIDES).pdf: slides.html $(wildcard css/*) $(wildcard img/*) $(svgfiles)
-       docker run --rm -v `pwd`:/pwd astefanutti/decktape /pwd/slides.html /pwd/$(SLIDES).pdf
+       docker run --network host --rm -t -v `pwd`:/slides astefanutti/decktape http://localhost:5000 /slides/$(SLIDES).pdf
 
 slides-offline.html: slides.html
        sed -e '1 a <!-- This file is auto-generated - DO NOT EDIT!!! -->' \
index f1065360dfe966969cec50e64787eb0efe923a01..af6e885fa7f72154579272fa1cb37a5523d28dd5 100644 (file)
@@ -1,7 +1,7 @@
 Event-driven programming in Perl
 Charles McGarvey | Mon, 6/18 at 2:00 pm | 50 minutes | Ballroom B
 
-Event-driven programming is a paradigm where programmers creates subroutines
+Event-driven programming is a paradigm where programmers create subroutines
 that get called when events occur. Events can be just about anything: timers
 expiring, new data becoming available to read from a socket, even humans
 clicking on things in an interactive program.
diff --git a/app.psgi b/app.psgi
new file mode 100644 (file)
index 0000000..006ed67
--- /dev/null
+++ b/app.psgi
@@ -0,0 +1,15 @@
+#!/usr/bin/env perl
+
+use Plack::App::Directory;
+use Plack::App::File;
+use Plack::Builder;
+use Plack::Util;
+
+builder {
+    mount '/css'            => Plack::App::Directory->new(root => 'css')->to_app;
+    mount '/img'            => Plack::App::Directory->new(root => 'img')->to_app;
+    mount '/js'             => Plack::App::Directory->new(root => 'js')->to_app;
+    mount '/remark.min.js'  => Plack::App::File->new(file => 'remark.min.js')->to_app;
+    mount '/'               => Plack::App::File->new(file => 'slides-offline.html')->to_app;
+};
+
index 5fe4e74a71a693cb24776ae2f9f7d58a17b3ef8e..525370d1033eb7bec8dc88fed373953e041dd5f5 100644 (file)
     color: #7d9726;
 }
 
+.big {
+    font-size: 150%;
+}
+
+.remark-code-line-highlighted {
+    background-color: rgba(200,200,255,.25);
+}
+.hljs-hybrid .hljs {
+    background: rgba(29,31,33,.96);
+}
+
index 04d938b439950f814a29aeda3f9512bb2a4c85b4..36ce1a2e31944fb96698b4319805f3c4c97fba77 100644 (file)
@@ -1,5 +1,43 @@
 
-#slide-bluehost img {
-    width: 250px;
+#slide-bluehost {
+    background: url('../img/bluehost.png') 1100px;
+}
+
+.pizza img {
+    width: 70%;
+}
+.pizza .bash {
+    font-size: 38px;
+}
+.pizza .perl {
+    font-size: 36px;
+}
+
+.ex-hwinterrupts .bash {
+    font-size: 22px;
+}
+
+.ex-pressenter .perl {
+    font-size: 40px;
+}
+
+.ex-signals .perl {
+    font-size: 36px;
+}
+
+.ex-gui .perl {
+    font-size: 28px;
+}
+
+.event-types ul {
+    font-size: 34px;
+}
+
+.syscalls ul {
+    font-size: 34px;
+}
+
+.ex-basicreactor .perl {
+    font-size: 38px;
 }
 
index 3a831807c89ef9c07dd5510b9a6197a83cd30127..3d124df69ea79fd968409c0c4bdfe1dde655d08c 100644 (file)
Binary files a/img/bluehost.png and b/img/bluehost.png differ
diff --git a/img/eventloop.dot b/img/eventloop.dot
new file mode 100644 (file)
index 0000000..3c0c3b3
--- /dev/null
@@ -0,0 +1,30 @@
+
+digraph G {
+    rankdir = LR
+       
+    node
+    [
+        fontname    = "Inconsolata"
+        fontsize    = 20
+        shape       = record
+        style       = rounded
+        margin      = "0.2,0.2"
+    ]
+
+    edge
+    [
+        fontname    = "Inconsolata"
+        fontsize    = 18
+        arrowhead   = vee
+        arrowtail   = vee
+        arrowsize   = 2
+    ]
+
+    "Event source 1" -> "Wait for\nan event\nto happen"
+    "Event source 2" -> "Wait for\nan event\nto happen"
+    "Event source n" -> "Wait for\nan event\nto happen"
+
+    "Wait for\nan event\nto happen" -> "Handle an\nevent" [label="Something happened...\n", tailport="n", headport="n"]
+    "Handle an\nevent" -> "Wait for\nan event\nto happen" [tailport="s", headport="s"]
+}
+
diff --git a/img/pizza.jpg b/img/pizza.jpg
new file mode 100644 (file)
index 0000000..f92a76d
Binary files /dev/null and b/img/pizza.jpg differ
index 6841507d42e97e238098b325112ac66b54b337b0..16f2f5c0439b4377c8ed931153d5255c126e2932 100644 (file)
--- a/notes.txt
+++ b/notes.txt
@@ -1,40 +1,66 @@
 
 Topics:
 
-Evolution of event-driven programming:
-- Wait for a key press or line of text.
-- Interrupts (hardware and software).
-- Modern event loops
+1. Evolution of event-driven programming:
+X Wait for a key press or line of text.
+X Interrupts (hardware and software).
+X Modern event loops
 
-How to write a modern event-loop.
-- kernel facilities (poll, select, etc.)
+2. Types of events in modern applications:
+X IO
+X Timer
+X User input
+X Signal
+X Anything that can spontaneously happen in the real world.
 
-Event-drive programming in Perl
-- POE
-- AnyEvent
-- IO::Async
+3. How to write a modern event-loop.
+X kernel facilities (poll, select, etc.)
 
-List of already-built event loops.
+4. List of already-built event loops.
 - EV
 - Glib
 
-Types of events in modern applications:
-- Data available
-- Timer
-- User input
-- Signal
-- Anything that can spontaneously happen in the real world.
+5. Event-driven programming in Perl
+- POE
+- AnyEvent
+- IO::Async
+- Mojo::IOLoop
 
-Exceptions in event-driven code.
+6. Special considerations
+- Exceptions in event-driven code.
+- SIGPIPE, EPIPE - might have more to do with long-lived processes rather than
+  just event-driven programming, but still something to watch out for...
 
-Promises:
+7. Promises:
 - Future
 - Future::AsyncAwait
 - Future::Utils
 
-Real-world uses for event-driven applications:
+8. Real-world uses for event-driven applications:
 - Webhooks
-- WebSockets
 - PubsubHubbub
 - msg queue
 
+
+
+
+Other topics:
+X What is event-driven programming?
+- Reactor: event loop that can receive multiple types of events and
+  demultiplex them, delivering them to appropriate handlers.
+- C10k problem
+- EDA (event-driven architecture)
+- Benefits of Event-driven
+
+Traditional programs:
+- CGI - web server calls your program, and your program does its thing and
+  finishes.
+- filters - grep, less, sed, etc. Like a function, the program takes its input
+  and produces some output.
+
+Perl features:
+- first-class subroutines
+
+- Can mix traditional architecture with event-driven (like docker that
+  provides both an http and command-line interface.
+
index 46dbe4085e44d73b2f1a40af890e2973997127c1..9eae8008ce65f65a0a2751af948d93738c50c4ee 100644 (file)
@@ -16,14 +16,389 @@ Charles McGarvey
 class:  center, middle
 name:   bluehost
 
-![Bluehost](img/bluehost.png)
-
-### https://bluehost.com/jobs
-
 ???
 - 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);
+```
+
+---
+## 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
+
+![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: ex-basicreactor
+
+## The basic reactor
+
+```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)
+]
+
 ---
 class: center, middle
 name:  conclusion
@@ -38,5 +413,5 @@ name:  last
 
 ### Thanks.
 
-</textarea><script src="https://gnab.github.io/remark/downloads/remark-latest.min.js"></script><script>var slideshow = remark.create({countIncrementalSlides: true, highlightLanguage: '', highlightLines: true, 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>
+</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>
 <!-- vim: set ts=4 sts=4 sw=4 tw=120 et ft=markdown nowrap: -->
This page took 0.045258 seconds and 4 git commands to generate.