1 package jdk.internal.ref; 2 3 /* 4 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. 5 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 * 7 * This code is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 only, as 9 * published by the Free Software Foundation. Oracle designates this 10 * particular file as subject to the "Classpath" exception as provided 11 * by Oracle in the LICENSE file that accompanied this code. 12 * 13 * This code is distributed in the hope that it will be useful, but WITHOUT 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16 * version 2 for more details (a copy is included in the LICENSE file that 17 * accompanied this code). 18 * 19 * You should have received a copy of the GNU General Public License version 20 * 2 along with this work; if not, write to the Free Software Foundation, 21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 22 * 23 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 24 * or visit www.oracle.com if you need additional information or have any 25 * questions. 26 */ 27 28 import java.lang.ref.Cleaner; 29 import java.lang.ref.Reference; 30 import java.lang.ref.WeakReference; 31 import java.util.Objects; 32 33 /** 34 * WeakCleanable subclasses efficiently encapsulate cleanup state and 35 * the cleaning action. 36 * Subclasses implement the abstract {@link #performCleanup()} method 37 * to provide the cleaning action. 38 * When constructed, the object reference and the {@link Cleaner.Cleanable Cleanable} 39 * are registered with the {@link Cleaner}. 40 * The Cleaner invokes {@link Cleaner.Cleanable#clean() clean} after the 41 * referent becomes weakly reachable. 42 */ 43 public abstract class WeakCleanable<T> extends WeakReference<T> 44 implements Cleaner.Cleanable { 45 46 /** 47 * Links to previous and next in a doubly-linked list. 48 */ 49 WeakCleanable<?> prev = this, next = this; 50 51 /** 52 * The list of WeakCleanable; synchronizes insert and remove. 53 */ 54 private final WeakCleanable<?> list; 55 56 /** 57 * Constructs new {@code WeakCleanableReference} with 58 * {@code non-null referent} and {@code non-null cleaner}. 59 * The {@code cleaner} is not retained by this reference; it is only used 60 * to register the newly constructed {@link Cleaner.Cleanable Cleanable}. 61 * 62 * @param referent the referent to track 63 * @param cleaner the {@code Cleaner} to register new reference with 64 */ 65 public WeakCleanable(T referent, Cleaner cleaner) { 66 super(Objects.requireNonNull(referent), ((CleanerImpl)cleaner).queue()); 67 list = ((CleanerImpl)cleaner).weakCleanableList(); 68 insert(); 69 70 // Ensure referent and cleaner remain accessible 71 Reference.reachabilityFence(referent); 72 Reference.reachabilityFence(cleaner); 73 74 } 75 76 /** 77 * Construct a new root of the list; not inserted. 78 */ 79 WeakCleanable() { 80 super(null, null); 81 this.list = this; 82 } 83 84 /** 85 * Insert this WeakCleanableReference after the list head. 86 */ 87 private void insert() { 88 synchronized (list) { 89 prev = list; 90 next = list.next; 91 next.prev = this; 92 list.next = this; 93 } 94 } 95 96 /** 97 * Remove this WeakCleanableReference from the list. 98 * 99 * @return true if Cleanable was removed or false if not because 100 * it had already been removed before 101 */ 102 private boolean remove() { 103 synchronized (list) { 104 if (next != this) { 105 next.prev = prev; 106 prev.next = next; 107 prev = this; 108 next = this; 109 return true; 110 } 111 return false; 112 } 113 } 114 115 /** 116 * Returns true if the list's next reference refers to itself. 117 * 118 * @return true if the list is empty 119 */ 120 boolean isListEmpty() { 121 synchronized (list) { 122 return list == list.next; 123 } 124 } 125 126 /** 127 * Unregister this WeakCleanable reference and invoke {@link #performCleanup()}, 128 * ensuring at-most-once semantics. 129 */ 130 @Override 131 public final void clean() { 132 if (remove()) { 133 super.clear(); 134 performCleanup(); 135 } 136 } 137 138 /** 139 * Unregister this WeakCleanable and clear the reference. 140 * Due to inherent concurrency, {@link #performCleanup()} may still be invoked. 141 */ 142 @Override 143 public void clear() { 144 if (remove()) { 145 super.clear(); 146 } 147 } 148 149 /** 150 * The {@code performCleanup} abstract method is overridden 151 * to implement the cleaning logic. 152 * The {@code performCleanup} method should not be called except 153 * by the {@link #clean} method which ensures at most once semantics. 154 */ 155 protected abstract void performCleanup(); 156 157 /** 158 * This method always throws {@link UnsupportedOperationException}. 159 * Enqueuing details of {@link Cleaner.Cleanable} 160 * are a private implementation detail. 161 * 162 * @throws UnsupportedOperationException always 163 */ 164 @Override 165 public final boolean isEnqueued() { 166 throw new UnsupportedOperationException("isEnqueued"); 167 } 168 169 /** 170 * This method always throws {@link UnsupportedOperationException}. 171 * Enqueuing details of {@link Cleaner.Cleanable} 172 * are a private implementation detail. 173 * 174 * @throws UnsupportedOperationException always 175 */ 176 @Override 177 public final boolean enqueue() { 178 throw new UnsupportedOperationException("enqueue"); 179 } 180 }