1. /*
  2. * @(#)ReferenceQueue.java 1.23 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.lang.ref;
  8. /**
  9. * Reference queues, to which registered reference objects are appended by the
  10. * garbage collector after the appropriate reachability changes are detected.
  11. *
  12. * @version 1.23, 12/19/03
  13. * @author Mark Reinhold
  14. * @since 1.2
  15. */
  16. public class ReferenceQueue<T> {
  17. /**
  18. * Constructs a new reference-object queue.
  19. */
  20. public ReferenceQueue() { }
  21. private static class Null extends ReferenceQueue {
  22. boolean enqueue(Reference r) {
  23. return false;
  24. }
  25. }
  26. static ReferenceQueue NULL = new Null();
  27. static ReferenceQueue ENQUEUED = new Null();
  28. static private class Lock { };
  29. private Lock lock = new Lock();
  30. private Reference<? extends T> head = null;
  31. private long queueLength = 0;
  32. boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
  33. synchronized (r) {
  34. if (r.queue == ENQUEUED) return false;
  35. synchronized (lock) {
  36. r.queue = ENQUEUED;
  37. r.next = (head == null) ? r : head;
  38. head = r;
  39. queueLength++;
  40. if (r instanceof FinalReference) {
  41. sun.misc.VM.addFinalRefCount(1);
  42. }
  43. lock.notifyAll();
  44. return true;
  45. }
  46. }
  47. }
  48. private Reference<? extends T> reallyPoll() { /* Must hold lock */
  49. if (head != null) {
  50. Reference<? extends T> r = head;
  51. head = (r.next == r) ? null : r.next;
  52. r.queue = NULL;
  53. r.next = r;
  54. queueLength--;
  55. if (r instanceof FinalReference) {
  56. sun.misc.VM.addFinalRefCount(-1);
  57. }
  58. return r;
  59. }
  60. return null;
  61. }
  62. /**
  63. * Polls this queue to see if a reference object is available. If one is
  64. * available without further delay then it is removed from the queue and
  65. * returned. Otherwise this method immediately returns <tt>null</tt>.
  66. *
  67. * @return A reference object, if one was immediately available,
  68. * otherwise <code>null</code>
  69. */
  70. public Reference<? extends T> poll() {
  71. synchronized (lock) {
  72. return reallyPoll();
  73. }
  74. }
  75. /**
  76. * Removes the next reference object in this queue, blocking until either
  77. * one becomes available or the given timeout period expires.
  78. *
  79. * <p> This method does not offer real-time guarantees: It schedules the
  80. * timeout as if by invoking the {@link Object#wait(long)} method.
  81. *
  82. * @param timeout If positive, block for up <code>timeout</code>
  83. * milliseconds while waiting for a reference to be
  84. * added to this queue. If zero, block indefinitely.
  85. *
  86. * @return A reference object, if one was available within the specified
  87. * timeout period, otherwise <code>null</code>
  88. *
  89. * @throws IllegalArgumentException
  90. * If the value of the timeout argument is negative
  91. *
  92. * @throws InterruptedException
  93. * If the timeout wait is interrupted
  94. */
  95. public Reference<? extends T> remove(long timeout)
  96. throws IllegalArgumentException, InterruptedException
  97. {
  98. if (timeout < 0) {
  99. throw new IllegalArgumentException("Negative timeout value");
  100. }
  101. synchronized (lock) {
  102. Reference<? extends T> r = reallyPoll();
  103. if (r != null) return r;
  104. for (;;) {
  105. lock.wait(timeout);
  106. r = reallyPoll();
  107. if (r != null) return r;
  108. if (timeout != 0) return null;
  109. }
  110. }
  111. }
  112. /**
  113. * Removes the next reference object in this queue, blocking until one
  114. * becomes available.
  115. *
  116. * @return A reference object, blocking until one becomes available
  117. * @throws InterruptedException If the wait is interrupted
  118. */
  119. public Reference<? extends T> remove() throws InterruptedException {
  120. return remove(0);
  121. }
  122. }