ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/docs/pws2006/event.pod
Revision: 1.14
Committed: Thu Feb 2 19:59:04 2006 UTC (20 years, 8 months ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.13: +7 -0 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 =head1 Ereignisgesteuerte Programmierung - die Realität
2
3 =head2 Zusammenfassung
4
5 Ereignisgesteuerte Programmierung ist hinreichend bekannt. Trotzdem
6 wird sie relativ selten benutzt - in Modulen so gut wie garnicht. Ich
7 möchte hier verschiedene Arten der Ereignissteuerung sauber von anderen
8 Formen der Programmierung trennen, vorhandene Ereignismodule und ihre
9 Unterschiede vorstellen. Vor allem sollen Möglichkeiten gezeigt werden,
10 wie man als Modulautor - je nach gewünschtem Aufwand - verschiedene APIs
11 anbieten kann.
12
13
14 =head1 Ereignissteuerung - In aller Kürze
15
16 Ereignissteuerung ist - für mich - kein sehr exakt festgelegter Begriff
17 oder eine festgelegte Syntax. Daher will ich einige Beispiele für
18 verschiedene Arten bzw. Grade der Ereignissteuerung, wie sie in der Praxis
19 vorkommen, vorstellen.
20
21 Üblicherweise verwendet man Ereignissteuerung immer dann, wenn man
22 genügend Rechenzeit für die Verarbeitung vieler Aufgaben hat, jedoch durch
23 externe Umstände (I/O-Geschwindigkeit, Netzwerk, User klickt nicht schnell
24 genug :) gezwungen ist, auf Daten bzw. Ereignisse zu warten.
25
26 Ereignissteuerung bedeutet dann, ein Programm derart zu strukturieren,
27 daß es auf Ereignisse wartet und - möglichst schnell - reagiert. Die
28 Haupt-Eingabe besteht sozusagen in einem Strom von Ereignissen
29 (Event-Stream). Das Ziel der Ereignissteuerung ist es, die Gesamtdauer
30 aller Operationen zu verringern und die Reaktionsgeschwindigkeit zu
31 erhöhen.
32
33 Unter Unix gibt es eine zentrale Funktion, mit der ein Programm auf
34 Ereignisse warten kann: C<select> (bzw. auch C<pselect>/C<poll>, die sich
35 aber nicht von C<select> unterscheiden, sowie kompliziertere Methoden wie
36 realtime-Signale, die aber alle auf dasselbe hinauslaufen). C<select> kann
37 auf einen Timeout und auf die Möglichkeit, auf einen Filehandle schreiben
38 oder davon lesen zu können, warten. Dies reicht für alles aus, da unter
39 Unix "alles ein Dateihandle ist" (und wenn dies einmal nicht der Fall ist,
40 ist das gleich ein major pain in the ass und man tut gut daran, es auf
41 einen Dateihandle abzubilden).
42
43 Daher ist eine derartige Programmstruktur meist eine zentrale Schleife,
44 in der auf Ereignisse (definiert durch "Watcher") gewartet wird und
45 dann Funktionen aufgerufen werden, um auf diese Ereignisse zu reagieren
46 ("Callbacks"). Da C<select> etwas low-level ist, gibt es Bibliotheken
47 und Module, die diese Funktionalität in eine freundlichere Schnittstelle
48 gießen - das nennt man dan "Event-Modell".
49
50 Daraus folgt, daß das "Hauptprogramm" der Aufruf dieser Schleife/dieses
51 Event-Modells ist, und alle Ereignisse in Unterfunktionen behandelt werden
52 müssen. Daher lassen sich in einem Programm auch sehr schwer mehrere
53 Event-Modelle miteinander mischen, da nur jeweils eines die Kontrolle über
54 den Programmablauf haben kann.
55
56
57 =head1 Formen der Ereignissteuerung
58
59 =head2 Linearer Ablauf - "Nicht ereignisgesteuert"
60
61 Wir alle kennen (hoffe ich) LWP, mit dem man sehr einfach Webseiten u.ä.
62 abrufen kann:
63
64 use LWP::Simple;
65 print get "http://www.cpan.org/";
66
67 Ein heutiger Rechner kann das in Millisekunden erledigen - wenn es länger
68 dauert, liegt es nicht am eigenen Rechner sondern am Netz. LWP arbeitet
69 intern nämlich folgendermaßen:
70
71 $socket = new IO::Socket ...;
72 print $socket $request;
73 $response = read $socket;
74 return $response;
75
76 Die Wartezeit entsteht vor allem beim Lesen der Antwort, zu kleineren
77 Teilen beim Verbindungsaufbau und selten beim Schreiben der Anforderung.
78
79 Prinzipiell gibt es auch hier eine Folge von Ereignissen, auf die gewartet
80 wird - allerdings immer nur eines, d.h. die Ereignisse "steuern" den
81 Programmablauf nicht. Daher ist dies keine Ereignissteuerung.
82
83 Der Vorteil einer solchen Struktur ist ihre Einfachheit - die zeitliche
84 und logische Abfolge des Requests stehen klar hintereinander.
85
86 Diese Einfachheit läßt sich auch ereignisgesteuert erreichen - allerdings
87 mit beträchtlichem Mehraufwand an anderer Stelle, den man jedoch gut in
88 andere Module verpacken kann.
89
90 =head3 blocking vs. "blocking"
91
92 Ein paar Worte noch zu blocking vs. non-blocking, bzw. blocking vs.
93 andere Arten von blocking: Unter Unix kann man Filehandles in den
94 "non-blocking"-Zustand versetzen. Dies ist manchmal hilfreich, hat aber
95 mit Ereignissteuerung wenig zu tun: Zum Lesen von Sockets braucht man
96 dies nicht, und bei Dateien zeigt es keine Wirkung (es wirkt nur auf
97 Dateihandles, bei denen die Menge an Daten unbekannt ist). In vielen
98 Fällen ist es sogar hinderlich.
99
100 So ist es bei vielen Protokollen (whois, finger, viele HTTP-Anfragen)
101 fast sicher, daß die Anfrage komplett in den TCP-Buffer geschrieben
102 werden kann. Passt er nicht, blockiert der Prozess, aber wenn dies
103 unter normalen Umständen nicht vorkommt, ist dies meistens akzeptabler
104 als die Programmstruktur nur für diesen zu verkomplizieren, wie dies
105 bei einem non-blocking Dateihandle nötig wäre (leider erzeugt das
106 C<IO::Socket>-Modul alle Socket-Handles per default non-blocking, was
107 meiner Meinung nach mehr Probleme schafft als löst).
108
109 In diesem Dokument wird der Begriff "blockierend" nicht als Gegensatz zu
110 diesem C<O_NONBLOCK> gebraucht, sondern allgemein verwendet, um jeglichen
111 Aufruf zu beschreiben, der auf bestimmte Ereignisse warten muss, statt
112 sofort zurückzukehren. Dies schließt nicht nur Dinge wie das Lesen von
113 Sockets, wenn keine Daten vorhanden sind, oder sleep()-ähnliche Aufrufe ein,
114 sondern auch Dinge wie das Lesen von einer Datei auf der Festplatte oder
115 von NFS, wenn die Daten nicht im RAM sind.
116
117 =head2 State-Maschinen
118
119 Um nun auf Ereignisse in beliebiger Folge reagieren zu können, muss man
120 jedes Ereignis ("Verbindung aufgebaut", "Daten können geschrieben werden",
121 "Daten können gelesen werden") in einer Unterroutine abarbeiten.
122
123 Bei Frameworks wie POE werden alle diese Unterroutinen als Methoden eines
124 Objektes aufgefasst. Das Objekt speichert den Zustand (z.B. "Aufbauphase",
125 "Antwortphase"). Bei jedem Ereignis muss der Zustand aus dem Objekt
126 "deserialisiert" werden, die Methode aufgerufen werden und der neue
127 Zustand wieder serialisiert werden.
128
129 Für das Finger-Protokoll würde das in etwa so aussehen (völlig fiktive
130 Syntax):
131
132 # fiktive "erwarte folgendes Ereignis"-Methode:
133 sub on_event {
134 my ($self, $filehandle, $watch_type, $method) = @_;
135 ...
136 }
137
138 # wird aufgerufen, wenn Daten geschrieben werden können
139 sub can_write {
140 my ($self) = @_;
141
142 # Request blockierend schreiben, da klein
143 print {$self->{fh}} $self->{username};
144 # sorge dafür, daß beim nächsten Mal can_read aufgerufen wird
145 $self->on_event ($self->{fh}, "readable", "can_read");
146 }
147
148 # wird aufgerufen, wenn Daten vorliegen
149 sub can_read {
150 my ($self) = q_;
151
152 sysread $self->{fh}, $self->{response}, length $self->{response}, 8192
153 or $self->on_event (undef, undef, "finish");
154 }
155
156 C<can_write> schreibt den Request und sorgt dann dafür, daß der Zustand
157 "can_read" angenommen wird, bei dem die Methode desselben Namens aufgerufen
158 wird, sobald Daten vom Dateihandle gelesen werden können.
159
160 C<can_read> liest nun die Daten ein und verbleibt im aktuellen Zustand,
161 solange Daten gelesen werden können. Bei Fehlern oder bei Verbindungsende
162 wird in den Zustand "finish" gesprungen. Typischerweise gibt es noch
163 andere Methoden, die z.B. bei Fehlern aufgerufen werden können.
164
165 Persönlich finde ich diesen Stil äußerst masochistisch und verwirrend,
166 aber es soll Programmierer geben, die anders denken. Für mich zählt aber
167 vor allem die Menge an Quellcode, die erzeugt und gewartet werden muss,
168 sowie das weite Auseinanderliegen wichtiger Stellen - der Ablauf ist nicht
169 klar.
170
171 Trotzdem ist dieser Stil häufig vertreten - meistens nicht in dieser
172 Klarheit sondern in Kombination mit anderen Stilen (im obigen Beispiel
173 wird z.B. die Anfrage nicht ereignisgesteuert geschrieben) - in der
174 Realität muss man zwischen Klarheit, Geschwindigkeit, Abhängigkeiten und
175 vielem mehr abwägen!
176
177 =head2 Continuation Passing
178
179 Ein etwas weniger häufig benutzter Stil ist Continuation Passing. Die
180 Ursache für das seltenere Vorkommen liegt I<meiner Meinung> nach darin,
181 daß dies in anderen (verbreiteten) Programmiersprachen (C, Python, ...)
182 weniger oder garnicht gut realisierbar ist, bzw. dies etwas Verständnis
183 und Wissen erfordert, was heutzutage nicht mehr gefördert wird.
184
185 Wie dem auch sei, hier ein Beispiel wie man eine Datei öffnet und einige
186 Daten liest, und sie dann löscht, mit C<IO::AIO> und voller Fehlerbehandlung:
187
188 aio_open "tempfile", O_RDONLY, 0, sub {
189 my $fh = shift
190 or die "tempfile: $!";
191
192 my $buf;
193 aio_read $fh, 0, 8192, $buf, 0, sub {
194 $_[0] > 0 # keine leeren Files
195 or die "tempfile: $!";
196
197 aio_unlink "tempfile", sub {
198 $_[0] and die "tempfile: $!";
199
200 print "read successfully up to 8192 bytes, and nuked file.\n";
201 };
202 };
203 };
204
205 Das Schema ist immer das gleiche: Bei jeder Anforderung (open/read/unlink)
206 wird eine Closure übergeben (die Zustandsdaten und Reaktion verkörpert),
207 die nach Beendigung der Anforderung aufgerufen wird. C<aio_open> kehrt
208 sofort zurück, aber die Closure wird erst dann aufgerufen, wenn die Datei
209 geöffnet wurde oder ein Fehler auftrat.
210
211 Der Name dieses Stils kommt daher, daß bei jeder Anforderung die komplette
212 "Fortsetzung" (Continuation) des Programmablaufes mit übergeben wird.
213
214 Die Vorteile des Stils liegen darin, daß die logische (nicht zeitliche)
215 lineare Reihenfolge klar bleibt und daß alles nahe beieinander
216 steht. Die Nachteile sind das zunehmende Nesting und die weniger flexiblen
217 Reaktionsmöglichkeiten. Außerdem bietet sich nicht jede Art der
218 Anforderung gleichermaßen an: C<IO::AIO> fördert diesen Stil. Bei C<Event> wird
219 es meistens etwas umständlicher, da mehr Parameter zu übergeben sind und
220 die Watcher nach jedem Ereignis per Hand gelöscht werden müssen.
221
222 Beides läßt sich umgehen, indem man sich in Richtung State-Maschine
223 bewegt:
224
225 sub do_open {
226 aio_open ..., sub {
227 do_read (@_);
228 };
229 }
230
231 sub do_read {
232 my ($fh) = @_;
233
234 aio_read ..., sub {
235 do_unlink ($fh, @_);
236 };
237 }
238
239 sub do_unlink {
240 ...
241 }
242
243 Das ist erstmal umständlicher, aber sehr langen Closures manchmal
244 vorzuziehen. Der Zustand wird hier nicht in einem Objekt gespeichert,
245 sondern in den Closures (z.B. C<$fh> bei C<aio_read>).
246
247 =head2 Coroutinen/Threads/Prozesse
248
249 Der letzte Stil besteht darin, für jeden logischen Ablauf eine Coroutine,
250 einen Thread oder einen Prozess zu benutzen. Die Nachteile nenne ich
251 gleich: Coroutinen sind nicht in Perl integriert und daher etwas
252 unportabler als Perl selbst, Threads stehen in Perl überhaupt nicht zur
253 Verfügung, und Prozesse sind relativ große Dinger, von denen man sich
254 nicht wirklich viele halten möchte.
255
256 Das obige C<IO::AIO>-Beispiel sähe mit Hilfe von C<Coro::AIO> so aus:
257
258 my $fh = aio_open "tempfile", O_RDONLY, 0
259 or die "tempfile: $!";
260 aio_read $fh, 0, 8192, my $buf, 0
261 or die "tempfile empty or read error ($!)";
262 aio_unlink "tempfile";
263
264 Meiner Meinung nach ist dies die klarste Methode, komplett
265 ereignisgesteuerte Abläufe darzustellen. Der Overhead, der durch die
266 Verwaltung von Coroutinen entsteht, ist allerdings höher als der anderer
267 Ansätze (allerdings niedriger als bei Threads oder Prozesse), und stellt
268 daher das andere Ende des Overhead vs. Einfachheit-Gegensatzes dar.
269
270
271 =head1 Event-Modelle
272
273 Perl strotzt geradezu vor Event-Modellen. Das ist keine gute Nachricht, da
274 sie alle inkompatibel sind.
275
276 Entstanden ist diese Situation dadurch, daß C<select> zwar prinzipiell
277 alles ermöglicht, aber nicht sehr freundlich ist. Daher entstand schnell
278 der Wunsch nach Wrapper und angenehmeren Schnittstellen. Vor allem
279 GUI-Toolkits bringen im allgemeinen ein eigenes Event-Modell mit, da hier
280 der Bedarf nach Ereignissteuerung besonders hoch ist, um die Latenz für
281 Benutzerinteraktionen niedrig zu halten.
282
283 Leider wird dies meistens nebensächlich behandelt - Gtk+/Glib z.B. hat ein
284 sehr umständliches Event-Modell, daß sich auch nicht durch Exaktheit z.B.
285 bei Timern hervortut.
286
287 Im folgenden will ich einige Event-Modelle kurz ansprechen:
288
289 =head2 Event
290
291 Das "Standard"-Eventmodul von Perl. Sollte es zumindest sein. Es bietet
292 mit Abstand die vernünftigste API! (!!) (!!!) (Wirklich!)
293
294 Die beiden wichtigsten Ereignisse, auf die ein Event-Modell reagieren
295 können muss, sind IO-Ready-Ereignisse (Daten können gelesen/geschrieben
296 werden) und Timer (Zeitsteuerung). Außerdem braucht man noch eine
297 Schnittstelle für die Hauptschleife.
298
299 Mit Event sieht dies so aus:
300
301 # Auf Daten warten:
302 Event->io (fd => $fh, poll => 'r', cb => sub {
303 # es kann nichtblockierend gelesen werden
304 });
305
306 # Jede Stunde was tun:
307 Event->timer (after => 3600, interval => 3600, cb => sub {
308 # tue was
309 });
310
311 # Hauptschleife:
312 Event::loop;
313
314 Leider ist die Entwicklung des Event-Modules eingeschlafen - es ist zwar
315 stabil und hat keine bekannten/relevanten Fehler, aber Patches z.B. für
316 die Unterstützung (in bestimmten Situationen) besser skalierender
317 Betriebssystem-Schnittstellen als C<select> wandern nicht oder nur halb in
318 die Distribution.
319
320 Dennoch stellt Event nahezu das Optimum dar.
321
322 =head2 Glib (Gtk2)
323
324 Glib implementiert das Event-Modell für Gtk+, sowie noch vieles weiteres,
325 wie z.B. Datentypen und Klassen (was die Unterstützung für Skript-Sprachen
326 so angenehm macht).
327
328 Die drei Beispiele lauten in Glib-Lingo so:
329
330 # Auf Daten warten:
331 add_watch Glib::IO fileno $fh, ['in', 'hup'], sub {
332 # es kann nichtblockierend gelesen werden
333
334 1 # wir wollen weitere Ereignisse dieser Art
335 };
336
337 # Jede Stunde was tun:
338 add Glib::Timeout 3600_000, sub {
339 # tue was
340
341 1 # auch nächste Stunde sind wir wieder für Sie da
342 };
343
344 # Hauptschleife:
345 1 while Glib::MainContext->default->iteration (1);
346
347 # bzw.in Gtk2-Programmen:
348 main Gtk2;
349
350 Interessanterweise erlaubt es Glib, die eigentliche C<select> (bzw.
351 hier: C<poll>) Funktion durch eine eigene zu ersetzen, was z.B. das
352 C<Glib::Event>-Modul ausnutzt.
353
354 =head2 Tk
355
356 Tk ist das traurigste Beispiel für ein Event-Modell: entweder etwas
357 ist nicht implementiert, oder es ist kaputt. Dennoch lassen sich die
358 wichtigsten Ereignisse mit Einschränkungen abbilden:
359
360 # Richtig, wir brauchen tatsächlich ein Fenster!
361 $mw = new MainWindow; # Namespace-Invasion
362 withdraw $mw; # Flickerflacker
363
364 # Auf Daten warten, nur ein watcher per filehandle
365 $mw->fileevent ($fh, readable => sub {
366 # es kann nichtblockierend gelesen werden
367 });
368
369 # _Ungefähr_ jede Stunde was tun
370 my $cb; $cb = sub {
371 # tue was
372
373 $mw->after (3600_000, $cb);
374 };
375 $mw->after (3600_000, $cb);
376
377 # Hauptschleife:
378 Tk::MainLoop;
379
380 An Tk sieht man deutlich, daß die Priorität eines Windowing-Toolkits eben
381 beim Windowing liegt, und nicht in der Event-API.
382
383 =head2 Qt
384
385 Besitzt jemand Informationen zu Qt? Perl+Qt scheint mir ziemlich tot zu
386 sein...
387
388
389 =head1 Das Problem für Modulautoren
390
391 Das Problem für Modulautoren ist ganz einfach: Das Hauptprogramm kann
392 immer nur ein Event-Modell gleichzeitig benutzen. Benutzt man in seinem
393 Modul das gleiche, ist man fein raus, benutzt man ein anderes, geht es
394 nicht. Garnicht.
395
396 Also versuchen es viele Modul-Autoren garnicht erst und bieten nur eine
397 nicht ereignisgesteuerte Schnittstelle an - benutzt man LWP in einem
398 Gtk+-Programm, hängt es, bis die Daten da sind - nicht gerade toll.
399
400
401 =head1 Lösungen/Workarounds
402
403 Welche Lösungen und Workarounds gibt es für dieses Problem?
404
405 =head2 Wozu? Blocking reicht - LWP
406
407 Naja, dies ist kein Workaround, aber wie gesagt die Norm unter den
408 vorhanden Modulen (wobei das keine Ausrede ist, um nicht wenigstens ein
409 Modell wie z.B. Event zu unterstützen...).
410
411 LWP ist dabei nur ein Beispiel:
412
413 my $data = get $url;
414
415 So sieht es auch bei fast allen Net::*-Modulen aus. Es gibt Workarounds
416 (technisch ausgedrückt "böse Hacks"), um auch solche Module zu zwingen,
417 aber sie sind bestenfalls nicht schön, und schlimmstenfalls kaputt, wenn
418 die zugrundeliegende Bibliothek globale Variablen auf mit Parallelität
419 nicht vereinbarer Weise benutzt - man müsste reinschauen können. Solche
420 Workarounds können meistens nur im Hauptprogramm eingesetzt werden.
421
422 =head2 Überlass es dem User - KGS::Protocol
423
424 Dies ist eine weitere, praktikable Möglichkeit, an das Problem
425 heranzutreten, ein Beispiel dafür ist das (völlig unbedeutende)
426 KGS::Protocol-Modul:
427
428 my $socket = new IO::Socket::INET ... # blockierender connect
429 $socket->blocking (0); # seufz
430
431 my $conn = new KGS::Protocol;
432
433 ...
434
435 Event->io (fd => $socket, poll => 'r', cb => sub {
436 sysread $socket, my $buffer, 8192;
437
438 $conn->feed_data ($buffer);
439 });
440
441 Das C<KGS::Protocol>-Modul weiss recht wenig über Sockets oder über
442 Dateihandles - das bleibt dem Benutzer des Moduls überlassen. Dieser
443 muss irgendwie (z.B. mit C<Event>) die Daten beschaffen und sie mit
444 C<feed_data> an das Modul übergeben.
445
446 Schreiben geschieht immer noch blockierend, was bei C<KGS::Protocol> in
447 der Praxis keine Relevanz hat. Das Modul läßt sich auch ohne Dateihandles
448 betreiben, was z.B. für Replays von aufgezeichneten Protokollen benutzt
449 werden kann - in seltenen Fällen ist das extrem hilfreich.
450
451 Ein anderes Modul, C<Net::Knuddels>, erlaubt diese Freiheit nicht,
452 hat aber dafür eine einfachere API. C<Net::Knuddels> braucht zwei
453 Ereignistypen: Eine Verzögerung um Flooding zu vermeiden und das "Daten
454 können gelesen werden"-Ereignis.
455
456 Das sieht dann so aus:
457
458 $client = new Net::Knuddels::Client
459 PeerAddr => "213.61.5.150:2710",
460 command_wait => sub {
461 my ($client, $wait) = @_;
462 Event->timer (after => $wait, cb => sub { $client->command_cb });
463 };
464
465 Event->io (
466 fd => $client->fh,
467 poll => 'r',
468 cb => sub {
469 $client->ready
470 or $_[0]->w->cancel;
471 });
472
473 Mit C<command_wait> übergibt man einen Callback, der nach einer bestimmten
474 Zeit (C<$wait>) die C<command_cb>-Methode aufrufen soll. Wie er das
475 macht, ist relativ wurscht. Die Default-Implementation des Moduls
476 schläft einfach die entsprechende Zeit und ruft dann direkt die
477 C<command_cb>-Methode auf. Im obigen Beispiel wird ein Time-Watcher
478 erzeugt, der C<command_cb> aufruft, und kehrt dann sofort zurück.
479
480 Diese Methode funktioniert, weil das Problem garnicht erst gelöst
481 wird: Es wird lediglich zum Aufrufer hin verlagert. Ist der Aufrufer
482 das Hauptprogramm, muss es Event-Watcher erzeugen, ist der Aufrufer ein
483 anderes Modul, hat dies wieder das gleiche Problem - entweder legt es ein
484 Event-Modell fest oder er schiebt es wieder zu seinem Aufrufer.
485
486 Hierbei muss der Aufrufer entsprechend aufgeklärt werden, was die API
487 etwas verkompliziert.
488
489 =head2 Leg dich fest - Coro::Event
490
491 Eine weitere Methode ist es, sich festzulegen. Das Coro-Modul benötigte
492 dringend Events, und hat sich auf das Event-Modul eingeschossen (hey, es
493 ist der Standard...). C<Coro::Event> ist daher recht effizient und einfach
494 zu benutzen (nahezu gleiche API wie C<Event> selbst), unterstützt aber
495 (zur Zeit) auch nur das Event-Modul.
496
497 Das ist nicht unbedingt schlimmer als nur eine blockierende API
498 anzubieten, da man schlimmstenfalls immer eine blockierende API erstellen
499 kann - so laufen alle Coro::Event-Benutzer untereinander ereignisgesteuert,
500 aber z.B. ein Glib-Benutzer wird blockiert.
501
502 =head2 Bilde ein Modell auf ein anderes ab - Glib::Event
503
504 Manchmal hat man Glück und benutzt zwei Event-Modelle, die man mit Gewalt
505 kombinieren kann. Eine häufige Kombination ist Gtk2 (also Glib) zusammen
506 mit Event. Und die Lösung lautet C<Glib::Event>:
507
508 use Gtk2 -init;
509 use Glib::Event;
510
511 Jetzt kann man beliebige Module benutzen, die selbst Event benutzen, oder
512 direkt Event benutzen, wenn einem dessen API mehr zusagt:
513
514 use Event;
515
516 Event->timer (after => 1, interval => 1, cb => sub { ... });
517
518 main Gtk2;
519
520 Tatsächlich funktioniert C<Glib::Event> sogar unabhängig vom Glib-Modul mit
521 jedem Programm, daß selbst die libglib benutzt und Perl z.B. einbettet.
522
523 C<Glib::Event> bringt die libglib dazu, intern Event zu benutzen. Das
524 macht aus Glib noch keinen Event-Benutzer (man muss immer noch die
525 Glib-Hauptschleife aufrufen, C<Event::loop> funktioniert nicht), begrenzt
526 das Problem aber immerhin auf den Aufruf der Hauptschleife, der nur einmal
527 pro Programm vorkommt.
528
529 Tatsächlich kann man sich mit Coroutinen behelfen, indem man die
530 Gtk+-Hauptschleife in eine Coroutine verlagert:
531
532 use Gtk2 -init;
533 use Coro;
534 use Coro::Event;
535 use Glib::Event;
536 async { main Gtk2 };
537 # tue andere Dinge
538 Event::loop;
539
540 =head2 Threads (?) und Prozesse
541
542 Threads würden ebenfalls helfen, da man zumindest theoretisch jedes
543 Event-Modell in seinem eigenen Thread laufen lassen könnte. Leider nur
544 theoretisch, da die meisten Event-Modelle damit nicht klarkommen, und
545 Threads von Perl sowieso nicht unterstützt werden (der irrige Begriff
546 "Thread" bezeichnet in Perl eine Prozessemulation auf Thread-Basis, der
547 eingeführt wurde, um die extrem langsame Prozess-Erzeugung unter Windows
548 zu beschleunigen und später aus nicht nachvollziehbaren Gründen auf Unix
549 portiert wurde. Perl-"Threads" vereinigen die Nachteile von Prozessen und
550 Threads mit extrem hohem Overhead ohne die jeweiligen Vorteile zu bieten).
551
552 Bleiben also nur separate Prozesse, was nicht sehr angenehm ist, aber in
553 vielen Fällen durchaus gangbar. Z.B. kann man LWP auf diese Weise begrenzt
554 parallelisieren:
555
556 # Warnung: keine Fehlerbehandlung
557 if (open my $subproc, "-|") {
558 Event->io (fd => $subproc, poll => 'r', cb => sub {
559 local $/;
560 my $webpage = <$subproc>;
561 });
562 } else {
563 print get $url;
564 }
565
566 Mit Perl-Threads gestaltet es sich etwas umständlicher und vor allem
567 wesentlich ressourcenintensiver (außer unter Windows, wo Prozesse sowieso
568 mit Threads emuliert werden und der Aufwand daher gleich (und gleich
569 I<hoch>) ist).
570
571 =head2 AnyEvent
572
573 Ein relativ neues Modul ist C<AnyEvent>. Der Name ist angelehnt
574 an C<AnyDBM_File>, da es wie dieses Modul versucht, eine
575 implementationsunabhängige API zu liefern.
576
577 AnyEvent ist also kein eigenes Event-Modell, sondern nur eine
578 Schnittstelle zu einem existierenden. Der Vorteil für Modul-Autoren
579 ist nun, daß sie AnyEvent als Event-Modell benutzen können, sich aber
580 gleichzeitig sicher sein können, daß ihr Modul mit Event, Gtk+, Tk oder
581 sogar rxvt-unicode zusammenarbeiten. Das Modul ist erweiterbar, so daß
582 jede weitere Implementation automatisch mit vorhandenen Modulen läuft.
583
584 Natürlich kann AnyEvent nur das unterstützen, was alle verwendeten
585 Event-Modelle unterstützen. Den kleinsten gemeinsamen Nenner sozusagen,
586 den man schnell mit C<Tk> identifizieren kann :)
587
588 Die API ist an die Event-API angelehnt, unterscheidet sich aber in einigen
589 Punkten. Die drei Standardbeispiele sehen bei C<AnyEvent> so aus:
590
591 # Auf Daten warten:
592 my $watcher = AnyEvent->io (fh => $fh, poll => 'r', cb => sub {
593 # es kann nichtblockierend gelesen werden
594 });
595 # wird der watcher vergessen, wird er zerstört, deshalb muss man
596 # ihn aufbewahren
597
598 # _Ungefähr_ jede Stunde was tun:
599 my $w;
600 my $cb; $cb = sub {
601 # tue was
602
603 $w = AnyEvent->timer (after => 3600, cb => $cb);
604 };
605 $cb->();
606
607 # Hauptschleife:
608 AnyEvent->condvar->new->wait;
609
610 Statt eines Filedeskriptors oder Handles akzeptiert AnyEvent nur
611 letzteren (C<fh> statt C<fd>). Pollen kann man z.Zt. nur nach 'r'ead oder
612 'w'rite -Ereignissen, und Timer sind immer relativ zu "jetzt" und feuern
613 nur einmal.
614
615 Am fremdartigsten ist sicher das, was unter "Hauptschleife"
616 steht: AnyEvent zielt vor allem auf Modul-Autoren. Diese brauchen
617 manchmal eine Schnittstelle in die Hauptschleife, ohne sie direkt
618 aufzurufen. C<condvar>s (Condition Variables, Bedingungsvariablen) kann
619 man sich am ehesten als "Fertig-Indikator" vorstellen. Jede C<condvar>
620 hat zwei Methoden: C<wait>, mit dem auf das Erreichen der Bedingung
621 gewartet werden kann, und C<broadcast>, mit der an alle Interessenten ein
622 "Bedingung erfüllt"-Signal gesendet werden kann.
623
624 Beispielsweise implementiert das folgende Fragment eine Art interaktive
625 Shell, deren "quit"-Befehl das Programm beenden soll:
626
627 use AnyEvent;
628
629 my $want_to_quit = AnyEvent->condvar;
630
631 my $io_watcher = AnyEvent->io (fh => \*STDIN, poll => 'r', cb => sub {
632 my $command = <STDIN>;
633
634 $command eq "quit"
635 and $want_to_quit->broadcast
636 });
637
638 $want_to_quit->wait;
639
640 Dieses Beispiel benutzt eine Condition-Variable namens C<$want_to_quit>
641 ("Beenden erwünscht"), die die Bedingung (wer hätte es gedacht) "Benutzer
642 wünscht das Beenden des Programms" ausdrückt.
643
644 C<< $want_to_quit->wait >> wartet daher, bis diese Bedingung
645 eintritt. Nebenher läuft aber die Ereignisverarbeitung weiter, bis
646 der Event-Callback das Kommando "quit" einliest und das Eintreten der
647 Bedingung C<broadcast>et.
648
649 In Modulen benutzt man C<condvars> am besten pro "Request", um das
650 Eintreten bestimmer Zustände (meistens "fertig") zu repräsentieren.
651
652 Wie man das macht und wozu das dient beschreibt der nächste Abschnitt.
653
654
655 =head1 Fallbeispiel Modul-API: IO::AIO und Coro::AIO
656
657 Das C<IO::AIO>-Modul bietet eine Schnittstelle für asynchrones I/O
658 an. D.h. man kann damit Dateien lesen, schreiben, löschen und vieles
659 mehr, ohne daß man auf das Ergebnis warten müsste. Keine Frage, es ist
660 ereignisgesteuert, oder besser gesagt, es wandelt I/O-Anfragen in einen
661 Strom von Ergebnisereignissen um.
662
663 Es stammt aus der Zeit vor AnyEvent und sollte deshalb völlig
664 unabhängig vom verwendeten Event-Modell benutzt werden können. Dies
665 wird erreicht, indem es einen Dateideskriptor zur Verfügung
666 stellt, der lesbar wird, sobald Ergebnisse vorliegen. Diesen
667 Dateideskriptor (C<IO::AIO::poll_fileno>) übergibt man einfach seinem
668 bevorzugten Event-Modell und sorgt dafür, daß bei Lesbarkeit die
669 C<IO::AIO::poll_cb>-Funktion aufgerufen wird.
670
671 C<IO::AIO> gibt in der Dokumentation Beispiele für die Integration in
672 eine Menge Event-Modelle an:
673
674 # AnyEvent
675 open my $fh, "<&=" . IO::AIO::poll_fileno or die "$!";
676 my $w = AnyEvent->io (fh => $fh, poll => 'r',
677 cb => sub { IO::AIO::poll_cb });
678
679 # Event
680 Event->io (fd => IO::AIO::poll_fileno,
681 poll => 'r',
682 cb => \&IO::AIO::poll_cb);
683
684 # Glib/Gtk2
685 add_watch Glib::IO IO::AIO::poll_fileno,
686 in => sub { IO::AIO::poll_cb; 1 };
687
688 # Tk
689 Tk::Event::IO->fileevent (IO::AIO::poll_fileno, "",
690 readable => \&IO::AIO::poll_cb);
691
692 # Danga::Socket
693 Danga::Socket->AddOtherFds (IO::AIO::poll_fileno =>
694 \&IO::AIO::poll_cb);
695
696 Das Prinzip ist wirklich immer das gleiche.
697
698 Man kann IO::AIO auch ohne ein Event-Modell benutzen:
699
700 # jede Menge Anfragen
701 aio_xxx ... for 1..100000000;
702
703 # warte bis es keine ausstehenden Requests mehr gibt:
704 IO::AIO::poll_wait, IO::AIO::poll_cb
705 while IO::AIO::nreqs;
706
707 # naja, in neueren Versionen geht es auch so:
708 IO::AIO::flush;
709
710 Das Modul C<Coro::AIO> bildet die C<IO::AIO>-API auf eine blockierende
711 aber Coroutinen-kompatible API ab. Dies geschieht programmatisch (es wurde
712 also nicht für jede IO::AIO::aio_*-Funktion eine Coro::AIO::aio_*-Funktion
713 implementiert).
714
715 Um dem Benutzer die Qual der Wahl eines Event-Modells zu ersparen, erzeugt
716 C<Coro::AIO> gleich einen AnyEvent-Watcher:
717
718 our $FH; open $FH, "<&=" . IO::AIO::poll_fileno;
719 our $WATCHER = AnyEvent->io (fh => $FH, poll => 'r'
720 cb => sub { IO::AIO::poll_cb });
721
722 Es ist nicht tragisch, wenn der mal nicht aufgerufen wird, weil der
723 Benutzer von C<Coro::AIO> andere Vorstellungen hat, solange nur
724 irgendjemand C<IO::AIO::poll_cb> aufruft.
725
726
727 =head1 Fallbeispiel Modul-API: Net-FCP und AnyEvent
728
729 C<Net::FCP> ist für das Freenet in etwa das, was LWP fürs Web ist. Meiner
730 Meinung nach ist die API von C<Net::FCP> geradezu ideal, da sie eine
731 sehr einfache Benutzung erlaubt (ähnlich LWP und LWP::Simple), und
732 trotzdem kompliziertere Anwendungen ermöglicht.
733
734 Freenet ist ein typisches Anfrage-Antwort-Protokoll, genau wie
735 HTTP. Die wichtigste Methode ist die C<client_get>-Methode, mit der man
736 Freenet-Objekte herunterladen kann:
737
738 my $fcp = new Net::FCP;
739
740 my $data = $fcp->client_get (
741 "freenet:SSK@xK6UnCmOBL1bMf-VZBDTQfvYTFwPAgM/LiberalDecalogue//"
742 );
743
744 Die Methode verhält sich (fast) wie C<LWP::Simple::get>: sie wartet so
745 lange, bis das Ergebnis angekommen ist oder ein Fehler aufgetreten ist
746 (letztere werden durch Exceptions weitergegeben).
747
748 =head3 Blockierende API
749
750 Alle Anfragen des Freenet-Protokolls (neben client_get gibt es noch viele
751 weitere) besitzen eine gleichnamige Methode, die eine Verbindung aufbaut,
752 die Anfrage losschickt und auf Antwort wartet:
753
754 my $data = $fcp->client_get ($uri);
755 $fcp->client_put ($uri, $metadata, $data, $htl);
756 $fcp->generate_chk ($metadata, $data);
757 ...
758
759 Für einfache Anwendungen reicht diese Schnittstelle völlig aus. Da Net::FCP
760 intern ereignisgesteuert ist, laufen solche Anfragen aber auch problemlos
761 in einer eigenen Coroutine, parallel zu anderen Anfragen, ohne daß der
762 aufrufende Code (oder Net::FCP) irgendetwas Spezielles machen müsste.
763
764 =head3 Nichtblockierende API
765
766 Tatsächlich sind alle Methoden autogeneriert (wie, wird noch beschrieben),
767 die Freenet-Abfragen durchführen, d.h. sie mussten nicht mal geschrieben
768 werden. Tatsächlich müssen "nur" Methoden geschrieben werden, die eine
769 Transaktion starten:
770
771 my $transaction = $fcp->txn_client_get ($uri);
772
773 Diese Methoden erzeugen lediglich ein neues Objekt (eine Transaktion), das
774 den Zustand der gesamten Protokollabfrage darstellt und kehren I<sofort>
775 zum Aufrufer zurück. Man kann der Transaktion einen Callback übergeben,
776 der aufgerufen wird, sobald ein Ergebnis vorliegt:
777
778 $transaction->cb (sub {
779 # Juchhee, wir haben die Daten! Oder einen Fehler...
780 });
781
782 Und natürlich kann man das Ergebnis auch abfragen:
783
784 my $data = $transaction->result;
785 # Entweder werden hier die Daten zurückgegeben,
786 # oder es wird eine Exception ausgelöst.
787
788 Wenn die Ergebnisse schon vorliegen, blockiert C<result> nicht, ansonsten
789 wartete es, bis dies der Fall ist.
790
791 Das allgemeine Prinzip ist, jede Anfrage in zwei Teile aufzuteilen: Start
792 der Transaktion und Ankunft der Ergebnisse.
793
794 =head2 Benutzung
795
796 Diese beiden APIs erlauben eine erstaunliche Vielfalt an Nutzungsstilen:
797
798 =head3 Blockierend
799
800 Ganz einfach blockierend. Hier wäre z.B. eine einfache, wget-artige
801 Applikation, die eine Freenet-URL herunterlädt und die Daten ausgibt:
802
803 # client_get liefetr eine Arrayref mit Metadaten und Daten.
804 print Net::FCP->new->client_get (shift)->[1];
805
806 =head3 Blockierend, mit Coroutinen
807
808 Das hypothetische Modul C<Net::Supergeil> benutzt das Net::FCP-Modul zum
809 Herunterladen von Videos. Leider ist es selbst nicht ereignisgesteuert und
810 blockiert den Aufrufer ein paar Tage.
811
812 Kein Problem, wir stecken den Aufruf in eine Coroutine:
813
814 use Coro;
815 # Lade/wähle das Event-Modell:
816 use Coro::Event;
817
818 async {
819 Net::Supergeil::lad_es_runter $uri, $file;
820 print "Daten sind in $file\n";
821 };
822
823 # tue etwas anderes...
824 ...
825 Coro::Event::loop;
826
827 Das funktioniert deshalb, weil Net::FCP ereignisgesteuert arbeitet
828 und Coro::Event, sofern keine Ereignisse vorliegen, einfach andere
829 Coroutinen ausführt. Obwohl Net::Supergeil keine sehr hilfreiche API zur
830 Verfügung stellt, kann man es trotzdem ereignisgesteuert einsetzen, weil
831 alle blockierenden Routinen, die es auf ruft, intern ereignisgesteuert
832 arbeiten. Dies ist zwar mit etwas Aufwand verbunden (ich betrachte "Coro"
833 hier als "Aufwand"), aber das ist allemal besser, als Forken zu I<müssen>
834 oder es garnicht zu I<können>.
835
836 =head3 Nichtblockierend, Parallel
837
838 Durch die Aufteilung in Start- und Ergebnisteile kann man die Anfragen
839 einfach parallelisieren (was bei Freenet extrem wichtig ist):
840
841 my @results = map $_->result,
842 map $fcp->txn_client_get ($_),
843 @uris;
844
845 Da mir gesagt wurde, C<map> sei sowas wie Magie, hier das ganze in
846 Javaspeak:
847
848 my @txns;
849 for my $url (@urls) {
850 push @txns, $fcp->txn_client_get ($url);
851 }
852 my @results;
853 for my $txn (@txns) {
854 push @results, $txn->result;
855 }
856
857 (Es gibt Leute, die behaupten, das wäre klarer und einfacher zu
858 maintainen).
859
860 Zuerst wird jede URL in eine Transaktion umgewandelt. Bis auf Erzeugen
861 einer Datenstruktur und einer Socket passiert dabei nicht viel, das ganze
862 geht also schnell.
863
864 Dann wird die C<result>-Methode jeder Transaktion bemüht. Da zu diesem
865 Zeitpunkt mit Sicherheit noch keine Ergebnisse vorliegen (schlicht
866 deshalb, weil nicht einmal der Verbindungsaufbau abgeschlossen ist),
867 blockiert C<result>.
868
869 Dies führt indirekt zu einem Sprung in die Hauptschleife des verwendeten
870 Event-Modells, wodurch alle Anfragen ins Rollen kommen und parallel
871 (genauer: zeitlich eng verzahnt) durchgeführt werden. Sind die Ergebnisse
872 einer Transaktion angekommen (manche dauern länger, manche sind schnell),
873 so wird die C<result>-Methode der nächsten Transaktion aufgerufen. Dann
874 gibt es wieder zwei Möglichkeiten: entweder es gibt schon Ergebnisse, dann
875 geht's sofort weiter, oder eben nicht, dann wird wieder blockiert und ein
876 bisschen weiter gearbeitet.
877
878 Das Schöne an dieser Art der Nutzung ist, daß überhaupt keine Aufrufe
879 irgendwelcher Event-Module auftauchen, und man sich auch nicht darum
880 kümmern braucht, welches Event-Modell benutzt wird.
881
882 =head3 Nichtblockierend, Continuation Passing
883
884 Das folgende Fragment lädt ein Freenet-Paket herunter. Ist es eine
885 Redirection, so lädt es die Seite herunter, auf die es zeigt:
886
887 $fcp->txn_client_get ($uri)->cb ({
888 my $data = $_[0]->result;
889 if (ist ein redirect) {
890 $fcp->txn_client_get ($redirect_uri)->cb ({
891 my $data = $_[0]->result;
892 # fertig
893 });
894 } else {
895 # fertig
896 }
897 });
898
899 Für die ausgelassenen Teile ("fertig") bietet sich eine
900 C<< AnyEvent->condvar >> an:
901
902 my $got_it = AnyEvent->condvar;
903
904 # und statt "fertig":
905 $got_it->broadcast;
906
907 =head3 Andere...
908
909 Prinzipiell läßt sich C<Net::FCP> auch in State-Maschinen
910 u.ä. einbauen: Net::FCP verhält sich wie ein Event-Modell für
911 Freenet-Ereignisse.
912
913 =head2 Implementation
914
915 Die Implementation ist vergleichsweise einfach und geradlinig. Ein gewisser
916 Grundaufwand ist nicht zu vermeiden, aber man erreicht mit wenig Aufwand
917 vergleichsweise viel.
918
919 Damit man wenig Aufwand treiben muss, gibt es eine Hilfsfunktion, die
920 sowohl die Methode mit C<txn_>-Präfix generiert als auch die ohne:
921
922 my $txn = sub {
923 my ($name, $sub) = @_;
924 *{"txn_$name"} = $sub;
925 *{$name} = sub { $sub->(@_)->result };
926 };
927
928 Der Aufruf ist ganz einfach:
929
930 $txn->(client_hello => sub {
931 my ($self) = @_;
932 $self->txn ("client_hello");
933 });
934
935 Das erzeugt sowohl die C<client_hello>- als auch die
936 C<txn_client_hello>-Methode. Die Methode ohne C<txn_> ist immer nach
937 demselben Muster aufgebaut:
938
939 txn_xxx(@_)->result
940
941 d.h. die Transaktion wird erzeugt und dann wird sofort C<< ->result >>
942 darauf aufgerufen. Das erzeugt dann die einfache blockierende API.
943
944 Für C<client_get> sieht es etwas komplizierter - aber im Prinzip genauso - aus:
945
946 $txn->(client_get => sub {
947 my ($self, $uri, $htl, $removelocal) = @_;
948
949 $uri =~ s/^freenet://; $uri = "freenet:$uri";
950
951 $self->txn (client_get => URI => $uri
952 hops_to_live => xeh (defined $htl ? $htl : 15),
953 remove_local_key => $removelocal ? "true" : "false");
954 });
955
956 Da alle Anfragen/Transaktionen ähnlich ablaufen (Verbindungsaufbau,
957 Anfrage hin, Antwort her, Ende), definiert Net::FCP die C<txn>-Hilfsmethode, die
958 eine Transaktion erzeugt:
959
960 sub txn {
961 my ($self, $type, %attr) = @_;
962
963 $type = touc $type;
964 "Net::FCP::Txn::$type"->new (fcp => $self, type => tolc $type, attr => \%attr);
965 }
966
967 Jeder Anfragetyp besitzt seine eigene Klasse,
968 z.B. C<Net::FCP::Txn::client_get>, die jeweils von C<Net::FCP::Txn>
969 abgeleitet ist.
970
971 Die C<new>-Methode erzeugt das Transaktionsobjekt und initiiert diese (ich
972 gebe nur die relevanten Zeilen an):
973
974 sub new {
975 my $class = shift;
976 my $self = bless { @_ }, $class;
977
978 $self->{signal} = AnyEvent->condvar;
979
980 C<< $self->{signal} >> ist das "Ergebnis vorhanden"-Signal, eine
981 C<condvar>. Dann wird eine Socket erzeugt und die Verbindung initiiert:
982
983 socket my $fh, PF_INET, SOCK_STREAM, 0
984 or Carp::croak "unable to create new tcp socket: $!";
985 binmode $fh, ":raw";
986 fcntl $fh, F_SETFL, O_NONBLOCK;
987 connect $fh, (sockaddr_in $self->{fcp}{port}, inet_aton $self->{fcp}{host})
988 and !$!{EWOULDBLOCK}
989 and !$!{EINPROGRESS}
990 and Carp::croak "FCP::txn: unable to connect to $self->{fcp}{host}:$self->{fcp}{port}: $!\n";
991
992 Nun wird der zu sendende Header in C<< $self->{sbuf} >> verstaut
993
994 $self->{sbuf} =
995 "\x00\x00\x00\x02"
996 . (Net::FCP::touc $self->{type})
997 . "\012$attr$data";
998
999 und ein Event-Watcher erzeugt. Wenn die Verbindung zustande kommt (oder
1000 ein Fehler auftritt), wird die Socket schreibbar (genaugenommen blockiert
1001 der Prozess nicht sofort, wenn man dann schreibt):
1002
1003 $self->{w} = AnyEvent->io (fh => $fh, poll => 'w', cb => sub { $self->fh_ready_w });
1004
1005 Und fertig:
1006
1007 $self
1008 }
1009
1010 Bis auf C<inet_aton> blockiert keiner der benutzten Aufrufe, und da die
1011 normale Adresse des Freenet-Hosts C<127.0.0.1> ist, wird C<inet_aton>
1012 eher selten blockieren. Das Erzeugen der Transaktion geschieht also "so
1013 schnell wie es die CPU erlaubt".
1014
1015 =head3 Senden
1016
1017 Sobald die Socket "schreibbar" wird, wird die C<fh_ready_w>-Methode (in
1018 etwa: Filehandle bereit zum Schreiben) aufgerufen. Diese versucht, so viel
1019 der Anfrage ($self->{sbuf}) zu schreiben, wie die Socket annimmt:
1020
1021 sub fh_ready_w {
1022 my ($self) = @_;
1023
1024 my $len = syswrite $self->{fh}, $self->{sbuf};
1025
1026 Konnte etwas geschrieben werden, wird $self->{sbuf} entsprechend
1027 gekürzt. Ist es danach leer, ist die gesamte Anfrage geschrieben worden,
1028 und es wird in die Empfangsphase gegangen, indem der alte AnyEvent-Watcher
1029 überschrieben (und damit gelöscht wird) und ein neuer Watcher erzeugt
1030 wird, der auf "Daten lesbar" reagiert:
1031
1032 if ($len > 0) {
1033 substr $self->{sbuf}, 0, $len, "";
1034 unless (length $self->{sbuf}) {
1035 $self->{w} = AnyEvent->io (fh => $self->{fh}, poll => 'r', cb => sub { $self->fh_ready_r });
1036 }
1037
1038 Der Rest der Methode kümmert sich um die Fehlerbehandlung:
1039
1040 } elsif (defined $len) {
1041 $self->throw (Net::FCP::Exception->new (network_error => { reason => "unexpected end of file while writing" }));
1042 } else {
1043 $self->throw (Net::FCP::Exception->new (network_error => { reason => "$!" }));
1044 }
1045 }
1046
1047 Die Fehlerbehandlung ist übrigens nicht einfach ein Aufruf von C<die>. Die
1048 Idee ist, daß es nicht allzu hilfreich ist, wenn irgendwo tief in
1049 C<Net:FCP> ein Fehler auftritt, da nicht klar ist, wer für die Anfrage
1050 verantwortlich ist. (Vielleicht werden mehrere Server gleichzeitig befragt,
1051 aber einer wurde falsch angegeben. Ein Hinweis, welches Codefragment die
1052 Anfrage in Auftrag gegeben hat, wäre in diesem Fall hilfreich.)
1053
1054 C<Net::FCP> merkt sich daher jeden aufgetretenen Fehler und bricht die
1055 Transaktion ab:
1056
1057 sub throw {
1058 my ($self, $exc) = @_;
1059
1060 $self->{exception} = $exc;
1061 $self->set_result;
1062 $self->eof; # must be last to avoid loops
1063 }
1064
1065 Die Methode C<eof> schließt einfach die Socket und gibt eventuell andere
1066 Ressourcen frei. Die C<set_result>-Methode wird immer aufgerufen, wenn die
1067 Transaktion ein Resultat hat (Daten, oder einen Fehler):
1068
1069 sub set_result {
1070 my ($self, $result) = @_;
1071
1072 $self->{result} = $result;
1073 $self->{cb}->($self) if exists $self->{cb};
1074 $self->{signal}->broadcast;
1075 }
1076
1077 Sie sorgt dafür, das ein eventuell gesetzter Callback sofort ausgeführt
1078 wird und broadcastet das anfänglich erzeugte "fertig"-Signal.
1079
1080 =head3 Empfangen
1081
1082 Der Normalfall sollte aber das Erreichen der Empfangsphase sein. Sobald
1083 Daten vorliegen, wird C<fh_read_r> aufgerufen. Prinzipiell genauso
1084 aufgebaut wie C<fh_ready_w>, jedoch komplizierter, weil wir die Daten
1085 gleich beim Empfang parsen:
1086
1087 sub fh_ready_r {
1088 my ($self) = @_;
1089
1090 if (sysread $self->{fh}, $self->{buf}, 65536, length $self->{buf}) {
1091 for (;;) {
1092 if ($self->{datalen}) {
1093 if (length $self->{buf} >= $self->{datalen}) {
1094 $self->rcv_data (substr $self->{buf}, 0, delete $self->{datalen}, "");
1095 } else {
1096 last;
1097 }
1098 } elsif ($self->{buf} =~ s/^DataChunk\015?\012Length=([0-9a-fA-F]+)\015?\012Data\015?\012//) {
1099 $self->{datalen} = hex $1;
1100 } elsif ($self->{buf} =~ s/^([a-zA-Z]+)\015?\012(?:(.+?)\015?\012)?EndMessage\015?\012//s) {
1101 $self->rcv ($1, {
1102 map { my ($a, $b) = split /=/, $_, 2; ((Net::FCP::tolc $a), $b) }
1103 split /\015?\012/, $2
1104 });
1105 } else {
1106 last;
1107 }
1108 }
1109 } else {
1110 $self->eof;
1111 }
1112 }
1113
1114 Das muss man jetzt nicht im Detail nachvollziehen, wichtig ist der Aufruf
1115 von C<sysread>, der Daten an den Skalar C<< $self->{buf} >> I<anhängt>.
1116 Sollten wieder Erwarten mal mehr als 64k Daten vorhanden sein, ist das
1117 übrigens nicht schlimm, da die Methode dann fast sofort wieder aufgerufen
1118 wird, solange, bis keine Daten mehr vorrätig sind.
1119
1120 Ist nach Meinung der Methode alles angekommen, was ankommen sollte,
1121 wird die C<rcv>-Methode aufgerufen. Die macht noch ein bisschen was
1122 Spezifisches, je nach Anfragetyp, und ruft ihrerseits wieder C<set_result>
1123 auf.
1124
1125 Bei Dateiende wird C<eof> aufgerufen, was übrigens nicht I<nur> Ressourcen
1126 freigibt, sondern auch einen Fehler auslöst, falls kein Resultat gesetzt
1127 wurde, was z.B. beim Verbindungsabbruch mitten in der Empfangsphase
1128 passiert.
1129
1130 =head3 Ergebnis
1131
1132 Ruft nun entweder der Callback oder jemand anders später die
1133 C<result>-Methode auf, so prüft diese zuerst, ob ein Resultat vorliegt,
1134 und wartet gegebenenfalls so lange, bis eines vorliegt:
1135
1136 sub result {
1137 my ($self) = @_;
1138
1139 $self->{signal}->wait unless exists $self->{result};
1140
1141 C<condvars> fügen sich sehr natürlich in derlei Programme ein, da sie
1142 es ermöglichen, sowohl nichtblockierend als auch blockierend bestimmte
1143 Ereignisse anzuzeigen.
1144
1145 Sollte ein Fehler aufgetreten sein, so wird die Exception sofort geworfen:
1146
1147 die $self->{exception} if $self->{exception};
1148
1149 Ein Backtrace ist dann viel aussagekräftiger, da das Programm dort
1150 abstürzt, wo die Daten verarbeitet werden sollen, was meistens
1151 Rückschlüsse auf die Art der Daten zuläßt :)
1152
1153 Ansonsten bleibt nur, das Ergebnis zu liefern:
1154
1155 $self->{result}
1156 }
1157
1158 Fertig!
1159
1160 =head1 Danke
1161
1162 Vielen Dank an Torsten Scheck, Robin Redeker und Ralf Valerien fürs
1163 Probelesen, Korrekturen und ihre Kommentare!
1164
1165 =head1 Literatur
1166
1167 Ein interessanterm lesenswerter Artikel über "State Threads" und
1168 Ereignisgesteurte Programmierung:
1169
1170 L<http://acmqueue.com/modules.php?name=Content&pa=showpage&pid=348>
1171
1172
1173