001 /* 002 * $Id: Deque.java,v 1.7 2002/08/11 15:58:00 kredel Exp $ 003 */ 004 005 //package edu.unima.ky.parallel; 006 package thread; 007 008 import java.io.*; 009 010 /** 011 * This Deque class implements a double ended queue in a 012 * similar way as the class BoundedBuffer does. 013 * It has some capacity to store objects. 014 * With the method <code>put</code> objects are placed into 015 * the buffer. With the <code>get</code> method objects are taken 016 * from the buffer in FIFO order and with <code>pop</code> objects 017 * are taken from the buffer in LIFO order. 018 * <code>put</code> blocks if there is no space to 019 * place a object into the buffer. 020 * <code>get</code> and <code>pop</code> block if there are 021 * no objects in the channel. 022 * This class is safe against Thread InterruptedException. 023 * @author Akitoshi Yoshida 024 * @author Heinz Kredel. 025 * @see BoundedBuffer 026 * see Channel 027 * see Queue 028 * see Deque 029 * see MemoryChannel 030 * see SyncChannel 031 * see Stack 032 */ 033 034 public class Deque implements Serializable { 035 036 /** 037 * the buffer is the deque contents. 038 */ 039 private Object[] buffer; 040 041 /** 042 * the buffer's size. 043 */ 044 private int size; 045 046 /** 047 * index to the first filled cell. 048 */ 049 private int front; 050 051 /** 052 * index to the first empty cell. 053 */ 054 private int rear; 055 056 /** 057 * a semaphore indicating an empty cell. 058 */ 059 private Semaphore empty; 060 061 /** 062 * a semaphore indicating a filled cell. 063 */ 064 private Semaphore full; 065 066 /** 067 * mutex for send. 068 */ 069 private Object snd; 070 071 /** 072 * mutex for receive. 073 */ 074 private Object rcv; 075 076 /** 077 * Declares an undefined value of type <CODE>String</CODE>. 078 */ 079 public final static String undefined = "undefined value"; 080 081 082 /** 083 * Construct a Deque. 084 * @param init An integer which defines the deques size. 085 */ 086 public Deque(int init) { 087 buffer = new Object[init]; 088 size = init; front = 0; rear = 0; 089 empty = new Semaphore(init); 090 full = new Semaphore(0); 091 snd = new Object(); 092 rcv = new Object(); 093 } 094 095 096 /** 097 * Put an object to the deque. 098 * Return without object put if Interrupted. 099 * @exception InterruptedException. 100 */ 101 public void put(Object v) throws InterruptedException { 102 empty.P(); // return without Object put if Interrupted 103 synchronized (snd) { 104 if (rear < 0) rear += size; 105 if (rear >= size) rear -= size; 106 buffer[rear] = v; 107 rear++; 108 } 109 full.V(); 110 } 111 112 113 /** 114 * Push an object to the deque. 115 * Return without object pushed if Interrupted. 116 * @exception InterruptedException. 117 */ 118 public void push(Object v) throws InterruptedException { 119 put(v); 120 } 121 122 123 /** 124 * Get an object from the deque, FIFO order. 125 * @exception InterruptedException. 126 * @return null object if Interrupted. 127 */ 128 public Object get() throws InterruptedException { 129 Object v = null; 130 full.P(); // return without Object if Interrupted 131 synchronized (rcv) { 132 if (front >= size) front -= size; 133 v = buffer[front]; 134 front++; 135 } 136 empty.V(); 137 return v; 138 } 139 140 141 /** 142 * Get an object from the deque within given timeout, FIFO order. 143 * @exception InterruptedException. 144 * @return null object if Interrupted. 145 */ 146 public Object get(int m) throws InterruptedException { 147 Object v = null; 148 if ( !full.P(m) ) return undefined; 149 // return without Object if Interrupted 150 synchronized (rcv) { 151 if (front >= size) front -= size; 152 v = buffer[front]; 153 front++; 154 } 155 empty.V(); 156 return v; 157 } 158 159 160 /** 161 * Pop an object from the deque, LIFO order. 162 * @exception InterruptedException. 163 * @return null object if Interrupted. 164 */ 165 public Object pop() throws InterruptedException { 166 Object v = null; 167 full.P(); // return without Object if Interrupted 168 synchronized (snd) { 169 rear--; 170 if (rear < 0) rear += size; 171 if (rear >= size) rear -= size; 172 v = buffer[rear]; 173 } 174 empty.V(); 175 return v; 176 } 177 178 179 /** 180 * Pop an object from the deque within given timeout, LIFO order. 181 * @exception InterruptedException. 182 * @return null object if Interrupted. 183 */ 184 public Object pop(int m) throws InterruptedException { 185 Object v = null; 186 if ( !full.P(m) ) return undefined; 187 // return without Object if Interrupted 188 synchronized (snd) { 189 rear--; 190 if (rear < 0) rear += size; 191 if (rear >= size) rear -= size; 192 v = buffer[rear]; 193 } 194 empty.V(); 195 return v; 196 } 197 198 199 /** 200 * Tests if the deque is empty. 201 */ 202 public boolean empty() { 203 return ( !full.isPositive() ); 204 } 205 206 207 /** 208 * Get the number of elements in the deque. 209 * @return size of deque. 210 */ 211 public int size() { 212 int s = rear - front; 213 if ( s < 0 ) { 214 s += size; 215 } 216 return s; 217 } 218 219 }