1 package Thrasher
::EventLoop
;
5 use Thrasher
::Log
qw(log debug);
11 Thrasher::EventLoop - the 'default' event loop for Thrasher Bird
15 The trickiest part of Thrasher is that it needs to manage both
16 connections to the protocols, and talking to the XMPP server
17 itself. You can't use blocking connections on both.
19 This both specifies an interface, and a default event loop
20 based on ignoring the transport entirely, which actually works
21 if your "transport" is a pure perl module that never has long-
24 The Event Loop is created by the main Thrasher routine while it is
25 configuring all the pieces. Event loops are tied to protocols
26 pretty intimately, so the Protocol you are using has responsibility
27 for controlling what event loop you are using, so the Protocol
28 can freely refer directly to advanced aspects of the
32 use Thrasher
::Log
qw(log);
36 our @EXPORT_OK = qw(IN OUT);
44 $self->{protocol
} = shift;
45 $self->{socket} = shift;
46 $self->{component
} = shift;
55 # This test event loop just assumes the protocol is a
56 # 'test' protocol and can be ignored, so despite the documentation
57 # in this case we DO have exactly one socket to read, preventing
58 # the need for fancy processing.
59 while (defined(my $val = $self->{socket}->read)) {
61 $self->{component
}->xml_in($val);
64 $self->{socket}->close;
67 # Returns some token that can be passed to 'cancel_schedule'
68 # Timeout is in milliseconds
69 # If the closure returns a true value, it should be rescheduled
70 # again in the given timeout, otherwise it should stop.
76 log("Thrasher::EventLoop laughs in the face of your attempt to "
77 ."schedule an event!");
79 eval { $closure->(); };
80 log("Error in scheduled callback: $@") if $@
;
83 # fd must be an actual file descriptor
84 # Directions is a bit mask of $IN and $OUT
85 # Return true to continue the watch, false to cancel it.
89 my $directions = shift;
92 die "Thrasher::EventLoop laughs in the face of your attempt "
93 ."to watch a file descriptor! You need a real event loop.";
98 my $opaque_token = shift;
100 die "Thrasher::EventLoop laughs in the face of your attempt "
101 ."to cancel a file descriptor watch! Hey, you shouldn't "
102 ."even be able to get here...";
105 # Idle handler means "do a task after all other stuff in this
106 # event loop run is done". The only thing Thrasher uses this for
107 # is to properly shut the system down after a SIGINT or something.
108 # Simpler event loops can implement this as simply immediately
109 # executing the passed-in closure, but many event loops will become
110 # offended if you do that.
111 sub execute_on_idle
{
115 die "Thrasher::EventLoop laughs in the face of your attempt to "
116 ."schedule something for idle execution!";
119 # This should quit your event loop, preferably more politely than
120 # with "exit()", since we may want to do more stuff later.
124 die "Thrasher::EventLoop laughs in the face of your quit!";