1 /* 2 * Copyright (c) 2011, 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 27 package sun.nio.cs; 28 29 import java.nio.charset.*; 30 31 32 /** 33 * Utility class for caching per-thread decoders and encoders. 34 */ 35 36 public class ThreadLocalCoders { 37 38 private static final int CACHE_SIZE = 3; 39 40 private static abstract class Cache { 41 42 // Thread-local reference to array of cached objects, in LRU order 43 private ThreadLocal<Object[]> cache = new ThreadLocal<>(); 44 private final int size; 45 Cache(int size)46 Cache(int size) { 47 this.size = size; 48 } 49 create(Object name)50 abstract Object create(Object name); 51 moveToFront(Object[] oa, int i)52 private void moveToFront(Object[] oa, int i) { 53 Object ob = oa[i]; 54 for (int j = i; j > 0; j--) 55 oa[j] = oa[j - 1]; 56 oa[0] = ob; 57 } 58 hasName(Object ob, Object name)59 abstract boolean hasName(Object ob, Object name); 60 forName(Object name)61 Object forName(Object name) { 62 Object[] oa = cache.get(); 63 if (oa == null) { 64 oa = new Object[size]; 65 cache.set(oa); 66 } else { 67 for (int i = 0; i < oa.length; i++) { 68 Object ob = oa[i]; 69 if (ob == null) 70 continue; 71 if (hasName(ob, name)) { 72 if (i > 0) 73 moveToFront(oa, i); 74 return ob; 75 } 76 } 77 } 78 79 // Create a new object 80 Object ob = create(name); 81 oa[oa.length - 1] = ob; 82 moveToFront(oa, oa.length - 1); 83 return ob; 84 } 85 86 } 87 88 private static Cache decoderCache = new Cache(CACHE_SIZE) { 89 boolean hasName(Object ob, Object name) { 90 if (name instanceof String) 91 return (((CharsetDecoder)ob).charset().name().equals(name)); 92 if (name instanceof Charset) 93 return ((CharsetDecoder)ob).charset().equals(name); 94 return false; 95 } 96 Object create(Object name) { 97 if (name instanceof String) 98 return Charset.forName((String)name).newDecoder(); 99 if (name instanceof Charset) 100 return ((Charset)name).newDecoder(); 101 assert false; 102 return null; 103 } 104 }; 105 decoderFor(Object name)106 public static CharsetDecoder decoderFor(Object name) { 107 CharsetDecoder cd = (CharsetDecoder)decoderCache.forName(name); 108 cd.reset(); 109 return cd; 110 } 111 112 private static Cache encoderCache = new Cache(CACHE_SIZE) { 113 boolean hasName(Object ob, Object name) { 114 if (name instanceof String) 115 return (((CharsetEncoder)ob).charset().name().equals(name)); 116 if (name instanceof Charset) 117 return ((CharsetEncoder)ob).charset().equals(name); 118 return false; 119 } 120 Object create(Object name) { 121 if (name instanceof String) 122 return Charset.forName((String)name).newEncoder(); 123 if (name instanceof Charset) 124 return ((Charset)name).newEncoder(); 125 assert false; 126 return null; 127 } 128 }; 129 encoderFor(Object name)130 public static CharsetEncoder encoderFor(Object name) { 131 CharsetEncoder ce = (CharsetEncoder)encoderCache.forName(name); 132 ce.reset(); 133 return ce; 134 } 135 136 } 137