[jboss-svn-commits] JBL Code SVN: r28750 - in labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman: synchronization and 1 other directory.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Mon Aug 3 09:10:33 EDT 2009
Author: adinn
Date: 2009-08-03 09:10:33 -0400 (Mon, 03 Aug 2009)
New Revision: 28750
Modified:
labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/helper/Helper.java
labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/synchronization/Rendezvous.java
Log:
added rendezvous delete call and modified implementation and tweaked implementation to ensure that repeatable rendezvous can be safely deleted
Modified: labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/helper/Helper.java
===================================================================
--- labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/helper/Helper.java 2009-08-03 11:11:04 UTC (rev 28749)
+++ labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/rule/helper/Helper.java 2009-08-03 13:10:33 UTC (rev 28750)
@@ -592,66 +592,62 @@
if (rendezvous == null || rendezvous.getExpected() != expected) {
return -1;
}
-
- return rendezvous.getArrived();
+ synchronized (rendezvous) {
+ return rendezvous.getArrived();
+ }
}
/**
- * meet other threads at a given rendezvous retrunign only when the expected number have arrived
+ * meet other threads at a given rendezvous returning only when the expected number have arrived
* @param identifier the identifier for the rendezvous
* @return an ordinal which sorts all parties to the rendezvous in order of arrival from 0 to
* (expected-1) or -1 if the rendezvous does not exist
*/
public int rendezvous(Object identifier)
{
- // we don't need to (cannot) synch on the map here although the reasoning is subtle
- // the last thread in will reset the rendezvous if it is rejoinable in which case
- // it stays in the map anyway. if it is not rejoinable then any thread which finds it in
- // the map will return -1 if it is calling rendezvous -- i.e. this is the same as if it was
- // not present. if a thread calls createRendezvous with the same identifier then this might
- // make a difference but in that case either the rendezvous should be created rejoinable or
- // the last thread out should be responsible for recreating the rendezvous.
-
Rendezvous rendezvous = rendezvousMap.get(identifier);
+
if (rendezvous != null) {
- int result = rendezvous.rendezvous();
- if (result == rendezvous.getExpected() && !rendezvous.isRejoinable()) {
- rendezvousMap.remove(identifier);
+ synchronized(rendezvous) {
+ int result = rendezvous.rendezvous();
+ // make sure the rendezvous is removed from the map if required
+ // n.b. this implementation makes sure the remove happens before any thread
+ // successfully passes the rendezvous call
+ if (rendezvous.needsRemove()) {
+ rendezvousMap.remove(identifier);
+ rendezvous.setRemoved();
+ }
+
+ return result;
}
-
- return result;
}
return -1;
}
/*
- * hmm, maybe we need this and maybe not
- *
- * terminate a rendezvous, waking any threads which are waiting and resetting the arrived count to zero. If the
- * rendezous is not restartable then it also gets removed from the rendezvous map. All threads waiting inside
- * a call to rendezvous return result -1;
+ * delete a rendezvous. All threads waiting inside a call to rendezvous return result -1;
* @param identifier
* @param expected
- * @return
-
- public int resetRendezvous(Object identifier)
- {
- }
+ * @return true if the rendezvous was active and deleted and false if it had already been deleted
*/
-
- /*
- * hmm, maybe we need this and maybe not
- *
- * delete a rendezvous, waking any threads which are waiting and resetting the arrived count to zero. All
- * threads waiting inside a call to rendezvous return result -1;
- * @param identifier
- * @param expected
- * @return
- public int deleteRendezvous(Object identifier)
+ public boolean deleteRendezvous(Object identifier, int expected)
{
+ Rendezvous rendezvous = rendezvousMap.get(identifier);
+ if (rendezvous == null || rendezvous.getExpected() != expected) {
+ return false;
+ }
+ synchronized (rendezvous) {
+ if (rendezvous.delete()) {
+ if (rendezvous.needsRemove()) {
+ rendezvousMap.remove(identifier);
+ }
+ return true;
+ }
+ }
+ // hmm, completed before we got there
+ return false;
}
- */
// counter support
Modified: labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/synchronization/Rendezvous.java
===================================================================
--- labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/synchronization/Rendezvous.java 2009-08-03 11:11:04 UTC (rev 28749)
+++ labs/jbosstm/workspace/adinn/byteman/trunk/src/org/jboss/byteman/synchronization/Rendezvous.java 2009-08-03 13:10:33 UTC (rev 28750)
@@ -36,33 +36,87 @@
public Rendezvous(int expected, boolean rejoinable)
{
this.expected = expected;
- this.arrived = 0;
this.rejoinable = rejoinable;
+ this.needsRemove = false;
+ this.isDeleted = false;
+ this.counter = new Counter();
}
+ /**
+ * enter this rendezvous. n.b. this must be called synchronized on the rendezvous object
+ * in question
+ * @return the index in arrival order from 0 to expected of the calling thread or -1 if
+ * either the rendezvous has completed and is not restartable or the rendezvous has been deleted
+ */
public int rendezvous()
{
- synchronized(this) {
- int index = arrived++;
- if (arrived < expected) {
+ Counter currentCounter = counter;
+
+ // too late the rendezvous has expired
+
+ if (isDeleted || (currentCounter.arrived == expected)) {
+ return -1;
+ }
+
+ // n.b. getting here implies !currentCounter.isPoisoned
+
+ int index = currentCounter.arrived++;
+
+ if (currentCounter.arrived < expected) {
+ // make sure we don't return before the rendezvous has actually happened
+ while (currentCounter.arrived < expected) {
try {
this.wait();
} catch (InterruptedException e) {
// do nothing
}
- } else {
- if (rejoinable) {
- // the last one in needs to set the count back to zero while it has the lock
- // this makes sure that any of the existing threads or any new thread trying
- // to re-enter the rendezvous will not fail to suspend
- arrived = 0;
+
+ // isPoisoned may have changed because a delete happened while we were waiting
+
+ if (currentCounter.isPoisoned) {
+ return -1;
}
- this.notifyAll();
}
- return index;
+ } else {
+ if (rejoinable) {
+ // create a new counter for the next rendezvous -- this allows the current threads
+ // to complete without counting them back out
+ counter = new Counter();
+ } else {
+ // tag the rendezvous to indicate that it has been deleted and needs ot be removed. the
+ // first thread emerging from a call to rendezvous must make sure it gets removed from
+ // the rendezvous map.
+ isDeleted = true;
+ needsRemove = true;
+ }
+ this.notifyAll();
}
+
+ return index;
}
+ /**
+ * delete this rendezvous causing any waiting threads to return -1 form the rendezvous call. n.b. this
+ * must be called synchronized on the rendezvous object in question
+ * @return
+ */
+ public boolean delete()
+ {
+ if (isDeleted) {
+ return false;
+ }
+ isDeleted = true;
+ needsRemove = true;
+
+ // if any threads arrived then make sure they are *all* poisoned
+ if (counter.arrived > 0 && counter.arrived < expected) {
+ counter.isPoisoned = true;
+ this.notifyAll();
+ }
+
+ return true;
+ }
+
public int getExpected() {
return expected;
}
@@ -72,19 +126,72 @@
private int expected;
/**
- * the number of threads which have arrive at this rendezvous so far
+ * the current counter for this rendezvous
*/
- private int arrived;
+ private Counter counter;
/**
* true if this rendezvous can be repeatedly joined, false it it is a one-off meeting
*/
private boolean rejoinable;
- public boolean isRejoinable() {
- return rejoinable;
- }
+ /**
+ * true if a rendezvous was deleted while a rendezbvous was in progress but had not completed
+ */
+ private boolean isDeleted;
+
+ /**
+ * true if a non-restartable rendezvous has completed and has not been removed from the rendezvous map
+ */
+ private boolean needsRemove;
+
+ /**
+ * retrieve the number of threads waiting at the rendezvous or -1 if the rendezvous has
+ * been deleted
+ * @return
+ */
public int getArrived() {
- return arrived;
+ if (isDeleted) {
+ return -1;
+ }
+ return counter.arrived;
}
+
+ /**
+ * check if the rendezvous has completed but has not yet been rtemoved
+ * @return
+ */
+ public boolean needsRemove() {
+ return needsRemove;
+ }
+
+ /**
+ * mark a completed rendezvous to indicate that it has been removed
+ * @return
+ */
+ public void setRemoved() {
+ needsRemove = false;
+ }
+
+ /**
+ * class encapsulating state for a specific rendezvous
+ */
+
+ public class Counter
+ {
+ /**
+ * count of the number of threads actually arrived at this rendezvous
+ */
+ public int arrived;
+ /**
+ * true if this
+ */
+ public boolean isPoisoned;
+
+ public Counter()
+ {
+ arrived = 0;
+ isPoisoned = false;
+ }
+ }
}
More information about the jboss-svn-commits
mailing list