/*
* JBoss, Home of Professional Open Source
* Copyright 2008-10 Red Hat and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*
* @authors Andrew Dinn
*/
package org.jboss.byteman.synchronization;
import org.jboss.byteman.rule.exception.ExecuteException;
/**
* class used to manage rule wait operations
*/
public class Waiter
{
public Waiter(Object object)
{
this(object, false, false);
}
public Waiter(Object object, boolean signalled, boolean killed)
{
this.waiterFor = object;
this.signalled = signalled;
this.killed = killed;
this.waiting = false;
}
public void waitFor(long millisecs)
{
long start = System.currentTimeMillis();
long waitForMillis = millisecs;
synchronized(this) {
waiting = true;
while (!signalled && waitForMillis >= 0){
try {
if (waitForMillis == 0 && millisecs > 0) {
break;
}
this.wait(waitForMillis);
} catch (InterruptedException e) {
// ignore
}
if (!signalled)
{
waitForMillis = (millisecs == 0) ? 0 : millisecs + start - System.currentTimeMillis();
}
}
if (signalled) {
// notify in case a signalling thread was waiting
this.notifyAll();
}
}
// if a signalKill was used then we have to throw an exception otherwise we just return
if (killed) {
throw new ExecuteException("Waiter.waitFor : killed thread waiting for " + waiterFor);
}
}
public boolean signalWake()
{
boolean result;
synchronized (this) {
result = signalled;
if (!signalled) {
signalled = true;
this.notifyAll();
}
}
return result;
}
public boolean signalThrow()
{
boolean result;
synchronized (this) {
result = signalled;
if (!signalled) {
signalled = true;
killed = true;
this.notifyAll();
}
}
return result;
}
public boolean waiting()
{
return waiting;
}
/**
* the object with which this waiter is associated
*/
private Object waiterFor;
/**
* true if this waiter has been signalled by a call to signalKill
*/
private boolean signalled;
/**
* true if this waiter has been signalled by a call to signal or signalKill
*/
private boolean killed;
/**
* true if waitFor has been called
*/
private boolean waiting;
/**
* getter for signalled flag
* @return signalled
*/
public boolean isSignalled() {
return signalled;
}
}