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 */
013package 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 */
030public class SoftLatch {
031
032  private boolean open;
033
034  /**
035   * Creates a new latch, with the given open/closed state.
036   * @param open whether the latch is open at the beginning
037   */
038  public SoftLatch(boolean open) {
039    this.open = open;
040  }
041
042  /**
043   * Open the latch and let all of the thread(s) waiting on it through.
044   * But - if any of the threads is using waitAndClose(), then as soon
045   * as that thread awakes further threads will be blocked.
046   */
047  public synchronized void open() {
048    open = true;
049    notifyAll();
050  }
051
052  /**
053   * Close the latch, causing future calls to wait() or waitAndClose()
054   * to block.
055   */
056  public synchronized void close() {
057    open = false;
058  }
059
060  /**
061   * Wait for the latch to become open.  If it is already open, don't
062   * wait at all.
063   */
064  public synchronized void await() {
065    while (!open) {
066      try {
067        wait();
068      } catch (InterruptedException e) {
069        throw new Error(e);
070      }
071    }
072  }
073
074  /**
075   * Wait for the latch to become open, and then close it and return.
076   * If the latch is already open, don't wait at all, just close it
077   * immediately and return.
078   */
079  public synchronized void waitAndClose() {
080    while (!open) {
081      try {
082        wait();
083      } catch (InterruptedException e) {
084        throw new Error(e);
085      }
086    }
087    open = false;
088  }
089}