Home | History | Annotate | Download | only in locale
      1 /* GENERATED SOURCE. DO NOT MODIFY. */
      2 //  2016 and later: Unicode, Inc. and others.
      3 // License & terms of use: http://www.unicode.org/copyright.html#License
      4 /*
      5  *******************************************************************************
      6  * Copyright (C) 2009-2010, International Business Machines Corporation and    *
      7  * others. All Rights Reserved.                                                *
      8  *******************************************************************************
      9  */
     10 package android.icu.impl.locale;
     11 
     12 import java.lang.ref.ReferenceQueue;
     13 import java.lang.ref.SoftReference;
     14 import java.util.concurrent.ConcurrentHashMap;
     15 
     16 /**
     17  * @hide Only a subset of ICU is exposed in Android
     18  */
     19 public abstract class LocaleObjectCache<K, V> {
     20     private ConcurrentHashMap<K, CacheEntry<K, V>> _map;
     21     private ReferenceQueue<V> _queue = new ReferenceQueue<V>();
     22 
     23     public LocaleObjectCache() {
     24         this(16, 0.75f, 16);
     25     }
     26 
     27     public LocaleObjectCache(int initialCapacity, float loadFactor, int concurrencyLevel) {
     28         _map = new ConcurrentHashMap<K, CacheEntry<K, V>>(initialCapacity, loadFactor, concurrencyLevel);
     29     }
     30 
     31     public V get(K key) {
     32         V value = null;
     33 
     34         cleanStaleEntries();
     35         CacheEntry<K, V> entry = _map.get(key);
     36         if (entry != null) {
     37             value = entry.get();
     38         }
     39         if (value == null) {
     40             key = normalizeKey(key);
     41             V newVal = createObject(key);
     42             if (key == null || newVal == null) {
     43                 // subclass must return non-null key/value object
     44                 return null;
     45             }
     46 
     47             CacheEntry<K, V> newEntry = new CacheEntry<K, V>(key, newVal, _queue);
     48 
     49             while (value == null) {
     50                 cleanStaleEntries();
     51                 entry = _map.putIfAbsent(key, newEntry);
     52                 if (entry == null) {
     53                     value = newVal;
     54                     break;
     55                 } else {
     56                     value = entry.get();
     57                 }
     58             }
     59         }
     60         return value;
     61     }
     62 
     63     @SuppressWarnings("unchecked")
     64     private void cleanStaleEntries() {
     65         CacheEntry<K, V> entry;
     66         while ((entry = (CacheEntry<K, V>)_queue.poll()) != null) {
     67             _map.remove(entry.getKey());
     68         }
     69     }
     70 
     71     protected abstract V createObject(K key);
     72 
     73     protected K normalizeKey(K key) {
     74         return key;
     75     }
     76 
     77     private static class CacheEntry<K, V> extends SoftReference<V> {
     78         private K _key;
     79 
     80         CacheEntry(K key, V value, ReferenceQueue<V> queue) {
     81             super(value, queue);
     82             _key = key;
     83         }
     84 
     85         K getKey() {
     86             return _key;
     87         }
     88     }
     89 }
     90