1#!/usr/bin/perl 2 3# Simplified example illustrating event handling and callback threads 4 5# Callback threads register their queues with the event handler thread. 6# Events are passed to the event handler via a queue. 7# The event handler then disseminates the event to the appropriately 8# registered thread. 9 10use strict; 11use warnings; 12 13use threads; 14use Thread::Queue; 15 16MAIN: 17{ 18 # Queue for registering callbacks 19 my $regis_q = Thread::Queue->new(); 20 21 # Queue for disseminating events 22 my $event_q = Thread::Queue->new(); 23 24 # Create callback threads 25 threads->create('CallBack', 'USR1', $regis_q)->detach(); 26 threads->create('CallBack', 'USR2', $regis_q)->detach(); 27 threads->create('CallBack', 'HUP', $regis_q)->detach(); 28 threads->create('CallBack', 'ALRM', $regis_q)->detach(); 29 30 # Create event handler thread 31 threads->create('EventHandler', $regis_q, $event_q)->detach(); 32 33 # Capture SIGUSR1 events 34 $SIG{'USR1'} = sub { 35 $event_q->enqueue('USR1'); # Send to event handler 36 }; 37 38 # Capture SIGUSR1 events 39 $SIG{'USR2'} = sub { 40 $event_q->enqueue('USR2'); # Send to event handler 41 }; 42 43 # Capture SIGHUP events 44 $SIG{'HUP'} = sub { 45 $event_q->enqueue('HUP'); # Send to event handler 46 }; 47 48 # Capture SIGHUP events 49 $SIG{'ALRM'} = sub { 50 $event_q->enqueue('ALRM'); # Send to event handler 51 alarm(5); # Reset alarm 52 }; 53 54 # Ready 55 print(<<_MSG_); 56Send signals to PID = $$ 57 (e.g., 'kill -USR1 $$') 58Use ^C (or 'kill -INT $$') to terminate 59_MSG_ 60 61 # Set initial alarm 62 alarm(5); 63 64 # Just hang around 65 while (1) { 66 sleep(10); 67 } 68} 69 70### Subroutines ### 71 72sub EventHandler 73{ 74 my ($regis_q, $event_q) = @_; 75 76 my %callbacks; # Registered callback queues 77 78 while (1) { 79 # Check for any registrations 80 while (my ($event_type, $q) = $regis_q->dequeue_nb(2)) { 81 if ($q) { 82 $callbacks{$event_type} = $q; 83 } else { 84 warn("BUG: Bad callback registration for event type $event_type\n"); 85 } 86 } 87 88 # Wait for event 89 if (my $event = $event_q->dequeue()) { 90 # Send event to appropriate queue 91 if (exists($callbacks{$event})) { 92 $callbacks{$event}->enqueue($event); 93 } else { 94 warn("WARNING: No callback for event type $event\n"); 95 } 96 } 97 } 98} 99 100 101sub CallBack 102{ 103 my $event_type = shift; # The type of event I'm handling 104 my $regis_q = shift; 105 106 # Announce registration 107 my $tid = threads->tid(); 108 print("Callback thread $tid registering for $event_type events\n"); 109 110 # Register my queue for my type of event 111 my $q = Thread::Queue->new(); 112 $regis_q->enqueue($event_type, $q); 113 114 # Process loop 115 while (1) { 116 # Wait for event callback 117 my $item = $q->dequeue(); 118 # Process event 119 print("Callback thread $tid notified of $item event\n") if $item; 120 } 121} 122 123# EOF 124