1. /*
  2. * @(#)ReferenceQueue.java 1.11 01/11/29
  3. *
  4. * Copyright 2002 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.11, 01/11/29
  13. * @author Mark Reinhold
  14. * @since JDK1.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. boolean enqueue(Reference r) { /* Called only by Reference class */
  32. synchronized (r) {
  33. if (r.queue == ENQUEUED) return false;
  34. synchronized (lock) {
  35. r.queue = ENQUEUED;
  36. r.next = (head == null) ? r : head;
  37. head = r;
  38. lock.notifyAll();
  39. return true;
  40. }
  41. }
  42. }
  43. private Reference reallyPoll() { /* Must hold lock */
  44. if (head != null) {
  45. Reference r = head;
  46. head = (r.next == r) ? null : r.next;
  47. r.queue = NULL;
  48. r.next = r;
  49. return r;
  50. }
  51. return null;
  52. }
  53. /**
  54. * Polls this queue to see if a reference object is available,
  55. * returning one immediately if so. If the queue is empty, this
  56. * method immediately returns <code>null</code>.
  57. *
  58. * @return A reference object, if one was immediately available,
  59. * otherwise <code>null</code>
  60. */
  61. public Reference poll() {
  62. synchronized (lock) {
  63. return reallyPoll();
  64. }
  65. }
  66. /**
  67. * Removes the next reference object in this queue, blocking until either
  68. * one becomes available or the given timeout period expires.
  69. *
  70. * @param timeout If positive, block for up <code>timeout</code>
  71. * milliseconds while waiting for a reference to be
  72. * added to this queue. If zero, block indefinitely.
  73. *
  74. * @return A reference object, if one was available within the specified
  75. * timeout period, otherwise <code>null</code>
  76. *
  77. * @throws IllegalArgumentException
  78. * If the value of the timeout argument is negative
  79. *
  80. * @throws InterruptedException
  81. * If the timeout wait is interrupted
  82. */
  83. public Reference remove(long timeout)
  84. throws IllegalArgumentException, InterruptedException
  85. {
  86. if (timeout < 0) {
  87. throw new IllegalArgumentException("Negative timeout value");
  88. }
  89. synchronized (lock) {
  90. Reference r = reallyPoll();
  91. if (r != null) return r;
  92. for (;;) {
  93. lock.wait(timeout);
  94. r = reallyPoll();
  95. if (r != null) return r;
  96. if (timeout != 0) return null;
  97. }
  98. }
  99. }
  100. /**
  101. * Removes the next reference object in this queue, blocking until one
  102. * becomes available.
  103. *
  104. * @throws InterruptedException If the wait is interrupted
  105. */
  106. public Reference remove() throws InterruptedException {
  107. return remove(0);
  108. }
  109. }