From 33ccc77902660ed4b49184e5ec99f4fd0ef63175 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 9 Aug 2011 00:43:24 +0200 Subject: [PATCH] [API] Make set_user_data() functions take a replace parameter We need this to set data on objects safely without worrying that some other thread unsets it by setting it at the same time. --- src/hb-blob.cc | 5 +++-- src/hb-blob.h | 3 ++- src/hb-buffer.cc | 5 +++-- src/hb-buffer.h | 3 ++- src/hb-common.cc | 13 ++++++++----- src/hb-font.cc | 15 +++++++++------ src/hb-font.h | 9 ++++++--- src/hb-object-private.hh | 13 ++++++++----- src/hb-private.hh | 16 +++++++++++----- src/hb-shape.cc | 2 +- src/hb-unicode.cc | 5 +++-- src/hb-unicode.h | 3 ++- src/hb-uniscribe-shape.cc | 18 ++++++++++++++---- test/test-object.c | 33 +++++++++++++++++---------------- 14 files changed, 89 insertions(+), 54 deletions(-) diff --git a/src/hb-blob.cc b/src/hb-blob.cc index 7ed3812..58d7324 100644 --- a/src/hb-blob.cc +++ b/src/hb-blob.cc @@ -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 * diff --git a/src/hb-blob.h b/src/hb-blob.h index f2eaae9..50c9ae3 100644 --- a/src/hb-blob.h +++ b/src/hb-blob.h @@ -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 * diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index e0c86f5..3be3f44 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -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 * diff --git a/src/hb-buffer.h b/src/hb-buffer.h index a43a8d1..a5efce3 100644 --- a/src/hb-buffer.h +++ b/src/hb-buffer.h @@ -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, diff --git a/src/hb-common.cc b/src/hb-common.cc index afbe941..48382ca 100644 --- a/src/hb-common.cc +++ b/src/hb-common.cc @@ -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; } diff --git a/src/hb-font.cc b/src/hb-font.cc index 4be2a2e..d3fbcbe 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -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 * diff --git a/src/hb-font.h b/src/hb-font.h index 7f8cd5e..363ab55 100644 --- a/src/hb-font.h +++ b/src/hb-font.h @@ -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 * diff --git a/src/hb-object-private.hh b/src/hb-object-private.hh index c0a7bbe..adaa6e8 100644 --- a/src/hb-object-private.hh +++ b/src/hb-object-private.hh @@ -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 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 diff --git a/src/hb-private.hh b/src/hb-private.hh index b2ef802..413becd 100644 --- a/src/hb-private.hh +++ b/src/hb-private.hh @@ -343,15 +343,21 @@ struct hb_lockable_set_t hb_array_t items; template - 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)) diff --git a/src/hb-shape.cc b/src/hb-shape.cc index 4202302..9a4ebfe 100644 --- a/src/hb-shape.cc +++ b/src/hb-shape.cc @@ -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 */ diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc index 2286f7b..4b285c5 100644 --- a/src/hb-unicode.cc +++ b/src/hb-unicode.cc @@ -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 * diff --git a/src/hb-unicode.h b/src/hb-unicode.h index 9aa97a6..13886df 100644 --- a/src/hb-unicode.h +++ b/src/hb-unicode.h @@ -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 * diff --git a/src/hb-uniscribe-shape.cc b/src/hb-uniscribe-shape.cc index fa29cde..b3653e7 100644 --- a/src/hb-uniscribe-shape.cc +++ b/src/hb-uniscribe-shape.cc @@ -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; diff --git a/test/test-object.c b/test/test-object.c index d0145c5..07cf158 100644 --- a/test/test-object.c +++ b/test/test-object.c @@ -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); -- 2.7.4