3
0
mirror of https://github.com/pragma-/pbot.git synced 2024-11-26 13:59:47 +01:00

EventDispatcher: store event handlers in priority queue

This commit is contained in:
Pragmatic Software 2021-07-18 18:23:42 -07:00
parent d380422d14
commit b970ee9aa6

View File

@ -12,6 +12,8 @@ use parent 'PBot::Class';
use PBot::Imports; use PBot::Imports;
use PBot::Utils::PriorityQueue;
sub initialize { sub initialize {
my ($self, %conf) = @_; my ($self, %conf) = @_;
@ -21,7 +23,7 @@ sub initialize {
# add an event handler # add an event handler
sub register_handler { sub register_handler {
my ($self, $event_name, $subref) = @_; my ($self, $event_name, $subref, $priority) = @_;
# get the package of the calling subroutine # get the package of the calling subroutine
my ($package) = caller(0); my ($package) = caller(0);
@ -29,8 +31,19 @@ sub register_handler {
# internal identifier to find calling package's event handler # internal identifier to find calling package's event handler
my $handler_id = "$package-$event_name"; my $handler_id = "$package-$event_name";
my $entry = {
priority => $priority // 50,
id => $handler_id,
subref => $subref,
};
# create new priority-queue for event-name if one doesn't exist
if (not exists $self->{handlers}->{$event_name}) {
$self->{handlers}->{$event_name} = PBot::Utils::PriorityQueue->new(pbot => $self->{pbot});
}
# add the event handler # add the event handler
$self->{handlers}->{$event_name}->{$handler_id} = $subref; $self->{handlers}->{$event_name}->add($entry);
# debugging # debugging
if ($self->{pbot}->{registry}->get_value('eventdispatcher', 'debug')) { if ($self->{pbot}->{registry}->get_value('eventdispatcher', 'debug')) {
@ -50,10 +63,18 @@ sub remove_handler {
# remove the event handler # remove the event handler
if (exists $self->{handlers}->{$event_name}) { if (exists $self->{handlers}->{$event_name}) {
delete $self->{handlers}->{$event_name}->{$handler_id}; my $handlers = $self->{handlers}->{$event_name};
for (my $i = 0; $i < $handlers->count; $i++) {
my $handler = $handlers->get($i);
if ($handler->{id} eq $handler_id) {
$handlers->remove($i--);
}
}
# remove root event-name key if it has no more handlers # remove root event-name key if it has no more handlers
if (not keys %{$self->{handlers}->{$event_name}}) { if (not $self->{handlers}->{$event_name}->count) {
delete $self->{handlers}->{$event_name}; delete $self->{handlers}->{$event_name};
} }
} }
@ -77,18 +98,15 @@ sub dispatch_event {
# if the event-name has handlers # if the event-name has handlers
if (exists $self->{handlers}->{$event_name}) { if (exists $self->{handlers}->{$event_name}) {
# then dispatch the event to each one # then dispatch the event to each one
foreach my $handler_id (keys %{$self->{handlers}->{$event_name}}) { foreach my $handler ($self->{handlers}->{$event_name}->entries) {
# get event handler subref
my $subref = $self->{handlers}->{$event_name}->{$handler_id};
# debugging # debugging
if ($debug) { if ($debug) {
$self->{pbot}->{logger}->log("Dispatching $event_name to handler $handler_id\n"); $self->{pbot}->{logger}->log("Dispatching $event_name to handler $handler->{id}\n");
} }
# invoke an event handler. a handler may return undef to indicate # invoke an event handler. a handler may return undef to indicate
# that it decided not to handle this event. # that it decided not to handle this event.
my $handler_result = eval { $subref->($event_name, $event_data) }; my $handler_result = eval { $handler->{subref}->($event_name, $event_data) };
# update $dispatch_result only when handler result is a defined # update $dispatch_result only when handler result is a defined
# value so we remember if any handlers have handled this event. # value so we remember if any handlers have handled this event.