You may also C<lock> a sub, using C<lock &sub>. Any calls to that sub from
another thread will block until the lock is released. This behaviour is not
-equvalent to C<use attrs qw(locked)> in the sub. C<use attrs qw(locked)>
-serializes access to a subroutine, but allows different threads
+equivalent to declaring the sub with the C<locked> attribute. The C<locked>
+attribute serializes access to a subroutine, but allows different threads
non-simultaneous access. C<lock &sub>, on the other hand, will not allow
I<any> other thread access for the duration of the lock.
=head1 SEE ALSO
-L<attrs>, L<Thread::Queue>, L<Thread::Semaphore>, L<Thread::Specific>.
+L<attributes>, L<Thread::Queue>, L<Thread::Semaphore>, L<Thread::Specific>.
=cut
PL_nthreads--;
t->prev->next = t->next;
t->next->prev = t->prev;
+ SvREFCNT_dec(t->oursv);
COND_BROADCAST(&PL_nthreads_cond);
MUTEX_UNLOCK(&PL_threads_mutex);
#endif
av_store(av, 1, newSVsv(thr->errsv));
DEBUG_S(PerlIO_printf(Perl_debug_log, "%p died: %s\n",
thr, SvPV(thr->errsv, PL_na)));
- } else {
+ }
+ else {
DEBUG_S(STMT_START {
for (i = 1; i <= retval; i++) {
PerlIO_printf(Perl_debug_log, "%p return[%d] = %s\n",
/* Thread creation failed--clean up */
SvREFCNT_dec(thr->cvcache);
remove_thread(aTHX_ thr);
- MUTEX_DESTROY(&thr->mutex);
for (i = 0; i <= AvFILL(initargs); i++)
SvREFCNT_dec(*av_fetch(initargs, i, FALSE));
SvREFCNT_dec(startsv);
}
JOIN(t, &av);
+ sv_2mortal((SV*)av);
+
if (SvTRUE(*av_fetch(av, 0, FALSE))) {
/* Could easily speed up the following if necessary */
for (i = 1; i <= AvFILL(av); i++)
- XPUSHs(sv_2mortal(*av_fetch(av, i, FALSE)));
- } else {
+ XPUSHs(*av_fetch(av, i, FALSE));
+ }
+ else {
STRLEN n_a;
char *mess = SvPV(*av_fetch(av, 1, FALSE), n_a);
DEBUG_S(PerlIO_printf(Perl_debug_log,
return bless [@_], $class;
}
-sub dequeue {
- use attrs qw(locked method);
+sub dequeue : locked, method {
my $q = shift;
cond_wait $q until @$q;
return shift @$q;
}
-sub dequeue_nb {
- use attrs qw(locked method);
+sub dequeue_nb : locked, method {
my $q = shift;
if (@$q) {
return shift @$q;
}
}
-sub enqueue {
- use attrs qw(locked method);
+sub enqueue : locked, method {
my $q = shift;
push(@$q, @_) and cond_broadcast $q;
}
-sub pending {
- use attrs qw(locked method);
+sub pending : locked, method {
my $q = shift;
return scalar(@$q);
}
bless \$val, $class;
}
-sub down {
- use attrs qw(locked method);
+sub down : locked, method {
my $s = shift;
my $inc = @_ ? shift : 1;
cond_wait $s until $$s >= $inc;
$$s -= $inc;
}
-sub up {
- use attrs qw(locked method);
+sub up : locked, method {
my $s = shift;
my $inc = @_ ? shift : 1;
($$s += $inc) > 0 and cond_broadcast $s;
=cut
-sub import {
- use attrs qw(locked method);
+sub import : locked, method {
require fields;
fields::->import(@_);
}
-sub key_create {
- use attrs qw(locked method);
+sub key_create : locked, method {
return ++$FIELDS{__MAX__};
}
$level = 0;
-sub single_file {
- use attrs 'locked';
+sub single_file : locked {
my $arg = shift;
$level++;
print "Level $level for $arg\n";
$global = undef;
-sub single_file {
- use attrs 'locked';
+sub single_file : locked {
my $who = shift;
my $i;