[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