1 18 package com.Ostermiller.util; 19 20 33 public class CircularObjectBuffer <ElementType> { 34 35 40 private final static int DEFAULT_SIZE = 1024; 41 42 47 public final static int INFINITE_SIZE = -1; 48 49 67 protected ElementType[] buffer; 68 73 protected volatile int readPosition = 0; 74 79 protected volatile int writePosition = 0; 80 85 protected volatile boolean infinite = false; 86 92 protected boolean blockingWrite = true; 93 94 101 protected boolean inputDone = false; 102 103 110 public void clear(){ 111 synchronized (this){ 112 readPosition = 0; 113 writePosition = 0; 114 inputDone = false; 115 } 116 } 117 118 130 public int getAvailable(){ 131 synchronized (this){ 132 return available(); 133 } 134 } 135 136 149 public int getSpaceLeft(){ 150 synchronized (this){ 151 return spaceLeft(); 152 } 153 } 154 155 167 public int getSize(){ 168 synchronized (this){ 169 return buffer.length; 170 } 171 } 172 173 private ElementType[] createArray(int size){ 174 return (ElementType[]) new Object [size]; 178 } 179 180 185 private void resize(){ 186 ElementType[] newBuffer = createArray(buffer.length * 2); 187 int available = available(); 188 if (readPosition <= writePosition){ 189 int length = writePosition - readPosition; 193 System.arraycopy(buffer, readPosition, newBuffer, 0, length); 194 } else { 195 int length1 = buffer.length - readPosition; 196 System.arraycopy(buffer, readPosition, newBuffer, 0, length1); 197 int length2 = writePosition; 198 System.arraycopy(buffer, 0, newBuffer, length1, length2); 199 } 200 buffer = newBuffer; 201 readPosition = 0; 202 writePosition = available; 203 } 204 205 210 private int spaceLeft(){ 211 if (writePosition < readPosition){ 212 return (readPosition - writePosition - 1); 216 } else { 217 return ((buffer.length - 1) - (writePosition - readPosition)); 219 } 220 } 221 222 227 private int available(){ 228 if (readPosition <= writePosition){ 229 return (writePosition - readPosition); 233 } else { 234 return (buffer.length - (readPosition - writePosition)); 236 } 237 } 238 239 246 public CircularObjectBuffer(){ 247 this (DEFAULT_SIZE, true); 248 } 249 250 267 public CircularObjectBuffer(int size){ 268 this (size, true); 269 } 270 271 281 public CircularObjectBuffer(boolean blockingWrite){ 282 this (DEFAULT_SIZE, blockingWrite); 283 } 284 285 304 public CircularObjectBuffer(int size, boolean blockingWrite){ 305 if (size == INFINITE_SIZE){ 306 buffer = createArray(DEFAULT_SIZE); 307 infinite = true; 308 } else { 309 buffer = createArray(size); 310 infinite = false; 311 } 312 this.blockingWrite = blockingWrite; 313 } 314 315 316 327 public ElementType read() throws InterruptedException { 328 while (true){ 329 synchronized (this){ 330 int available = available(); 331 if (available > 0){ 332 ElementType result = buffer[readPosition]; 333 readPosition++; 334 if (readPosition == buffer.length){ 335 readPosition = 0; 336 } 337 return result; 338 } else if (inputDone){ 339 return null; 340 } 341 } 342 Thread.sleep(100); 343 } 344 } 345 346 359 public int read(ElementType[] buf) throws InterruptedException { 360 return read(buf, 0, buf.length); 361 } 362 363 378 public int read(ElementType[] buf, int off, int len) throws InterruptedException { 379 while (true){ 380 synchronized (this){ 381 int available = available(); 382 if (available > 0){ 383 int length = Math.min(len, available); 384 int firstLen = Math.min(length, buffer.length - readPosition); 385 int secondLen = length - firstLen; 386 System.arraycopy(buffer, readPosition, buf, off, firstLen); 387 if (secondLen > 0){ 388 System.arraycopy(buffer, 0, buf, off+firstLen, secondLen); 389 readPosition = secondLen; 390 } else { 391 readPosition += length; 392 } 393 if (readPosition == buffer.length) { 394 readPosition = 0; 395 } 396 return length; 397 } else if (inputDone){ 398 return -1; 399 } 400 } 401 Thread.sleep(100); 402 } 403 } 404 405 406 419 public long skip(long n) throws InterruptedException , IllegalArgumentException { 420 while (true){ 421 synchronized (this){ 422 int available = available(); 423 if (available > 0){ 424 int length = Math.min((int)n, available); 425 int firstLen = Math.min(length, buffer.length - readPosition); 426 int secondLen = length - firstLen; 427 if (secondLen > 0){ 428 readPosition = secondLen; 429 } else { 430 readPosition += length; 431 } 432 if (readPosition == buffer.length) { 433 readPosition = 0; 434 } 435 return length; 436 } else if (inputDone){ 437 return 0; 438 } 439 } 440 Thread.sleep(100); 441 } 442 } 443 444 455 public void done(){ 456 synchronized (this){ 457 inputDone = true; 458 } 459 } 460 461 476 public void write(ElementType[] buf) throws BufferOverflowException, IllegalStateException , InterruptedException { 477 write(buf, 0, buf.length); 478 } 479 480 497 public void write(ElementType[] buf, int off, int len) throws BufferOverflowException, IllegalStateException , InterruptedException { 498 while (len > 0){ 499 synchronized (CircularObjectBuffer.this){ 500 if (inputDone) throw new IllegalStateException ("CircularObjectBuffer.done() has been called, CircularObjectBuffer.write() failed."); 501 int spaceLeft = spaceLeft(); 502 while (infinite && spaceLeft < len){ 503 resize(); 504 spaceLeft = spaceLeft(); 505 } 506 if (!blockingWrite && spaceLeft < len) throw new BufferOverflowException("CircularObjectBuffer is full; cannot write " + len + " Objects"); 507 int realLen = Math.min(len, spaceLeft); 508 int firstLen = Math.min(realLen, buffer.length - writePosition); 509 int secondLen = Math.min(realLen - firstLen, buffer.length - readPosition - 1); 510 int written = firstLen + secondLen; 511 if (firstLen > 0){ 512 System.arraycopy(buf, off, buffer, writePosition, firstLen); 513 } 514 if (secondLen > 0){ 515 System.arraycopy(buf, off+firstLen, buffer, 0, secondLen); 516 writePosition = secondLen; 517 } else { 518 writePosition += written; 519 } 520 if (writePosition == buffer.length) { 521 writePosition = 0; 522 } 523 off += written; 524 len -= written; 525 } 526 if (len > 0){ 527 Thread.sleep(100); 528 } 529 } 530 } 531 532 547 public void write(ElementType o) throws BufferOverflowException, IllegalStateException , InterruptedException { 548 boolean written = false; 549 while (!written){ 550 synchronized (CircularObjectBuffer.this){ 551 if (inputDone) throw new IllegalStateException ("CircularObjectBuffer.done() has been called, CircularObjectBuffer.write() failed."); 552 int spaceLeft = spaceLeft(); 553 while (infinite && spaceLeft < 1){ 554 resize(); 555 spaceLeft = spaceLeft(); 556 } 557 if (!blockingWrite && spaceLeft < 1) throw new BufferOverflowException("CircularObjectBuffer is full; cannot write 1 Object"); 558 if (spaceLeft > 0){ 559 buffer[writePosition] = o; 560 writePosition++; 561 if (writePosition == buffer.length) { 562 writePosition = 0; 563 } 564 written = true; 565 } 566 } 567 if (!written){ 568 Thread.sleep(100); 569 } 570 } 571 } 572 } 573 | Popular Tags |