001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.scheduler;
014    
015    /**
016     * An implementation of a latch using monitors.
017     * This essentially gives you park/unpark functionality.  It can also
018     * be used like the Win32-style AutoResetEvent or ManualResetEvent.
019     * <p>
020     * Park/unpark example: use open() to unpark and waitAndClose() to park.
021     * <p>
022     * AutoResetEvent example: use open() to set, close() to reset, and
023     * waitAndClose() to wait.
024     * <p>
025     * ManualResetEvent example: use open() to set, close() to reset, and
026     * wait() to wait.
027     * <p>
028     * Note: <b><i>never</i></b> synchronize on instances of this class.
029     */
030    public class SoftLatch {
031    
032      private boolean open;
033    
034      /** Create a new latch, with the given open/closed state. */
035      public SoftLatch(boolean open) {
036        this.open = open;
037      }
038    
039      /**
040       * Open the latch and let all of the thread(s) waiting on it through.
041       * But - if any of the threads is using waitAndClose(), then as soon
042       * as that thread awakes further threads will be blocked.
043       */
044      public synchronized void open() {
045        open=true;
046        notifyAll();
047      }
048    
049      /**
050       * Close the latch, causing future calls to wait() or waitAndClose()
051       * to block.
052       */
053      public synchronized void close() {
054        open=false;
055      }
056    
057      /**
058       * Wait for the latch to become open.  If it is already open, don't
059       * wait at all.
060       */
061      public synchronized void await() {
062        while (!open) {
063          try {
064            wait();
065          } catch (InterruptedException e) {
066            throw new Error(e);
067          }
068        }
069      }
070    
071      /**
072       * Wait for the latch to become open, and then close it and return.
073       * If the latch is already open, don't wait at all, just close it
074       * immediately and return.
075       */
076      public synchronized void waitAndClose() {
077        while (!open) {
078          try {
079            wait();
080          } catch (InterruptedException e) {
081            throw new Error(e);
082          }
083        }
084        open=false;
085      }
086    }