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 015import org.vmmagic.pragma.Unpreemptible; 016import org.vmmagic.pragma.Uninterruptible; 017 018/** 019 * An implementation of a latch using the HeavyCondLock in "nice" mode. 020 * This essentially gives you park/unpark functionality. It can also 021 * be used like the Win32-style AutoResetEvent or ManualResetEvent. 022 * <p> 023 * Park/unpark example: use open() to unpark and waitAndClose() to park. 024 * <p> 025 * AutoResetEvent example: use open() to set, close() to reset, and 026 * waitAndClose() to wait. 027 * <p> 028 * ManualResetEvent example: use open() to set, close() to reset, and 029 * wait() to wait. 030 */ 031@Unpreemptible 032public class Latch { 033 private final Monitor schedLock = new Monitor(); 034 private boolean open; 035 036 /** 037 * Create a new latch, with the given open/closed state. 038 * @param open whether the latch is open or closed at 039 * the beginning 040 */ 041 public Latch(boolean open) { 042 this.open = open; 043 } 044 /** 045 * Open the latch and let all of the thread(s) waiting on it through. 046 * But - if any of the threads is using waitAndClose(), then as soon 047 * as that thread awakes further threads will be blocked. 048 */ 049 public void openWithHandshake() { 050 schedLock.lockWithHandshake(); 051 open = true; 052 schedLock.broadcast(); 053 schedLock.unlock(); 054 } 055 /** 056 * Like open(), but does it without letting the system know that we 057 * could potentially block. This is faster, and better for use in 058 * interrupt handlers. 059 */ 060 @Uninterruptible 061 public void openNoHandshake() { 062 schedLock.lockNoHandshake(); 063 open = true; 064 schedLock.broadcast(); 065 schedLock.unlock(); 066 } 067 /** 068 * Close the latch, causing future calls to wait() or waitAndClose() 069 * to block. 070 */ 071 public void closeWithHandshake() { 072 schedLock.lockWithHandshake(); 073 open = false; 074 schedLock.unlock(); 075 } 076 /** 077 * Wait for the latch to become open. If it is already open, don't 078 * wait at all. 079 */ 080 public void waitWithHandshake() { 081 schedLock.lockWithHandshake(); 082 while (!open) { 083 schedLock.waitWithHandshake(); 084 } 085 schedLock.unlock(); 086 } 087 /** 088 * Wait for the latch to become open, and then close it and return. 089 * If the latch is already open, don't wait at all, just close it 090 * immediately and return. 091 */ 092 public void waitAndCloseWithHandshake() { 093 schedLock.lockWithHandshake(); 094 while (!open) { 095 schedLock.waitWithHandshake(); 096 } 097 open = false; 098 schedLock.unlock(); 099 } 100}