… | |
… | |
23 | AnyEvent is first of all just a framework to do event-based |
23 | AnyEvent is first of all just a framework to do event-based |
24 | programming. Typically such frameworks are an all-or-nothing thing: If you |
24 | programming. Typically such frameworks are an all-or-nothing thing: If you |
25 | use one such framework, you can't (easily, or even at all) use another in |
25 | use one such framework, you can't (easily, or even at all) use another in |
26 | the same program. |
26 | the same program. |
27 | |
27 | |
28 | AnyEvent is different - it is a thin abstraction layer on top of other of |
28 | AnyEvent is different - it is a thin abstraction layer on top of other |
29 | event loops, just like DBI is an abstraction of many different database |
29 | event loops, just like DBI is an abstraction of many different database |
30 | APIs. Its main purpose is to move the choice of the underlying framework |
30 | APIs. Its main purpose is to move the choice of the underlying framework |
31 | (the event loop) from the module author to the program author using the |
31 | (the event loop) from the module author to the program author using the |
32 | module. |
32 | module. |
33 | |
33 | |
… | |
… | |
124 | Waiting as done in the first example is also called "blocking" the process |
124 | Waiting as done in the first example is also called "blocking" the process |
125 | because you "block"/keep your process from executing anything else while |
125 | because you "block"/keep your process from executing anything else while |
126 | you do so. |
126 | you do so. |
127 | |
127 | |
128 | The second example avoids blocking by only registering interest in a read |
128 | The second example avoids blocking by only registering interest in a read |
129 | event, which is fast and doesn't block your process. Only when read data |
129 | event, which is fast and doesn't block your process. Only when data is |
130 | is available will the callback be called, which can then proceed to read |
130 | available for reading will the callback be called, which can then proceed |
131 | the data. |
131 | to read the data. |
132 | |
132 | |
133 | The "interest" is represented by an object returned by C<< AnyEvent->io |
133 | The "interest" is represented by an object returned by C<< AnyEvent->io |
134 | >> called a "watcher" object - called like that because it "watches" your |
134 | >> called a "watcher" object - called this because it "watches" your |
135 | file handle (or other event sources) for the event you are interested in. |
135 | file handle (or other event sources) for the event you are interested in. |
136 | |
136 | |
137 | In the example above, we create an I/O watcher by calling the C<< |
137 | In the example above, we create an I/O watcher by calling the C<< |
138 | AnyEvent->io >> method. Disinterest in some event is simply expressed |
138 | AnyEvent->io >> method. Disinterest in some event is simply expressed |
139 | by forgetting about the watcher, for example, by C<undef>'ing the only |
139 | by forgetting about the watcher, for example, by C<undef>'ing the only |
… | |
… | |
218 | In AnyEvent, this is done using condition variables. Condition variables |
218 | In AnyEvent, this is done using condition variables. Condition variables |
219 | are named "condition variables" because they represent a condition that is |
219 | are named "condition variables" because they represent a condition that is |
220 | initially false and needs to be fulfilled. |
220 | initially false and needs to be fulfilled. |
221 | |
221 | |
222 | You can also call them "merge points", "sync points", "rendezvous ports" |
222 | You can also call them "merge points", "sync points", "rendezvous ports" |
223 | or even callbacks and many other things (and they are often called like |
223 | or even callbacks and many other things (and they are often called these |
224 | this in other frameworks). The important point is that you can create them |
224 | names in other frameworks). The important point is that you can create them |
225 | freely and later wait for them to become true. |
225 | freely and later wait for them to become true. |
226 | |
226 | |
227 | Condition variables have two sides - one side is the "producer" of the |
227 | Condition variables have two sides - one side is the "producer" of the |
228 | condition (whatever code detects and flags the condition), the other side |
228 | condition (whatever code detects and flags the condition), the other side |
229 | is the "consumer" (the code that waits for that condition). |
229 | is the "consumer" (the code that waits for that condition). |
… | |
… | |
347 | |
347 | |
348 | Instead of waiting for a condition variable, the program enters the Gtk2 |
348 | Instead of waiting for a condition variable, the program enters the Gtk2 |
349 | main loop by calling C<< Gtk2->main >>, which will block the program and |
349 | main loop by calling C<< Gtk2->main >>, which will block the program and |
350 | wait for events to arrive. |
350 | wait for events to arrive. |
351 | |
351 | |
352 | This also shows that AnyEvent is quite flexible - you didn't have anything |
352 | This also shows that AnyEvent is quite flexible - you didn't have to do |
353 | to do to make the AnyEvent watcher use Gtk2 (actually Glib) - it just |
353 | anything to make the AnyEvent watcher use Gtk2 (actually Glib) - it just |
354 | worked. |
354 | worked. |
355 | |
355 | |
356 | Admittedly, the example is a bit silly - who would want to read names |
356 | Admittedly, the example is a bit silly - who would want to read names |
357 | from standard input in a Gtk+ application. But imagine that instead of |
357 | from standard input in a Gtk+ application. But imagine that instead of |
358 | doing that, you would make a HTTP request in the background and display |
358 | doing that, you would make a HTTP request in the background and display |
359 | it's results. In fact, with event-based programming you can make many |
359 | it's results. In fact, with event-based programming you can make many |
360 | http-requests in parallel in your program and still provide feedback to |
360 | HTTP requests in parallel in your program and still provide feedback to |
361 | the user and stay interactive. |
361 | the user and stay interactive. |
362 | |
362 | |
363 | And in the next part you will see how to do just that - by implementing an |
363 | And in the next part you will see how to do just that - by implementing an |
364 | HTTP request, on our own, with the utility modules AnyEvent comes with. |
364 | HTTP request, on our own, with the utility modules AnyEvent comes with. |
365 | |
365 | |
366 | Before that, however, let's briefly look at how you would write your |
366 | Before that, however, let's briefly look at how you would write your |
367 | program with using only AnyEvent, without ever calling some other event |
367 | program using only AnyEvent, without ever calling some other event |
368 | loop's run function. |
368 | loop's run function. |
369 | |
369 | |
370 | In the example using condition variables, we used those to start waiting |
370 | In the example using condition variables, we used those to start waiting |
371 | for events, and in fact, condition variables are the solution: |
371 | for events, and in fact, condition variables are the solution: |
372 | |
372 | |