Front page | perl.perl5.porters |
Postings from November 2003
[PATCH] cond_wait() and arbitrary lock variables
Thread Next
From:
Mike Pomraning
Date:
November 24, 2003 06:07
Subject:
[PATCH] cond_wait() and arbitrary lock variables
Message ID:
Pine.LNX.4.58.0311232311320.5397@localhost.localdomain
The following patch against 5.8.2 allows a shared variable to be cond_wait()d
with a distinct, shared lock variable:
use threads::shared;
cond_wait($v); # $v is both condition and mutex
cond_wait($v, $v); # same as above, but explicit
cond_wait($v, $lockvar); # $v's predicate is protected by $lockvar, which
# presumably protects other predicates as well
This is useful for, e.g., a Queue object which has client threads waiting on
one of two interesting predicates: "items ready" ($q->dequeue) or "queue
empty" ($q->await_empty).
--- ext/threads/shared/shared.xs.orig 2003-11-02 15:50:30.000000000 -0600
+++ ext/threads/shared/shared.xs 2003-11-23 23:26:32.000000000 -0600
@@ -1039,21 +1039,38 @@
Perl_sharedsv_lock(aTHX_ shared);
void
-cond_wait_enabled(SV *ref)
- PROTOTYPE: \[$@%]
- CODE:
+cond_wait_enabled(SV *ref_cond, SV *ref_lock = 0)
+ PROTOTYPE: \[$@%];\[$@%]
+ PREINIT:
shared_sv* shared;
+ perl_cond* user_condition;
int locks;
- if(!SvROK(ref))
+ int same = 0;
+
+ CODE:
+ if (!ref_lock || ref_lock == ref_cond) same = 1;
+
+ if(!SvROK(ref_cond))
Perl_croak(aTHX_ "Argument to cond_wait needs to be passed as ref");
- ref = SvRV(ref);
- if(SvROK(ref))
- ref = SvRV(ref);
- shared = Perl_sharedsv_find(aTHX_ ref);
+ ref_cond = SvRV(ref_cond);
+ if(SvROK(ref_cond))
+ ref_cond = SvRV(ref_cond);
+ shared = Perl_sharedsv_find(aTHX_ ref_cond);
if(!shared)
croak("cond_wait can only be used on shared values");
- if(shared->lock.owner != aTHX)
- croak("You need a lock before you can cond_wait");
+
+ user_condition = &shared->user_cond;
+ if (! same) {
+ if (!SvROK(ref_lock))
+ Perl_croak(aTHX_ "cond_wait lock needs to be passed as ref");
+ ref_lock = SvRV(ref_lock);
+ if (SvROK(ref_lock)) ref_lock = SvRV(ref_lock);
+ shared = Perl_sharedsv_find(aTHX_ ref_lock);
+ if (!shared)
+ croak("cond_wait lock must be a shared value");
+ }
+ if(shared->lock.owner != aTHX)
+ croak("You need a lock before you can cond_wait");
/* Stealing the members of the lock object worries me - NI-S */
MUTEX_LOCK(&shared->lock.mutex);
shared->lock.owner = NULL;
@@ -1063,10 +1080,12 @@
/* since we are releasing the lock here we need to tell other
people that is ok to go ahead and use it */
COND_SIGNAL(&shared->lock.cond);
- COND_WAIT(&shared->user_cond, &shared->lock.mutex);
+ COND_WAIT(user_condition, &shared->lock.mutex);
while(shared->lock.owner != NULL) {
- COND_WAIT(&shared->lock.cond,&shared->lock.mutex);
- }
+ /* OK -- we got the signal, now wait for threads to give us
+ back the lock */
+ COND_WAIT(&shared->lock.cond, &shared->lock.mutex);
+ }
shared->lock.owner = aTHX;
shared->lock.locks = locks;
MUTEX_UNLOCK(&shared->lock.mutex);
--- ext/threads/shared/shared.pm.orig 2003-11-22 22:40:15.000000000 -0600
+++ ext/threads/shared/shared.pm 2003-11-23 23:09:41.000000000 -0600
@@ -24,10 +24,10 @@
# saves on average about 4K of memory per thread.
eval <<'EOD';
-sub cond_wait (\[$@%]) { undef }
-sub cond_signal (\[$@%]) { undef }
-sub cond_broadcast (\[$@%]) { undef }
-sub share (\[$@%]) { return $_[0] }
+sub cond_wait (\[$@%];\[$@%]) { undef }
+sub cond_signal (\[$@%]) { undef }
+sub cond_broadcast (\[$@%]) { undef }
+sub share (\[$@%]) { return $_[0] }
EOD
}
}
@@ -122,6 +122,8 @@
=item cond_wait VARIABLE
+=item cond_wait CONDVAR LOCKVAR
+
The C<cond_wait> function takes a B<locked> variable as a parameter,
unlocks the variable, and blocks until another thread does a
C<cond_signal> or C<cond_broadcast> for that same locked variable.
@@ -134,6 +136,11 @@
blocked wait state are atomic, The two actions of exiting from the
blocked wait state and relocking the variable are not.
+In its second form, C<cond_wait> takes a shared, B<unlocked> variable
+followed by a shared, B<locked> variable. The second variable is
+unlocked and thread execution suspended until another thread signals
+the first variable.
+
It is important to note that the variable can be notified even if
no thread C<cond_signal> or C<cond_broadcast> on the variable.
It is therefore important to check the value of the variable and
-Mike
Thread Next
-
[PATCH] cond_wait() and arbitrary lock variables
by Mike Pomraning