1. /*
  2. * @(#)ReferenceQueue.java 1.20 03/01/23
  3. *
  4. * Copyright 2003 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.20, 01/23/03
  13. * @author Mark Reinhold
  14. * @since 1.2
  15. */
  16. public class ReferenceQueue {
  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 head = null;
  31. private long queueLength = 0;
  32. boolean enqueue(Reference 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. lock.notifyAll();
  41. return true;
  42. }
  43. }
  44. }
  45. private Reference reallyPoll() { /* Must hold lock */
  46. if (head != null) {
  47. Reference r = head;
  48. head = (r.next == r) ? null : r.next;
  49. r.queue = NULL;
  50. r.next = r;
  51. queueLength--;
  52. return r;
  53. }
  54. return null;
  55. }
  56. /**
  57. * Polls this queue to see if a reference object is available. If one is
  58. * available without further delay then it is removed from the queue and
  59. * returned. Otherwise this method immediately returns <tt>null</tt>.
  60. *
  61. * @return A reference object, if one was immediately available,
  62. * otherwise <code>null</code>
  63. */
  64. public Reference poll() {
  65. synchronized (lock) {
  66. return reallyPoll();
  67. }
  68. }
  69. /**
  70. * Removes the next reference object in this queue, blocking until either
  71. * one becomes available or the given timeout period expires.
  72. *
  73. * <p> This method does not offer real-time guarantees: It schedules the
  74. * timeout as if by invoking the {@link Object#wait(long)} method.
  75. *
  76. * @param timeout If positive, block for up <code>timeout</code>
  77. * milliseconds while waiting for a reference to be
  78. * added to this queue. If zero, block indefinitely.
  79. *
  80. * @return A reference object, if one was available within the specified
  81. * timeout period, otherwise <code>null</code>
  82. *
  83. * @throws IllegalArgumentException
  84. * If the value of the timeout argument is negative
  85. *
  86. * @throws InterruptedException
  87. * If the timeout wait is interrupted
  88. */
  89. public Reference remove(long timeout)
  90. throws IllegalArgumentException, InterruptedException
  91. {
  92. if (timeout < 0) {
  93. throw new IllegalArgumentException("Negative timeout value");
  94. }
  95. synchronized (lock) {
  96. Reference r = reallyPoll();
  97. if (r != null) return r;
  98. for (;;) {
  99. lock.wait(timeout);
  100. r = reallyPoll();
  101. if (r != null) return r;
  102. if (timeout != 0) return null;
  103. }
  104. }
  105. }
  106. /**
  107. * Removes the next reference object in this queue, blocking until one
  108. * becomes available.
  109. *
  110. * @return A reference object, blocking until one becomes available
  111. * @throws InterruptedException If the wait is interrupted
  112. */
  113. public Reference remove() throws InterruptedException {
  114. return remove(0);
  115. }
  116. }