/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.scheduler;
import org.vmmagic.pragma.Unpreemptible;
import org.vmmagic.pragma.Uninterruptible;
/**
* An implementation of a latch using the HeavyCondLock in "nice" mode.
* This essentially gives you park/unpark functionality. It can also
* be used like the Win32-style AutoResetEvent or ManualResetEvent.
* <p>
* Park/unpark example: use open() to unpark and waitAndClose() to park.
* <p>
* AutoResetEvent example: use open() to set, close() to reset, and
* waitAndClose() to wait.
* <p>
* ManualResetEvent example: use open() to set, close() to reset, and
* wait() to wait.
*/
@Unpreemptible
public class Latch {
private final Monitor schedLock = new Monitor();
private boolean open;
/**
* Create a new latch, with the given open/closed state.
* @param open whether the latch is open or closed at
* the beginning
*/
public Latch(boolean open) {
this.open = open;
}
/**
* Open the latch and let all of the thread(s) waiting on it through.
* But - if any of the threads is using waitAndClose(), then as soon
* as that thread awakes further threads will be blocked.
*/
public void openWithHandshake() {
schedLock.lockWithHandshake();
open = true;
schedLock.broadcast();
schedLock.unlock();
}
/**
* Like open(), but does it without letting the system know that we
* could potentially block. This is faster, and better for use in
* interrupt handlers.
*/
@Uninterruptible
public void openNoHandshake() {
schedLock.lockNoHandshake();
open = true;
schedLock.broadcast();
schedLock.unlock();
}
/**
* Close the latch, causing future calls to wait() or waitAndClose()
* to block.
*/
public void closeWithHandshake() {
schedLock.lockWithHandshake();
open = false;
schedLock.unlock();
}
/**
* Wait for the latch to become open. If it is already open, don't
* wait at all.
*/
public void waitWithHandshake() {
schedLock.lockWithHandshake();
while (!open) {
schedLock.waitWithHandshake();
}
schedLock.unlock();
}
/**
* Wait for the latch to become open, and then close it and return.
* If the latch is already open, don't wait at all, just close it
* immediately and return.
*/
public void waitAndCloseWithHandshake() {
schedLock.lockWithHandshake();
while (!open) {
schedLock.waitWithHandshake();
}
open = false;
schedLock.unlock();
}
}