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.adaptive.util; 014 015import org.jikesrvm.VM; 016import org.jikesrvm.util.PriorityQueueRVM; 017 018/** 019 * This class extends PriorityQueueRVM to safely 020 * support multiple producers/consumers where 021 * the consumers are blocked if no objects are available 022 * to consume. 023 */ 024public class BlockingPriorityQueue extends PriorityQueueRVM { 025 026 /** 027 * Used to notify consumers when about to wait and when notified 028 * Default implementation does nothing, but can be overriden as needed by client. 029 */ 030 public static class CallBack { 031 public void aboutToWait() {} 032 033 public void doneWaiting() {} 034 } 035 036 CallBack callback; 037 038 /** 039 * @param _cb the callback object 040 */ 041 public BlockingPriorityQueue(CallBack _cb) { 042 super(); 043 callback = _cb; 044 } 045 046 public BlockingPriorityQueue() { 047 this(new CallBack()); 048 } 049 050 /** 051 * Insert the object passed with the priority value passed.<p> 052 * 053 * Notify any sleeping consumer threads that an object 054 * is available for consumption. 055 * 056 * @param _priority the priority to 057 * @param _data the object to insert 058 */ 059 @Override 060 public final synchronized void insert(double _priority, Object _data) { 061 super.insert(_priority, _data); 062 try { 063 notifyAll(); 064 } catch (Exception e) { 065 // TODO: should we exit or something more dramatic? 066 VM.sysWrite("Exception occurred while notifying that element was inserted!\n"); 067 } 068 } 069 070 /** 071 * Remove and return the front (minimum) object. If the queue is currently 072 * empty, then block until an object is available to be dequeued. 073 * 074 * @return the front (minimum) object. 075 */ 076 @Override 077 public final synchronized Object deleteMin() { 078 // While the queue is empty, sleep until notified that an object has been enqueued. 079 while (isEmpty()) { 080 try { 081 callback.aboutToWait(); 082 wait(); 083 callback.doneWaiting(); 084 } catch (InterruptedException e) { 085 // TODO: should we exit or something more dramatic? 086 VM.sysWrite("Interrupted Exception occurred!\n"); 087 } 088 } 089 090 // When we get to here, we know the queue is non-empty, so dequeue an object and return it. 091 return super.deleteMin(); 092 } 093}