Imported Upstream version 8.2.2
[platform/upstream/harfbuzz.git] / src / hb-cache.hh
index e617b75..6d8a54c 100644 (file)
 #include "hb.hh"
 
 
-/* Implements a lockfree cache for int->int functions. */
+/* Implements a lockfree cache for int->int functions.
+ *
+ * The cache is a fixed-size array of 16-bit or 32-bit integers.
+ * The key is split into two parts: the cache index and the rest.
+ *
+ * The cache index is used to index into the array.  The rest is used
+ * to store the key and the value.
+ *
+ * The value is stored in the least significant bits of the integer.
+ * The key is stored in the most significant bits of the integer.
+ * The key is shifted by cache_bits to the left to make room for the
+ * value.
+ */
 
-template <unsigned int key_bits, unsigned int value_bits, unsigned int cache_bits>
+template <unsigned int key_bits=16,
+        unsigned int value_bits=8 + 32 - key_bits,
+        unsigned int cache_bits=8,
+        bool thread_safe=true>
 struct hb_cache_t
 {
+  using item_t = typename std::conditional<thread_safe,
+                                          typename std::conditional<key_bits + value_bits - cache_bits <= 16,
+                                                                    hb_atomic_short_t,
+                                                                    hb_atomic_int_t>::type,
+                                          typename std::conditional<key_bits + value_bits - cache_bits <= 16,
+                                                                    short,
+                                                                    int>::type
+                                         >::type;
+
   static_assert ((key_bits >= cache_bits), "");
-  static_assert ((key_bits + value_bits - cache_bits <= 8 * sizeof (hb_atomic_int_t)), "");
-  static_assert (sizeof (hb_atomic_int_t) == sizeof (unsigned int), "");
+  static_assert ((key_bits + value_bits <= cache_bits + 8 * sizeof (item_t)), "");
 
-  void init () { clear (); }
-  void fini () {}
+  hb_cache_t () { clear (); }
 
   void clear ()
   {
-    for (unsigned i = 0; i < ARRAY_LENGTH (values); i++)
-      values[i].set_relaxed (-1);
+    for (auto &v : values)
+      v = -1;
   }
 
   bool get (unsigned int key, unsigned int *value) const
   {
     unsigned int k = key & ((1u<<cache_bits)-1);
-    unsigned int v = values[k].get_relaxed ();
-    if ((key_bits + value_bits - cache_bits == 8 * sizeof (hb_atomic_int_t) && v == (unsigned int) -1) ||
+    unsigned int v = values[k];
+    if ((key_bits + value_bits - cache_bits == 8 * sizeof (item_t) && v == (unsigned int) -1) ||
        (v >> value_bits) != (key >> cache_bits))
       return false;
     *value = v & ((1u<<value_bits)-1);
@@ -65,16 +87,13 @@ struct hb_cache_t
       return false; /* Overflows */
     unsigned int k = key & ((1u<<cache_bits)-1);
     unsigned int v = ((key>>cache_bits)<<value_bits) | value;
-    values[k].set_relaxed (v);
+    values[k] = v;
     return true;
   }
 
   private:
-  hb_atomic_int_t values[1u<<cache_bits];
+  item_t values[1u<<cache_bits];
 };
 
-typedef hb_cache_t<21, 16, 8> hb_cmap_cache_t;
-typedef hb_cache_t<16, 24, 8> hb_advance_cache_t;
-
 
 #endif /* HB_CACHE_HH */