1. /*
  2. * @(#)ReferenceQueue.java 1.14 00/02/02
  3. *
  4. * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.lang.ref;
  11. /**
  12. * Reference queues, to which registered reference objects are appended by the
  13. * garbage collector after the appropriate reachability changes are detected.
  14. *
  15. * @version 1.14, 02/02/00
  16. * @author Mark Reinhold
  17. * @since 1.2
  18. */
  19. public class ReferenceQueue {
  20. /**
  21. * Constructs a new reference-object queue.
  22. */
  23. public ReferenceQueue() { }
  24. private static class Null extends ReferenceQueue {
  25. boolean enqueue(Reference r) {
  26. return false;
  27. }
  28. }
  29. static ReferenceQueue NULL = new Null();
  30. static ReferenceQueue ENQUEUED = new Null();
  31. static private class Lock { };
  32. private Lock lock = new Lock();
  33. private Reference head = null;
  34. boolean enqueue(Reference r) { /* Called only by Reference class */
  35. synchronized (r) {
  36. if (r.queue == ENQUEUED) return false;
  37. synchronized (lock) {
  38. r.queue = ENQUEUED;
  39. r.next = (head == null) ? r : head;
  40. head = r;
  41. lock.notifyAll();
  42. return true;
  43. }
  44. }
  45. }
  46. private Reference reallyPoll() { /* Must hold lock */
  47. if (head != null) {
  48. Reference r = head;
  49. head = (r.next == r) ? null : r.next;
  50. r.queue = NULL;
  51. r.next = r;
  52. return r;
  53. }
  54. return null;
  55. }
  56. /**
  57. * Polls this queue to see if a reference object is available,
  58. * returning one immediately if so. If the queue is empty, this
  59. * method immediately returns <code>null</code>.
  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. * @param timeout If positive, block for up <code>timeout</code>
  74. * milliseconds while waiting for a reference to be
  75. * added to this queue. If zero, block indefinitely.
  76. *
  77. * @return A reference object, if one was available within the specified
  78. * timeout period, otherwise <code>null</code>
  79. *
  80. * @throws IllegalArgumentException
  81. * If the value of the timeout argument is negative
  82. *
  83. * @throws InterruptedException
  84. * If the timeout wait is interrupted
  85. */
  86. public Reference remove(long timeout)
  87. throws IllegalArgumentException, InterruptedException
  88. {
  89. if (timeout < 0) {
  90. throw new IllegalArgumentException("Negative timeout value");
  91. }
  92. synchronized (lock) {
  93. Reference r = reallyPoll();
  94. if (r != null) return r;
  95. for (;;) {
  96. lock.wait(timeout);
  97. r = reallyPoll();
  98. if (r != null) return r;
  99. if (timeout != 0) return null;
  100. }
  101. }
  102. }
  103. /**
  104. * Removes the next reference object in this queue, blocking until one
  105. * becomes available.
  106. *
  107. * @throws InterruptedException If the wait is interrupted
  108. */
  109. public Reference remove() throws InterruptedException {
  110. return remove(0);
  111. }
  112. }