1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.lang.ref; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The {@code ReferenceQueue} is the container on which reference objects are 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * enqueued when the garbage collector detects the reachability type specified 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for the referent. 24f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 25f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * @since 1.2 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class ReferenceQueue<T> { 28250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson private static final int NANOS_PER_MILLI = 1000000; 29f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private Reference<? extends T> head; 31eb3e5888d4b3c17b5b6e977440178e88ba174f93Elena Sayapina private Reference<? extends T> tail; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new instance of this class. 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public ReferenceQueue() { 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the next available reference from the queue, removing it in the 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * process. Does not wait for a reference to become available. 42f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the next available reference, or {@code null} if no reference is 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * immediately available 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @SuppressWarnings("unchecked") 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public synchronized Reference<? extends T> poll() { 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (head == null) { 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 52eb3e5888d4b3c17b5b6e977440178e88ba174f93Elena Sayapina Reference<? extends T> ret = head; 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 54eb3e5888d4b3c17b5b6e977440178e88ba174f93Elena Sayapina if (head == tail) { 55eb3e5888d4b3c17b5b6e977440178e88ba174f93Elena Sayapina tail = null; 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project head = null; 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project head = head.queueNext; 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project ret.queueNext = null; 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return ret; 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the next available reference from the queue, removing it in the 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * process. Waits indefinitely for a reference to become available. 68f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 69250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson * @throws InterruptedException if the blocking call was interrupted 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public Reference<? extends T> remove() throws InterruptedException { 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return remove(0L); 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 74f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Returns the next available reference from the queue, removing it in the 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * process. Waits for a reference to become available or the given timeout 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * period to elapse, whichever happens first. 79f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 80250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson * @param timeoutMillis maximum time to spend waiting for a reference object 81250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson * to become available. A value of {@code 0} results in the method 82250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson * waiting indefinitely. 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return the next available reference, or {@code null} if no reference 84250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson * becomes available within the timeout period 85250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson * @throws IllegalArgumentException if {@code timeoutMillis < 0}. 86250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson * @throws InterruptedException if the blocking call was interrupted 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 88250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson public synchronized Reference<? extends T> remove(long timeoutMillis) 89250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson throws InterruptedException { 90250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson if (timeoutMillis < 0) { 91250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson throw new IllegalArgumentException("timeout < 0: " + timeoutMillis); 92250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson } 93250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson 94250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson if (head != null) { 95250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson return poll(); 96250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson } 97250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson 98250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson // avoid overflow: if total > 292 years, just wait forever 99250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson if (timeoutMillis == 0 || (timeoutMillis > Long.MAX_VALUE / NANOS_PER_MILLI)) { 100250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson do { 101250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson wait(0); 102250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson } while (head == null); 103250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson return poll(); 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 106250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson // guaranteed to not overflow 107250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson long nanosToWait = timeoutMillis * NANOS_PER_MILLI; 108250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson int timeoutNanos = 0; 109250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson 110250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson // wait until notified or the timeout has elapsed 111250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson long startTime = System.nanoTime(); 112250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson while (true) { 113250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson wait(timeoutMillis, timeoutNanos); 114250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson if (head != null) { 115250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson break; 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 117250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson long nanosElapsed = System.nanoTime() - startTime; 118250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson long nanosRemaining = nanosToWait - nanosElapsed; 119250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson if (nanosRemaining <= 0) { 120250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson break; 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 122250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson timeoutMillis = nanosRemaining / NANOS_PER_MILLI; 123250e0d89cc3f5d2fc03ed23961c774c02f825ffdJesse Wilson timeoutNanos = (int) (nanosRemaining - timeoutMillis * NANOS_PER_MILLI); 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return poll(); 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 129f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * Enqueue the reference object on the receiver. 130f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 131f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * @param reference 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * reference object to be enqueued. 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 134f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson synchronized void enqueue(Reference<? extends T> reference) { 135eb3e5888d4b3c17b5b6e977440178e88ba174f93Elena Sayapina if (tail == null) { 136eb3e5888d4b3c17b5b6e977440178e88ba174f93Elena Sayapina head = reference; 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 138eb3e5888d4b3c17b5b6e977440178e88ba174f93Elena Sayapina tail.queueNext = reference; 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 140eb3e5888d4b3c17b5b6e977440178e88ba174f93Elena Sayapina 141eb3e5888d4b3c17b5b6e977440178e88ba174f93Elena Sayapina // The newly enqueued reference becomes the new tail, and always 142eb3e5888d4b3c17b5b6e977440178e88ba174f93Elena Sayapina // points to itself. 143eb3e5888d4b3c17b5b6e977440178e88ba174f93Elena Sayapina tail = reference; 144eb3e5888d4b3c17b5b6e977440178e88ba174f93Elena Sayapina tail.queueNext = reference; 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project notify(); 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 14755d86d85b3cd11461ba793cdc8ed74c87311a447Carl Shapiro 14864c6c367497c7fcf88e7527022234043e4460758Jesse Wilson /** @hide */ 1492680db46e43b69cc1c49429d371cd1c7512d6f2cElliott Hughes public static Reference<?> unenqueued = null; 15055d86d85b3cd11461ba793cdc8ed74c87311a447Carl Shapiro 15155d86d85b3cd11461ba793cdc8ed74c87311a447Carl Shapiro static void add(Reference<?> list) { 15255d86d85b3cd11461ba793cdc8ed74c87311a447Carl Shapiro synchronized (ReferenceQueue.class) { 15355d86d85b3cd11461ba793cdc8ed74c87311a447Carl Shapiro if (unenqueued == null) { 15455d86d85b3cd11461ba793cdc8ed74c87311a447Carl Shapiro unenqueued = list; 15555d86d85b3cd11461ba793cdc8ed74c87311a447Carl Shapiro } else { 156365ea82a5c83d18f1630b7cf232f8499d9613dc0Mathieu Chartier // Find the last element in unenqueued. 157365ea82a5c83d18f1630b7cf232f8499d9613dc0Mathieu Chartier Reference<?> last = unenqueued; 158365ea82a5c83d18f1630b7cf232f8499d9613dc0Mathieu Chartier while (last.pendingNext != unenqueued) { 159365ea82a5c83d18f1630b7cf232f8499d9613dc0Mathieu Chartier last = last.pendingNext; 160365ea82a5c83d18f1630b7cf232f8499d9613dc0Mathieu Chartier } 161365ea82a5c83d18f1630b7cf232f8499d9613dc0Mathieu Chartier // Add our list to the end. Update the pendingNext to point back to enqueued. 162365ea82a5c83d18f1630b7cf232f8499d9613dc0Mathieu Chartier last.pendingNext = list; 163365ea82a5c83d18f1630b7cf232f8499d9613dc0Mathieu Chartier last = list; 164365ea82a5c83d18f1630b7cf232f8499d9613dc0Mathieu Chartier while (last.pendingNext != list) { 165365ea82a5c83d18f1630b7cf232f8499d9613dc0Mathieu Chartier last = last.pendingNext; 166365ea82a5c83d18f1630b7cf232f8499d9613dc0Mathieu Chartier } 167365ea82a5c83d18f1630b7cf232f8499d9613dc0Mathieu Chartier last.pendingNext = unenqueued; 16855d86d85b3cd11461ba793cdc8ed74c87311a447Carl Shapiro } 16955d86d85b3cd11461ba793cdc8ed74c87311a447Carl Shapiro ReferenceQueue.class.notifyAll(); 17055d86d85b3cd11461ba793cdc8ed74c87311a447Carl Shapiro } 17155d86d85b3cd11461ba793cdc8ed74c87311a447Carl Shapiro } 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 173