[API] Make set_user_data() functions take a replace parameter
authorBehdad Esfahbod <behdad@behdad.org>
Mon, 8 Aug 2011 22:43:24 +0000 (00:43 +0200)
committerBehdad Esfahbod <behdad@behdad.org>
Mon, 8 Aug 2011 22:43:24 +0000 (00:43 +0200)
We need this to set data on objects safely without worrying that some
other thread unsets it by setting it at the same time.

14 files changed:
src/hb-blob.cc
src/hb-blob.h
src/hb-buffer.cc
src/hb-buffer.h
src/hb-common.cc
src/hb-font.cc
src/hb-font.h
src/hb-object-private.hh
src/hb-private.hh
src/hb-shape.cc
src/hb-unicode.cc
src/hb-unicode.h
src/hb-uniscribe-shape.cc
test/test-object.c

index 7ed3812..58d7324 100644 (file)
@@ -165,9 +165,10 @@ hb_bool_t
 hb_blob_set_user_data (hb_blob_t          *blob,
                       hb_user_data_key_t *key,
                       void *              data,
-                      hb_destroy_func_t   destroy)
+                      hb_destroy_func_t   destroy,
+                      hb_bool_t           replace)
 {
-  return hb_object_set_user_data (blob, key, data, destroy);
+  return hb_object_set_user_data (blob, key, data, destroy, replace);
 }
 
 void *
index f2eaae9..50c9ae3 100644 (file)
@@ -66,7 +66,8 @@ hb_bool_t
 hb_blob_set_user_data (hb_blob_t          *blob,
                       hb_user_data_key_t *key,
                       void *              data,
-                      hb_destroy_func_t   destroy);
+                      hb_destroy_func_t   destroy,
+                      hb_bool_t           replace);
 
 
 void *
index e0c86f5..3be3f44 100644 (file)
@@ -532,9 +532,10 @@ hb_bool_t
 hb_buffer_set_user_data (hb_buffer_t        *buffer,
                         hb_user_data_key_t *key,
                         void *              data,
-                        hb_destroy_func_t   destroy)
+                        hb_destroy_func_t   destroy,
+                        hb_bool_t           replace)
 {
-  return hb_object_set_user_data (buffer, key, data, destroy);
+  return hb_object_set_user_data (buffer, key, data, destroy, replace);
 }
 
 void *
index a43a8d1..a5efce3 100644 (file)
@@ -75,7 +75,8 @@ hb_bool_t
 hb_buffer_set_user_data (hb_buffer_t        *buffer,
                         hb_user_data_key_t *key,
                         void *              data,
-                        hb_destroy_func_t   destroy);
+                        hb_destroy_func_t   destroy,
+                        hb_bool_t           replace);
 
 void *
 hb_buffer_get_user_data (hb_buffer_t        *buffer,
index afbe941..48382ca 100644 (file)
@@ -301,17 +301,20 @@ static hb_static_mutex_t user_data_lock;
 bool
 hb_user_data_array_t::set (hb_user_data_key_t *key,
                           void *              data,
-                          hb_destroy_func_t   destroy)
+                          hb_destroy_func_t   destroy,
+                          hb_bool_t           replace)
 {
   if (!key)
     return false;
 
-  if (!data && !destroy) {
-    items.remove (key, user_data_lock);
-    return true;
+  if (replace) {
+    if (!data && !destroy) {
+      items.remove (key, user_data_lock);
+      return true;
+    }
   }
   hb_user_data_item_t item = {key, data, destroy};
-  bool ret = !!items.replace_or_insert (item, user_data_lock);
+  bool ret = !!items.replace_or_insert (item, user_data_lock, replace);
 
   return ret;
 }
index 4be2a2e..d3fbcbe 100644 (file)
@@ -248,9 +248,10 @@ hb_bool_t
 hb_font_funcs_set_user_data (hb_font_funcs_t    *ffuncs,
                             hb_user_data_key_t *key,
                             void *              data,
-                            hb_destroy_func_t   destroy)
+                            hb_destroy_func_t   destroy,
+                            hb_bool_t           replace)
 {
-  return hb_object_set_user_data (ffuncs, key, data, destroy);
+  return hb_object_set_user_data (ffuncs, key, data, destroy, replace);
 }
 
 void *
@@ -667,9 +668,10 @@ hb_bool_t
 hb_face_set_user_data (hb_face_t          *face,
                       hb_user_data_key_t *key,
                       void *              data,
-                      hb_destroy_func_t   destroy)
+                      hb_destroy_func_t   destroy,
+                      hb_bool_t           replace)
 {
-  return hb_object_set_user_data (face, key, data, destroy);
+  return hb_object_set_user_data (face, key, data, destroy, replace);
 }
 
 void *
@@ -852,9 +854,10 @@ hb_bool_t
 hb_font_set_user_data (hb_font_t          *font,
                       hb_user_data_key_t *key,
                       void *              data,
-                      hb_destroy_func_t   destroy)
+                      hb_destroy_func_t   destroy,
+                      hb_bool_t           replace)
 {
-  return hb_object_set_user_data (font, key, data, destroy);
+  return hb_object_set_user_data (font, key, data, destroy, replace);
 }
 
 void *
index 7f8cd5e..363ab55 100644 (file)
@@ -65,7 +65,8 @@ hb_bool_t
 hb_face_set_user_data (hb_face_t          *face,
                       hb_user_data_key_t *key,
                       void *              data,
-                      hb_destroy_func_t   destroy);
+                      hb_destroy_func_t   destroy,
+                      hb_bool_t           replace);
 
 
 void *
@@ -123,7 +124,8 @@ hb_bool_t
 hb_font_funcs_set_user_data (hb_font_funcs_t    *ffuncs,
                             hb_user_data_key_t *key,
                             void *              data,
-                            hb_destroy_func_t   destroy);
+                            hb_destroy_func_t   destroy,
+                            hb_bool_t           replace);
 
 
 void *
@@ -338,7 +340,8 @@ hb_bool_t
 hb_font_set_user_data (hb_font_t          *font,
                       hb_user_data_key_t *key,
                       void *              data,
-                      hb_destroy_func_t   destroy);
+                      hb_destroy_func_t   destroy,
+                      hb_bool_t           replace);
 
 
 void *
index c0a7bbe..adaa6e8 100644 (file)
@@ -122,7 +122,8 @@ struct hb_user_data_array_t {
 
   HB_INTERNAL bool set (hb_user_data_key_t *key,
                        void *              data,
-                       hb_destroy_func_t   destroy);
+                       hb_destroy_func_t   destroy,
+                       hb_bool_t           replace);
 
   HB_INTERNAL void *get (hb_user_data_key_t *key);
 
@@ -178,11 +179,12 @@ struct _hb_object_header_t {
 
   inline bool set_user_data (hb_user_data_key_t *key,
                             void *              data,
-                            hb_destroy_func_t   destroy_func) {
+                            hb_destroy_func_t   destroy_func,
+                            hb_bool_t           replace) {
     if (unlikely (!this || this->is_inert ()))
       return false;
 
-    return user_data.set (key, data, destroy_func);
+    return user_data.set (key, data, destroy_func, replace);
   }
 
   inline void *get_user_data (hb_user_data_key_t *key) {
@@ -237,9 +239,10 @@ template <typename Type>
 static inline bool hb_object_set_user_data (Type               *obj,
                                            hb_user_data_key_t *key,
                                            void *              data,
-                                           hb_destroy_func_t   destroy)
+                                           hb_destroy_func_t   destroy,
+                                           hb_bool_t           replace)
 {
-  return obj->header.set_user_data (key, data, destroy);
+  return obj->header.set_user_data (key, data, destroy, replace);
 }
 
 template <typename Type>
index b2ef802..413becd 100644 (file)
@@ -343,15 +343,21 @@ struct hb_lockable_set_t
   hb_array_t <item_t> items;
 
   template <typename T>
-  inline item_t *replace_or_insert (T v, lock_t &l)
+  inline item_t *replace_or_insert (T v, lock_t &l, bool replace)
   {
     l.lock ();
     item_t *item = items.find (v);
     if (item) {
-      item_t old = *item;
-      *item = v;
-      l.unlock ();
-      old.finish ();
+      if (replace) {
+       item_t old = *item;
+       *item = v;
+       l.unlock ();
+       old.finish ();
+      }
+      else {
+        item = NULL;
+       l.unlock ();
+      }
     } else {
       item = items.push ();
       if (likely (item))
index 4202302..9a4ebfe 100644 (file)
@@ -76,7 +76,7 @@ static struct static_shaper_list_t
           end = p + strlen (p);
 
        for (unsigned int j = i; j < ARRAY_LENGTH (shapers); j++)
-         if (end - p == strlen (shapers[j].name) &&
+         if (end - p == (int) strlen (shapers[j].name) &&
              0 == strncmp (shapers[j].name, p, end - p))
          {
            /* Reorder this shaper to position i */
index 2286f7b..4b285c5 100644 (file)
@@ -175,9 +175,10 @@ hb_bool_t
 hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
                                hb_user_data_key_t *key,
                                void *              data,
-                               hb_destroy_func_t   destroy)
+                               hb_destroy_func_t   destroy,
+                               hb_bool_t           replace)
 {
-  return hb_object_set_user_data (ufuncs, key, data, destroy);
+  return hb_object_set_user_data (ufuncs, key, data, destroy, replace);
 }
 
 void *
index 9aa97a6..13886df 100644 (file)
@@ -66,7 +66,8 @@ hb_bool_t
 hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
                                hb_user_data_key_t *key,
                                void *              data,
-                               hb_destroy_func_t   destroy);
+                               hb_destroy_func_t   destroy,
+                               hb_bool_t           replace);
 
 
 void *
index fa29cde..b3653e7 100644 (file)
@@ -129,10 +129,15 @@ _hb_uniscribe_face_get_data (hb_face_t *face)
     DEBUG_MSG (UNISCRIBE, face, "Face AddFontMemResourceEx() failed");
 
   if (unlikely (!hb_face_set_user_data (face, &uniscribe_face_data_key, data,
-                                       (hb_destroy_func_t) _hb_uniscribe_face_data_destroy)))
+                                       (hb_destroy_func_t) _hb_uniscribe_face_data_destroy,
+                                       FALSE)))
   {
     _hb_uniscribe_face_data_destroy (data);
-    return &_hb_uniscribe_face_data_nil;
+    data = (hb_uniscribe_face_data_t *) hb_face_get_user_data (face, &uniscribe_face_data_key);
+    if (data)
+      return data;
+    else
+      return &_hb_uniscribe_face_data_nil;
   }
 
   return data;
@@ -183,10 +188,15 @@ _hb_uniscribe_font_get_data (hb_font_t *font)
   }
 
   if (unlikely (!hb_font_set_user_data (font, &uniscribe_font_data_key, data,
-                                       (hb_destroy_func_t) _hb_uniscribe_font_data_destroy)))
+                                       (hb_destroy_func_t) _hb_uniscribe_font_data_destroy,
+                                       FALSE)))
   {
     _hb_uniscribe_font_data_destroy (data);
-    return &_hb_uniscribe_font_data_nil;
+    data = (hb_uniscribe_font_data_t *) hb_font_get_user_data (font, &uniscribe_font_data_key);
+    if (data)
+      return data;
+    else
+      return &_hb_uniscribe_font_data_nil;
   }
 
   return data;
index d0145c5..07cf158 100644 (file)
@@ -116,7 +116,7 @@ create_unicode_funcs_inert (void)
 typedef void     *(*create_func_t)         (void);
 typedef void     *(*reference_func_t)      (void *obj);
 typedef void      (*destroy_func_t)        (void *obj);
-typedef hb_bool_t (*set_user_data_func_t)  (void *obj, hb_user_data_key_t *key, void *data, hb_destroy_func_t destroy);
+typedef hb_bool_t (*set_user_data_func_t)  (void *obj, hb_user_data_key_t *key, void *data, hb_destroy_func_t destroy, hb_bool_t replace);
 typedef void *    (*get_user_data_func_t)  (void *obj, hb_user_data_key_t *key);
 typedef void      (*make_immutable_func_t) (void *obj);
 typedef hb_bool_t (*is_immutable_func_t)   (void *obj);
@@ -247,7 +247,7 @@ test_object (void)
       if (o->is_immutable)
        g_assert (!o->is_immutable (obj));
 
-      g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0));
+      g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
       g_assert (o->get_user_data (obj, &key[0]) == &data[0]);
 
       if (o->is_immutable) {
@@ -256,38 +256,39 @@ test_object (void)
       }
 
       /* Should still work even if object is made immutable */
-      g_assert (o->set_user_data (obj, &key[1], &data[1], free_up1));
+      g_assert (o->set_user_data (obj, &key[1], &data[1], free_up1, TRUE));
       g_assert (o->get_user_data (obj, &key[1]) == &data[1]);
 
-      g_assert (!o->set_user_data (obj, NULL, &data[0], free_up0));
+      g_assert (!o->set_user_data (obj, NULL, &data[0], free_up0, TRUE));
       g_assert (o->get_user_data (obj, &key[0]) == &data[0]);
-      g_assert (o->set_user_data (obj, &key[0], &data[1], NULL));
+      g_assert (o->set_user_data (obj, &key[0], &data[1], NULL, TRUE));
       g_assert (data[0].freed);
       g_assert (o->get_user_data (obj, &key[0]) == &data[1]);
       g_assert (!data[1].freed);
 
       data[0].freed = FALSE;
-      g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0));
+      g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
       g_assert (!data[0].freed);
-      g_assert (o->set_user_data (obj, &key[0], NULL, NULL));
+      g_assert (o->set_user_data (obj, &key[0], NULL, NULL, TRUE));
       g_assert (data[0].freed);
 
       data[0].freed = FALSE;
       global_data = 0;
-      g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0));
+      g_assert (o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
+      g_assert (!o->set_user_data (obj, &key[0], &data[0], free_up0, FALSE));
       g_assert_cmpuint (global_data, ==, 0);
-      g_assert (o->set_user_data (obj, &key[0], NULL, global_free_up));
+      g_assert (o->set_user_data (obj, &key[0], NULL, global_free_up, TRUE));
       g_assert_cmpuint (global_data, ==, 0);
-      g_assert (o->set_user_data (obj, &key[0], NULL, NULL));
+      g_assert (o->set_user_data (obj, &key[0], NULL, NULL, TRUE));
       g_assert_cmpuint (global_data, ==, 1);
 
       global_data = 0;
       for (j = 2; j < 1000; j++)
-       g_assert (o->set_user_data (obj, &key[j], &data[j], global_free_up));
+       g_assert (o->set_user_data (obj, &key[j], &data[j], global_free_up, TRUE));
       for (j = 2; j < 1000; j++)
        g_assert (o->get_user_data (obj, &key[j]) == &data[j]);
       for (j = 100; j < 1000; j++)
-       g_assert (o->set_user_data (obj, &key[j], NULL, NULL));
+       g_assert (o->set_user_data (obj, &key[j], NULL, NULL, TRUE));
       for (j = 2; j < 100; j++)
        g_assert (o->get_user_data (obj, &key[j]) == &data[j]);
       for (j = 100; j < 1000; j++)
@@ -298,8 +299,8 @@ test_object (void)
        * Make sure it doesn't deadlock or corrupt memory. */
       deadlock_test.klass = o;
       deadlock_test.object = obj;
-      g_assert (o->set_user_data (obj, &deadlock_test.key, &deadlock_test, free_deadlock_test));
-      g_assert (o->set_user_data (obj, &deadlock_test.key, NULL, NULL));
+      g_assert (o->set_user_data (obj, &deadlock_test.key, &deadlock_test, free_deadlock_test, TRUE));
+      g_assert (o->set_user_data (obj, &deadlock_test.key, NULL, NULL, TRUE));
 
       g_assert (!data[1].freed);
       o->destroy (obj);
@@ -321,7 +322,7 @@ test_object (void)
       if (o->is_immutable)
        g_assert (o->is_immutable (obj));
 
-      g_assert (!o->set_user_data (obj, &key[0], &data[0], free_up0));
+      g_assert (!o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
       g_assert (!o->get_user_data (obj, &key[0]));
 
       o->destroy (obj);
@@ -349,7 +350,7 @@ test_object (void)
       if (o->is_immutable)
        g_assert (o->is_immutable (obj));
 
-      g_assert (!o->set_user_data (obj, &key[0], &data[0], free_up0));
+      g_assert (!o->set_user_data (obj, &key[0], &data[0], free_up0, TRUE));
       g_assert (!o->get_user_data (obj, &key[0]));
 
       o->destroy (obj);