From f747336ecc953fd9f0339e74fd1e245bc6278b06 Mon Sep 17 00:00:00 2001 From: dakkar Date: Wed, 5 Aug 2009 15:34:52 +0200 Subject: first draft --- Queue.pm | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ thr.pl | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 Queue.pm create mode 100644 thr.pl 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; -- cgit v1.2.3