< prev index next >

src/java.corba/share/classes/com/sun/corba/se/impl/orbutil/concurrent/Sync.java

Print this page




 164  *     for (;;) {
 165  *       try {
 166  *         lock.acquire();
 167  *         try {
 168  *           if (other.lock.attempt(100)) {
 169  *             try {
 170  *               long t = value;
 171  *               value = other.value;
 172  *               other.value = t;
 173  *               return;
 174  *             }
 175  *             finally { other.lock.release(); }
 176  *           }
 177  *         }
 178  *         finally { lock.release(); }
 179  *       }
 180  *       catch (InterruptedException ex) { return; }
 181  *     }
 182  *   }
 183  * }
 184  *</pre>
 185  * <p>
 186  * Here is an even fancier version, that uses lock re-ordering
 187  * upon conflict:
 188  * <pre>
 189  * class Cell {
 190  *   long value;
 191  *   Sync lock = ...;
 192  *   private static boolean trySwap(Cell a, Cell b) {
 193  *     a.lock.acquire();
 194  *     try {
 195  *       if (!b.lock.attempt(0))
 196  *         return false;
 197  *       try {
 198  *         long t = a.value;
 199  *         a.value = b.value;
 200  *         b.value = t;
 201  *         return true;
 202  *       }
 203  *       finally { other.lock.release(); }
 204  *     }
 205  *     finally { lock.release(); }
 206  *     return false;
 207  *   }
 208  *
 209  *  void swapValue(Cell other) {
 210  *    try {
 211  *      while (!trySwap(this, other) &&
 212  *            !tryswap(other, this))
 213  *        Thread.sleep(1);
 214  *    }
 215  *    catch (InterruptedException ex) { return; }
 216  *  }
 217  *}
 218  *</pre>
 219  * <p>
 220  * Interruptions are in general handled as early as possible.
 221  * Normally, InterruptionExceptions are thrown
 222  * in acquire and attempt(msec) if interruption
 223  * is detected upon entry to the method, as well as in any
 224  * later context surrounding waits.
 225  * However, interruption status is ignored in release();
 226  * <p>
 227  * Timed versions of attempt report failure via return value.
 228  * If so desired, you can transform such constructions to use exception
 229  * throws via
 230  * <pre>
 231  *   if (!c.attempt(timeval)) throw new TimeoutException(timeval);
 232  * </pre>
 233  * <p>
 234  * The TimoutSync wrapper class can be used to automate such usages.
 235  * <p>
 236  * All time values are expressed in milliseconds as longs, which have a maximum
 237  * value of Long.MAX_VALUE, or almost 300,000 centuries. It is not
 238  * known whether JVMs actually deal correctly with such extreme values.
 239  * For convenience, some useful time values are defined as static constants.
 240  * <p>
 241  * All implementations of the three Sync methods guarantee to
 242  * somehow employ Java <code>synchronized</code> methods or blocks,
 243  * and so entail the memory operations described in JLS
 244  * chapter 17 which ensure that variables are loaded and flushed
 245  * within before/after constructions.
 246  * <p>
 247  * Syncs may also be used in spinlock constructions. Although
 248  * it is normally best to just use acquire(), various forms
 249  * of busy waits can be implemented. For a simple example
 250  * (but one that would probably never be preferable to using acquire()):
 251  * <pre>
 252  * class X {
 253  *   Sync lock = ...
 254  *   void spinUntilAcquired() throws InterruptedException {
 255  *     // Two phase.
 256  *     // First spin without pausing.
 257  *     int purespins = 10;
 258  *     for (int i = 0; i < purespins; ++i) {
 259  *       if (lock.attempt(0))
 260  *         return true;
 261  *     }
 262  *     // Second phase - use timed waits
 263  *     long waitTime = 1; // 1 millisecond
 264  *     for (;;) {
 265  *       if (lock.attempt(waitTime))
 266  *         return true;
 267  *       else
 268  *         waitTime = waitTime * 3 / 2 + 1; // increase 50%
 269  *     }
 270  *   }
 271  * }
 272  * </pre>
 273  * <p>
 274  * In addition pure synchronization control, Syncs
 275  * may be useful in any context requiring before/after methods.
 276  * For example, you can use an ObservableSync
 277  * (perhaps as part of a LayeredSync) in order to obtain callbacks
 278  * before and after each method invocation for a given class.
 279  *
 280  * <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]
 281  **/
 282 
 283 
 284 public interface Sync {
 285 
 286   /**
 287    *  Wait (possibly forever) until successful passage.
 288    *  Fail only upon interuption. Interruptions always result in
 289    *  `clean' failures. On failure,  you can be sure that it has not
 290    *  been acquired, and that no
 291    *  corresponding release should be performed. Conversely,
 292    *  a normal return guarantees that the acquire was successful.
 293   **/
 294 
 295   public void acquire() throws InterruptedException;
 296 
 297   /**
 298    * Wait at most msecs to pass; report whether passed.
 299    * <p>
 300    * The method has best-effort semantics:




 164  *     for (;;) {
 165  *       try {
 166  *         lock.acquire();
 167  *         try {
 168  *           if (other.lock.attempt(100)) {
 169  *             try {
 170  *               long t = value;
 171  *               value = other.value;
 172  *               other.value = t;
 173  *               return;
 174  *             }
 175  *             finally { other.lock.release(); }
 176  *           }
 177  *         }
 178  *         finally { lock.release(); }
 179  *       }
 180  *       catch (InterruptedException ex) { return; }
 181  *     }
 182  *   }
 183  * }
 184  * </pre>
 185  * <p>
 186  * Here is an even fancier version, that uses lock re-ordering
 187  * upon conflict:
 188  * <pre>{@code
 189  * class Cell {
 190  *   long value;
 191  *   Sync lock = ...;
 192  *   private static boolean trySwap(Cell a, Cell b) {
 193  *     a.lock.acquire();
 194  *     try {
 195  *       if (!b.lock.attempt(0))
 196  *         return false;
 197  *       try {
 198  *         long t = a.value;
 199  *         a.value = b.value;
 200  *         b.value = t;
 201  *         return true;
 202  *       }
 203  *       finally { other.lock.release(); }
 204  *     }
 205  *     finally { lock.release(); }
 206  *     return false;
 207  *   }
 208  *
 209  *  void swapValue(Cell other) {
 210  *    try {
 211  *      while (!trySwap(this, other) &&
 212  *            !tryswap(other, this))
 213  *        Thread.sleep(1);
 214  *    }
 215  *    catch (InterruptedException ex) { return; }
 216  *  }
 217  * }
 218  * }</pre>
 219  * <p>
 220  * Interruptions are in general handled as early as possible.
 221  * Normally, InterruptionExceptions are thrown
 222  * in acquire and attempt(msec) if interruption
 223  * is detected upon entry to the method, as well as in any
 224  * later context surrounding waits.
 225  * However, interruption status is ignored in release();
 226  * <p>
 227  * Timed versions of attempt report failure via return value.
 228  * If so desired, you can transform such constructions to use exception
 229  * throws via
 230  * <pre>
 231  *   if (!c.attempt(timeval)) throw new TimeoutException(timeval);
 232  * </pre>
 233  * <p>
 234  * The TimoutSync wrapper class can be used to automate such usages.
 235  * <p>
 236  * All time values are expressed in milliseconds as longs, which have a maximum
 237  * value of Long.MAX_VALUE, or almost 300,000 centuries. It is not
 238  * known whether JVMs actually deal correctly with such extreme values.
 239  * For convenience, some useful time values are defined as static constants.
 240  * <p>
 241  * All implementations of the three Sync methods guarantee to
 242  * somehow employ Java <code>synchronized</code> methods or blocks,
 243  * and so entail the memory operations described in JLS
 244  * chapter 17 which ensure that variables are loaded and flushed
 245  * within before/after constructions.
 246  * <p>
 247  * Syncs may also be used in spinlock constructions. Although
 248  * it is normally best to just use acquire(), various forms
 249  * of busy waits can be implemented. For a simple example
 250  * (but one that would probably never be preferable to using acquire()):
 251  * <pre>{@code
 252  * class X {
 253  *   Sync lock = ...
 254  *   void spinUntilAcquired() throws InterruptedException {
 255  *     // Two phase.
 256  *     // First spin without pausing.
 257  *     int purespins = 10;
 258  *     for (int i = 0; i < purespins; ++i) {
 259  *       if (lock.attempt(0))
 260  *         return true;
 261  *     }
 262  *     // Second phase - use timed waits
 263  *     long waitTime = 1; // 1 millisecond
 264  *     for (;;) {
 265  *       if (lock.attempt(waitTime))
 266  *         return true;
 267  *       else
 268  *         waitTime = waitTime * 3 / 2 + 1; // increase 50%
 269  *     }
 270  *   }
 271  * }
 272  * }</pre>
 273  * <p>
 274  * In addition pure synchronization control, Syncs
 275  * may be useful in any context requiring before/after methods.
 276  * For example, you can use an ObservableSync
 277  * (perhaps as part of a LayeredSync) in order to obtain callbacks
 278  * before and after each method invocation for a given class.
 279  *
 280  * [<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]
 281  **/
 282 
 283 
 284 public interface Sync {
 285 
 286   /**
 287    *  Wait (possibly forever) until successful passage.
 288    *  Fail only upon interuption. Interruptions always result in
 289    *  `clean' failures. On failure,  you can be sure that it has not
 290    *  been acquired, and that no
 291    *  corresponding release should be performed. Conversely,
 292    *  a normal return guarantees that the acquire was successful.
 293   **/
 294 
 295   public void acquire() throws InterruptedException;
 296 
 297   /**
 298    * Wait at most msecs to pass; report whether passed.
 299    * <p>
 300    * The method has best-effort semantics:


< prev index next >