1*2d1272b8SAndroid Build Coastguard Worker /* 2*2d1272b8SAndroid Build Coastguard Worker * Copyright © 2012 Google, Inc. 3*2d1272b8SAndroid Build Coastguard Worker * 4*2d1272b8SAndroid Build Coastguard Worker * This is part of HarfBuzz, a text shaping library. 5*2d1272b8SAndroid Build Coastguard Worker * 6*2d1272b8SAndroid Build Coastguard Worker * Permission is hereby granted, without written agreement and without 7*2d1272b8SAndroid Build Coastguard Worker * license or royalty fees, to use, copy, modify, and distribute this 8*2d1272b8SAndroid Build Coastguard Worker * software and its documentation for any purpose, provided that the 9*2d1272b8SAndroid Build Coastguard Worker * above copyright notice and the following two paragraphs appear in 10*2d1272b8SAndroid Build Coastguard Worker * all copies of this software. 11*2d1272b8SAndroid Build Coastguard Worker * 12*2d1272b8SAndroid Build Coastguard Worker * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13*2d1272b8SAndroid Build Coastguard Worker * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14*2d1272b8SAndroid Build Coastguard Worker * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15*2d1272b8SAndroid Build Coastguard Worker * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16*2d1272b8SAndroid Build Coastguard Worker * DAMAGE. 17*2d1272b8SAndroid Build Coastguard Worker * 18*2d1272b8SAndroid Build Coastguard Worker * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19*2d1272b8SAndroid Build Coastguard Worker * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20*2d1272b8SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21*2d1272b8SAndroid Build Coastguard Worker * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22*2d1272b8SAndroid Build Coastguard Worker * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23*2d1272b8SAndroid Build Coastguard Worker * 24*2d1272b8SAndroid Build Coastguard Worker * Google Author(s): Behdad Esfahbod 25*2d1272b8SAndroid Build Coastguard Worker */ 26*2d1272b8SAndroid Build Coastguard Worker 27*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_CACHE_HH 28*2d1272b8SAndroid Build Coastguard Worker #define HB_CACHE_HH 29*2d1272b8SAndroid Build Coastguard Worker 30*2d1272b8SAndroid Build Coastguard Worker #include "hb.hh" 31*2d1272b8SAndroid Build Coastguard Worker 32*2d1272b8SAndroid Build Coastguard Worker 33*2d1272b8SAndroid Build Coastguard Worker /* Implements a lockfree cache for int->int functions. 34*2d1272b8SAndroid Build Coastguard Worker * 35*2d1272b8SAndroid Build Coastguard Worker * The cache is a fixed-size array of 16-bit or 32-bit integers. 36*2d1272b8SAndroid Build Coastguard Worker * The key is split into two parts: the cache index and the rest. 37*2d1272b8SAndroid Build Coastguard Worker * 38*2d1272b8SAndroid Build Coastguard Worker * The cache index is used to index into the array. The rest is used 39*2d1272b8SAndroid Build Coastguard Worker * to store the key and the value. 40*2d1272b8SAndroid Build Coastguard Worker * 41*2d1272b8SAndroid Build Coastguard Worker * The value is stored in the least significant bits of the integer. 42*2d1272b8SAndroid Build Coastguard Worker * The key is stored in the most significant bits of the integer. 43*2d1272b8SAndroid Build Coastguard Worker * The key is shifted by cache_bits to the left to make room for the 44*2d1272b8SAndroid Build Coastguard Worker * value. 45*2d1272b8SAndroid Build Coastguard Worker */ 46*2d1272b8SAndroid Build Coastguard Worker 47*2d1272b8SAndroid Build Coastguard Worker template <unsigned int key_bits=16, 48*2d1272b8SAndroid Build Coastguard Worker unsigned int value_bits=8 + 32 - key_bits, 49*2d1272b8SAndroid Build Coastguard Worker unsigned int cache_bits=8, 50*2d1272b8SAndroid Build Coastguard Worker bool thread_safe=true> 51*2d1272b8SAndroid Build Coastguard Worker struct hb_cache_t 52*2d1272b8SAndroid Build Coastguard Worker { 53*2d1272b8SAndroid Build Coastguard Worker using item_t = typename std::conditional<thread_safe, 54*2d1272b8SAndroid Build Coastguard Worker typename std::conditional<key_bits + value_bits - cache_bits <= 16, 55*2d1272b8SAndroid Build Coastguard Worker hb_atomic_short_t, 56*2d1272b8SAndroid Build Coastguard Worker hb_atomic_int_t>::type, 57*2d1272b8SAndroid Build Coastguard Worker typename std::conditional<key_bits + value_bits - cache_bits <= 16, 58*2d1272b8SAndroid Build Coastguard Worker short, 59*2d1272b8SAndroid Build Coastguard Worker int>::type 60*2d1272b8SAndroid Build Coastguard Worker >::type; 61*2d1272b8SAndroid Build Coastguard Worker 62*2d1272b8SAndroid Build Coastguard Worker static_assert ((key_bits >= cache_bits), ""); 63*2d1272b8SAndroid Build Coastguard Worker static_assert ((key_bits + value_bits <= cache_bits + 8 * sizeof (item_t)), ""); 64*2d1272b8SAndroid Build Coastguard Worker hb_cache_thb_cache_t65*2d1272b8SAndroid Build Coastguard Worker hb_cache_t () { clear (); } 66*2d1272b8SAndroid Build Coastguard Worker clearhb_cache_t67*2d1272b8SAndroid Build Coastguard Worker void clear () 68*2d1272b8SAndroid Build Coastguard Worker { 69*2d1272b8SAndroid Build Coastguard Worker for (auto &v : values) 70*2d1272b8SAndroid Build Coastguard Worker v = -1; 71*2d1272b8SAndroid Build Coastguard Worker } 72*2d1272b8SAndroid Build Coastguard Worker gethb_cache_t73*2d1272b8SAndroid Build Coastguard Worker bool get (unsigned int key, unsigned int *value) const 74*2d1272b8SAndroid Build Coastguard Worker { 75*2d1272b8SAndroid Build Coastguard Worker unsigned int k = key & ((1u<<cache_bits)-1); 76*2d1272b8SAndroid Build Coastguard Worker unsigned int v = values[k]; 77*2d1272b8SAndroid Build Coastguard Worker if ((key_bits + value_bits - cache_bits == 8 * sizeof (item_t) && v == (unsigned int) -1) || 78*2d1272b8SAndroid Build Coastguard Worker (v >> value_bits) != (key >> cache_bits)) 79*2d1272b8SAndroid Build Coastguard Worker return false; 80*2d1272b8SAndroid Build Coastguard Worker *value = v & ((1u<<value_bits)-1); 81*2d1272b8SAndroid Build Coastguard Worker return true; 82*2d1272b8SAndroid Build Coastguard Worker } 83*2d1272b8SAndroid Build Coastguard Worker sethb_cache_t84*2d1272b8SAndroid Build Coastguard Worker bool set (unsigned int key, unsigned int value) 85*2d1272b8SAndroid Build Coastguard Worker { 86*2d1272b8SAndroid Build Coastguard Worker if (unlikely ((key >> key_bits) || (value >> value_bits))) 87*2d1272b8SAndroid Build Coastguard Worker return false; /* Overflows */ 88*2d1272b8SAndroid Build Coastguard Worker unsigned int k = key & ((1u<<cache_bits)-1); 89*2d1272b8SAndroid Build Coastguard Worker unsigned int v = ((key>>cache_bits)<<value_bits) | value; 90*2d1272b8SAndroid Build Coastguard Worker values[k] = v; 91*2d1272b8SAndroid Build Coastguard Worker return true; 92*2d1272b8SAndroid Build Coastguard Worker } 93*2d1272b8SAndroid Build Coastguard Worker 94*2d1272b8SAndroid Build Coastguard Worker private: 95*2d1272b8SAndroid Build Coastguard Worker item_t values[1u<<cache_bits]; 96*2d1272b8SAndroid Build Coastguard Worker }; 97*2d1272b8SAndroid Build Coastguard Worker 98*2d1272b8SAndroid Build Coastguard Worker 99*2d1272b8SAndroid Build Coastguard Worker #endif /* HB_CACHE_HH */ 100