1 /* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun; 27 28 import java.lang.ref.Reference; 29 import java.lang.ref.SoftReference; 30 import java.lang.ref.WeakReference; 31 32 /** 33 * This abstract ReentrantContextProvider helper class manages the creation, 34 * storage, and retrieval of concrete ReentrantContext instances which can be 35 * subclassed to hold cached contextual data. 36 * 37 * It supports reentrancy as every call to acquire() provides a new unique context 38 * instance that must later be returned for reuse by a call to release(ctx) 39 * (typically in a try/finally block). 40 * 41 * It has a couple of abstract implementations which store references in a queue 42 * and/or thread-local storage. 43 * The Providers can be configured to hold ReentrantContext instances in memory 44 * using hard, soft or weak references. 45 * 46 * The acquire() and release() methods are used to retrieve and return the contexts. 47 * 48 * The {@code newContext()} method remains abstract in all implementations and 49 * must be provided by the module to create a new subclass of ReentrantContext 50 * with the appropriate contextual data in it. 51 * 52 * Sample Usage: 53 * - create a subclass ReentrantContextImpl to hold the thread state: 54 * 55 * static final class ReentrantContextImpl extends ReentrantContext { 56 * // specific cached data 57 * } 58 * 59 * - create the appropriate ReentrantContextProvider: 60 * 61 * private static final ReentrantContextProvider<ReentrantContextImpl> contextProvider = 62 * new ReentrantContextProviderTL<ReentrantContextImpl>(ReentrantContextProvider.REF_WEAK) 63 * { 64 * @Override 65 * protected ReentrantContextImpl newContext() { 66 * return new ReentrantContextImpl(); 67 * } 68 * }; 69 * ... 70 * void someMethod() { 71 * ReentrantContextImpl ctx = contextProvider.acquire(); 72 * try { 73 * // use the context 74 * } finally { 75 * contextProvider.release(ctx); 76 * } 77 * } 78 * 79 * @param <K> ReentrantContext subclass 80 * 81 * @see ReentrantContext 82 */ 83 public abstract class ReentrantContextProvider<K extends ReentrantContext> 84 { 85 // thread-local storage: inactive 86 static final byte USAGE_TL_INACTIVE = 0; 87 // thread-local storage: in use 88 static final byte USAGE_TL_IN_USE = 1; 89 // CLQ storage 90 static final byte USAGE_CLQ = 2; 91 92 // hard reference 93 public static final int REF_HARD = 0; 94 // soft reference 95 public static final int REF_SOFT = 1; 96 // weak reference 97 public static final int REF_WEAK = 2; 98 99 /* members */ 100 // internal reference type 101 private final int refType; 102 103 /** 104 * Create a new ReentrantContext provider using the given reference type 105 * among hard, soft or weak 106 * 107 * @param refType reference type 108 */ 109 protected ReentrantContextProvider(final int refType) { 110 this.refType = refType; 111 } 112 113 /** 114 * Create a new ReentrantContext instance 115 * 116 * @return new ReentrantContext instance 117 */ 118 protected abstract K newContext(); 119 120 /** 121 * Give a ReentrantContext instance for the current thread 122 * 123 * @return ReentrantContext instance 124 */ 125 public abstract K acquire(); 126 127 /** 128 * Restore the given ReentrantContext instance for reuse 129 * 130 * @param ctx ReentrantContext instance 131 */ 132 public abstract void release(K ctx); 133 134 @SuppressWarnings("unchecked") 135 protected final Reference<K> getOrCreateReference(final K ctx) { 136 if (ctx.reference == null) { 137 // Create the reference: 138 switch (refType) { 139 case REF_HARD: 140 ctx.reference = new HardReference<K>(ctx); 141 break; 142 case REF_SOFT: 143 ctx.reference = new SoftReference<K>(ctx); 144 break; 145 default: 146 case REF_WEAK: 147 ctx.reference = new WeakReference<K>(ctx); 148 break; 149 } 150 } 151 return (Reference<K>) ctx.reference; 152 } 153 154 /* Missing HardReference implementation */ 155 static final class HardReference<V> extends WeakReference<V> { 156 // kept strong reference: 157 private final V strongRef; 158 159 HardReference(final V referent) { 160 // no referent needed for the parent WeakReference: 161 super(null); 162 this.strongRef = referent; 163 } 164 165 @Override 166 public V get() { 167 return strongRef; 168 } 169 } 170 }