Front page | perl.perl6.language |
Postings from June 2006
RE: Synchronized / Thread syntax in Perl 6
Thread Previous
|
Thread Next
From:
John Drago
Date:
June 2, 2006 09:58
Subject:
RE: Synchronized / Thread syntax in Perl 6
Message ID:
00cc01c68652$cc485310$2305640a@corp.data393.com
> > > You mean "is parallel" as a synonym for "is async"?
> >
> > I think "is parallel" denotes something as usable by multiple threads
> > simultaneously, "in parallel".
> > "is serial" would denote that only one thread can use the $thing at a
> > time, exclusively.
>
> Are you saying both are asynchronous, but one specifies that a resource
> should be locked rather than duplicated?
>
> > . . .
> > > If $age has been passed to an asynchronous closure, it should be
> > > marked as locked, and other threads trying to access it would have
> > > to get a lock first. Yes, lots of overhead.... but that way if the
> > > default is WAIT (which seems the smart default to me), the thread
> > > waits until TakesForever() releases the resource.
>
> In that light, responding to my own comment, you could infer that you
> should lock anything passed by reference, and not worry about it if
> passed by value unless you said "$age is locked" or "is serial" or
> whatever, yes?
Correct - since only references can affect their originator (or whatever you call it).
Modifying something passed by value would be exempt.
>
> > > if we declare
> > >
> > > our method TakesForever ( int $num is serial ) is async but NOWAIT
> > {
> > > ...
> > > }
> > >
> > > or
> > >
> > > my $age = 27 but NOWAIT;
> > >
> > > or
> > >
> > > TakesForever( $age but NOWAIT );
> > >
> > > (or whatever) then I'd say it should just fail. I mean, isn't that
> > kind
> > > of the idea, to have that sort of flexibility?
> > >
> >
> > Perhaps some more syntax-play is in order here.
>
> lol -- yeah. :)
>
> > One thing about threading with Perl5 is that it is easy to write a
> > simple threaded program that is entirely opaque - unless you
> > wrote the program yourself.
> >
> > The program below gets a list of coderefs and executes each one, then
> > returns the result.
> > #================================================
> > (Using the threads.pm way...)
> > package QueueRunner;
> >
> > use strict;
> > use threads;
> > use threads::shared;
> >
> > sub process_job_queue
> > {
> > my ($s, @jobs_in) = @_;
> > my @results : shared = ();
> > my @workers = ();
> >
> > push @workers, async { push( @results, $_->() ) } foreach @jobs_in;
> > $_->join foreach @workers;
> > return @results;
> > }# end process_job_queue()
> >
> > # Elsewhere...
> > package main;
> >
> > my @answer = QueueRunner->process_job_queue( \&job1, \&job2, \&job3
> > );
> >
> > #================================================
> > And my attempt at the same, using Perl6:
> > #================================================
> >
> > class QueueRunner {
> > our sub process_job_queue( Code @jobs_in ) returns List of Any {
> > my Any @results is parallel;
> > my Thread @workers = ();
> >
> > for @jobs_in {
> > @workers.push( async { &_() } );
> > }
> > for @workers {
> > @results.push( $_.join() );
> > }
> >
> > return @results;
> > }# end process_job_queue()
> > }# end QueueRunner
> >
> > # Elsewhere...
> > my @answer = QueueRunner.process_job_queue( @jobs );
> >
> > #================================================
> >
> > I made absolutely no progress here. It seems to me that it's no more
> > obvious what's going on here than in the Perl5 version. Any
> > comments?
> >
> > Regards,
> > John Drago
>
> Hm. If we're using *implicit* threads (which I thought was the point),
> how about
>
> class QueueRunner {
>
> our sub process_queue(Code @jobs_in) {
> my @ans is serial;
> @ans.push map { async { &_() } } @jobs_in;
>
> @ans;
> }
>
> }# end QueueRunner
>
> # Elsewhere...
> my @answer = QueueRunner.process_job_queue( @jobs );
>
> The point is that the call to async() is supposed to handle the thread
> management for you, isn't it?
>
> Though if that works, you could squish this example even more, to
>
> class QueueRunner {
>
> our sub process_queue(Code @jobs_in) {
> map { async { &_() } } @jobs_in;
> }
>
> }# end QueueRunner
>
> # Elsewhere...
> my @answer = QueueRunner.process_job_queue( @jobs );
>
> and the issues of serialization are hidden in the map() call. For all
> that....
>
> my @answer = map { async { &_() } } @jobs;
>
> though that gets away from the point.
>
> Someone smack me if I'm drifting too far here?
>
Actually I think you did it just right. I think that horse is dead now.
So, what about "serial" classes and methods?:
# Does marking this class "is serial" mean it's forced to be a singleton?
class Foo is serial {
has $.counted = 0;
our method Qux {
say($.counted++ ~ " Foo.Qux");
}
}
# Only one thread may call Bar.Baz() at a time:
class Bar {
has $.counted = 0;
our method Baz is serial {
say($.counted++ ~ " Bar.Baz");
}
}
# ... later ...
my Foo $foo = Foo.new();
my Bar $bar = Bar.new();
# $foo and $bar are implicitly shared with other threads:
for 1..5 {
async {
is atomic;
$foo.Qux();
$bar.Baz();
};
}
...what would it print?
1 Foo.Qux
1 Bar.Baz
2 Bar.Baz
2 Foo.Qux
3 Bar.Baz
4 Bar.Baz
3 Foo.Qux
5 Bar.Baz
6 Bar.Baz
4 Foo.Qux
7 Bar.Baz
8 Bar.Baz
5 Foo.Qux
9 Bar.Baz
10 Bar.Baz
(Now the first thread would be done with $foo, so the second thread could use it.)
6 Foo.Qux
7 Foo.Qux
8 Foo.Qux
9 Foo.Qux
10 Foo.Qux
-----------------------------------------------
Regards,
John Drago
Thread Previous
|
Thread Next