/*
* 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.adaptive.util;
import org.jikesrvm.VM;
import org.jikesrvm.util.PriorityQueueRVM;
/**
* This class extends PriorityQueueRVM to safely
* support multiple producers/consumers where
* the consumers are blocked if no objects are available
* to consume.
*/
public class BlockingPriorityQueue extends PriorityQueueRVM {
/**
* Used to notify consumers when about to wait and when notified
* Default implementation does nothing, but can be overriden as needed by client.
*/
public static class CallBack {
public void aboutToWait() {}
public void doneWaiting() {}
}
CallBack callback;
/**
* @param _cb the callback object
*/
public BlockingPriorityQueue(CallBack _cb) {
super();
callback = _cb;
}
public BlockingPriorityQueue() {
this(new CallBack());
}
/**
* Insert the object passed with the priority value passed.<p>
*
* Notify any sleeping consumer threads that an object
* is available for consumption.
*
* @param _priority the priority to
* @param _data the object to insert
*/
@Override
public final synchronized void insert(double _priority, Object _data) {
super.insert(_priority, _data);
try {
notifyAll();
} catch (Exception e) {
// TODO: should we exit or something more dramatic?
VM.sysWriteln("Exception occurred while notifying that element was inserted!");
}
}
/**
* Remove and return the front (minimum) object. If the queue is currently
* empty, then block until an object is available to be dequeued.
*
* @return the front (minimum) object.
*/
@Override
public final synchronized Object deleteMin() {
// While the queue is empty, sleep until notified that an object has been enqueued.
while (isEmpty()) {
try {
callback.aboutToWait();
wait();
callback.doneWaiting();
} catch (InterruptedException e) {
// TODO: should we exit or something more dramatic?
VM.sysWriteln("Interrupted Exception occurred!");
}
}
// When we get to here, we know the queue is non-empty, so dequeue an object and return it.
return super.deleteMin();
}
}