xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-cache.hh (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
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