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 import org.vmmagic.pragma.Unpreemptible; 016 import 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 032 public class Latch { 033 private final Monitor schedLock = new Monitor(); 034 private boolean open; 035 /** Create a new latch, with the given open/closed state. */ 036 public Latch(boolean open) { 037 this.open = open; 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 void openWithHandshake() { 045 schedLock.lockWithHandshake(); 046 open=true; 047 schedLock.broadcast(); 048 schedLock.unlock(); 049 } 050 /** 051 * Like open(), but does it without letting the system know that we 052 * could potentially block. This is faster, and better for use in 053 * interrupt handlers. 054 */ 055 @Uninterruptible 056 public void openNoHandshake() { 057 schedLock.lockNoHandshake(); 058 open=true; 059 schedLock.broadcast(); 060 schedLock.unlock(); 061 } 062 /** 063 * Close the latch, causing future calls to wait() or waitAndClose() 064 * to block. 065 */ 066 public void closeWithHandshake() { 067 schedLock.lockWithHandshake(); 068 open=false; 069 schedLock.unlock(); 070 } 071 /** 072 * Wait for the latch to become open. If it is already open, don't 073 * wait at all. 074 */ 075 public void waitWithHandshake() { 076 schedLock.lockWithHandshake(); 077 while (!open) { 078 schedLock.waitWithHandshake(); 079 } 080 schedLock.unlock(); 081 } 082 /** 083 * Wait for the latch to become open, and then close it and return. 084 * If the latch is already open, don't wait at all, just close it 085 * immediately and return. 086 */ 087 public void waitAndCloseWithHandshake() { 088 schedLock.lockWithHandshake(); 089 while (!open) { 090 schedLock.waitWithHandshake(); 091 } 092 open=false; 093 schedLock.unlock(); 094 } 095 }