summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordakkar <dakkar@sardina.(none)>2009-08-05 15:34:52 +0200
committerdakkar <dakkar@sardina.(none)>2009-08-05 15:34:52 +0200
commitf747336ecc953fd9f0339e74fd1e245bc6278b06 (patch)
treeb238bb64f7ec395e0e3f9b8c1ad97b7338b7227a
downloadThread-Queue-Event-f747336ecc953fd9f0339e74fd1e245bc6278b06.tar.gz
Thread-Queue-Event-f747336ecc953fd9f0339e74fd1e245bc6278b06.tar.bz2
Thread-Queue-Event-f747336ecc953fd9f0339e74fd1e245bc6278b06.zip
first draft
-rw-r--r--Queue.pm65
-rw-r--r--thr.pl47
2 files changed, 112 insertions, 0 deletions
diff --git a/Queue.pm b/Queue.pm
new file mode 100644
index 0000000..bf83a0d
--- /dev/null
+++ b/Queue.pm
@@ -0,0 +1,65 @@
+package Glib::Thread::Queue;
+use Moose;
+use Glib;
+use Thread::Queue;
+use Carp;
+
+has queue => (
+ is => 'ro',
+ isa => 'Thread::Queue',
+ init_arg => undef,
+ builder => '_build_queue',
+ handles => [qw(
+ enqueue
+ dequeue
+ dequeue_nb
+ pending
+ peek
+ insert
+ extract
+ )],
+);
+
+has pipes => (
+ isa => 'ArrayRef',
+ is => 'ro',
+ builder => '_build_pipes',
+);
+
+sub _build_pipes {
+ my ($main,$thread);pipe($main,$thread);
+
+ return [$main,$thread];
+}
+
+sub _build_queue {
+ return Thread::Queue->new();
+}
+
+after enqueue => sub {
+ my ($self)=shift;
+ syswrite $self->pipes->[1],'0';
+};
+
+before dequeue => sub {
+ my ($self)=shift;
+ my $foo;sysread $self->pipes->[0],$foo,1;
+};
+
+sub add_watch {
+ my ($self,$sub)=@_;
+
+ Glib::IO->add_watch(fileno($self->pipes->[0]),'in',$sub);
+}
+
+sub signal {
+ my ($self)=@_;
+
+ croak "Not signaling on an empty queue, would block"
+ unless $self->pending;
+
+ syswrite $self->pipes->[1],'0';
+}
+
+no Moose;
+1;
diff --git a/thr.pl b/thr.pl
new file mode 100644
index 0000000..c648509
--- /dev/null
+++ b/thr.pl
@@ -0,0 +1,47 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use threads;
+use Glib;
+use Queue;
+
+=head1 Signaling across threads to a Glib loop
+
+Looks like the best way is to use a pipe
+
+=cut
+
+my $q=Glib::Thread::Queue->new();
+
+threads->create(
+ sub{
+ print "sleeping\n";
+ sleep 2;
+ print "sending boo\n";
+ $q->enqueue('boo');
+ sleep 2;
+ print "inserting bar & foo\n";
+ $q->insert(0,'bar');
+ $q->insert(1,'foo');
+ print "signaling\n";
+ $q->signal();
+ print "signaling\n";
+ $q->signal();
+ sleep 2;
+ print "sending quit";
+ $q->enqueue('quit');
+});
+
+my $loop=Glib::MainLoop->new();
+$q->add_watch(sub{
+ print "waking up\n";
+ my $foo=$q->dequeue();
+ print "got $foo\n";
+ if ($foo eq 'quit') {
+ print "quitting\n";
+ $loop->quit;
+ }
+ return Glib::SOURCE_CONTINUE;
+ },
+ );
+$loop->run;