Home | History | Annotate | Download | only in cs
      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 
     46         Cache(int size) {
     47             this.size = size;
     48         }
     49 
     50         abstract Object create(Object name);
     51 
     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 
     59         abstract boolean hasName(Object ob, Object name);
     60 
     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 
    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 
    130     public static CharsetEncoder encoderFor(Object name) {
    131         CharsetEncoder ce = (CharsetEncoder)encoderCache.forName(name);
    132         ce.reset();
    133         return ce;
    134     }
    135 
    136 }
    137