提交 33ccc779 编写于 作者: B Behdad Esfahbod

[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.
上级 944b2ba1
...@@ -165,9 +165,10 @@ hb_bool_t ...@@ -165,9 +165,10 @@ hb_bool_t
hb_blob_set_user_data (hb_blob_t *blob, hb_blob_set_user_data (hb_blob_t *blob,
hb_user_data_key_t *key, hb_user_data_key_t *key,
void * data, 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 * void *
......
...@@ -66,7 +66,8 @@ hb_bool_t ...@@ -66,7 +66,8 @@ hb_bool_t
hb_blob_set_user_data (hb_blob_t *blob, hb_blob_set_user_data (hb_blob_t *blob,
hb_user_data_key_t *key, hb_user_data_key_t *key,
void * data, void * data,
hb_destroy_func_t destroy); hb_destroy_func_t destroy,
hb_bool_t replace);
void * void *
......
...@@ -532,9 +532,10 @@ hb_bool_t ...@@ -532,9 +532,10 @@ hb_bool_t
hb_buffer_set_user_data (hb_buffer_t *buffer, hb_buffer_set_user_data (hb_buffer_t *buffer,
hb_user_data_key_t *key, hb_user_data_key_t *key,
void * data, 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 * void *
......
...@@ -75,7 +75,8 @@ hb_bool_t ...@@ -75,7 +75,8 @@ hb_bool_t
hb_buffer_set_user_data (hb_buffer_t *buffer, hb_buffer_set_user_data (hb_buffer_t *buffer,
hb_user_data_key_t *key, hb_user_data_key_t *key,
void * data, void * data,
hb_destroy_func_t destroy); hb_destroy_func_t destroy,
hb_bool_t replace);
void * void *
hb_buffer_get_user_data (hb_buffer_t *buffer, hb_buffer_get_user_data (hb_buffer_t *buffer,
......
...@@ -301,17 +301,20 @@ static hb_static_mutex_t user_data_lock; ...@@ -301,17 +301,20 @@ static hb_static_mutex_t user_data_lock;
bool bool
hb_user_data_array_t::set (hb_user_data_key_t *key, hb_user_data_array_t::set (hb_user_data_key_t *key,
void * data, void * data,
hb_destroy_func_t destroy) hb_destroy_func_t destroy,
hb_bool_t replace)
{ {
if (!key) if (!key)
return false; return false;
if (!data && !destroy) { if (replace) {
items.remove (key, user_data_lock); if (!data && !destroy) {
return true; items.remove (key, user_data_lock);
return true;
}
} }
hb_user_data_item_t item = {key, data, destroy}; 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; return ret;
} }
......
...@@ -248,9 +248,10 @@ hb_bool_t ...@@ -248,9 +248,10 @@ hb_bool_t
hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs, hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
hb_user_data_key_t *key, hb_user_data_key_t *key,
void * data, 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 * void *
...@@ -667,9 +668,10 @@ hb_bool_t ...@@ -667,9 +668,10 @@ hb_bool_t
hb_face_set_user_data (hb_face_t *face, hb_face_set_user_data (hb_face_t *face,
hb_user_data_key_t *key, hb_user_data_key_t *key,
void * data, 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 * void *
...@@ -852,9 +854,10 @@ hb_bool_t ...@@ -852,9 +854,10 @@ hb_bool_t
hb_font_set_user_data (hb_font_t *font, hb_font_set_user_data (hb_font_t *font,
hb_user_data_key_t *key, hb_user_data_key_t *key,
void * data, 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 * void *
......
...@@ -65,7 +65,8 @@ hb_bool_t ...@@ -65,7 +65,8 @@ hb_bool_t
hb_face_set_user_data (hb_face_t *face, hb_face_set_user_data (hb_face_t *face,
hb_user_data_key_t *key, hb_user_data_key_t *key,
void * data, void * data,
hb_destroy_func_t destroy); hb_destroy_func_t destroy,
hb_bool_t replace);
void * void *
...@@ -123,7 +124,8 @@ hb_bool_t ...@@ -123,7 +124,8 @@ hb_bool_t
hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs, hb_font_funcs_set_user_data (hb_font_funcs_t *ffuncs,
hb_user_data_key_t *key, hb_user_data_key_t *key,
void * data, void * data,
hb_destroy_func_t destroy); hb_destroy_func_t destroy,
hb_bool_t replace);
void * void *
...@@ -338,7 +340,8 @@ hb_bool_t ...@@ -338,7 +340,8 @@ hb_bool_t
hb_font_set_user_data (hb_font_t *font, hb_font_set_user_data (hb_font_t *font,
hb_user_data_key_t *key, hb_user_data_key_t *key,
void * data, void * data,
hb_destroy_func_t destroy); hb_destroy_func_t destroy,
hb_bool_t replace);
void * void *
......
...@@ -122,7 +122,8 @@ struct hb_user_data_array_t { ...@@ -122,7 +122,8 @@ struct hb_user_data_array_t {
HB_INTERNAL bool set (hb_user_data_key_t *key, HB_INTERNAL bool set (hb_user_data_key_t *key,
void * data, 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); HB_INTERNAL void *get (hb_user_data_key_t *key);
...@@ -178,11 +179,12 @@ struct _hb_object_header_t { ...@@ -178,11 +179,12 @@ struct _hb_object_header_t {
inline bool set_user_data (hb_user_data_key_t *key, inline bool set_user_data (hb_user_data_key_t *key,
void * data, void * data,
hb_destroy_func_t destroy_func) { hb_destroy_func_t destroy_func,
hb_bool_t replace) {
if (unlikely (!this || this->is_inert ())) if (unlikely (!this || this->is_inert ()))
return false; 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) { inline void *get_user_data (hb_user_data_key_t *key) {
...@@ -237,9 +239,10 @@ template <typename Type> ...@@ -237,9 +239,10 @@ template <typename Type>
static inline bool hb_object_set_user_data (Type *obj, static inline bool hb_object_set_user_data (Type *obj,
hb_user_data_key_t *key, hb_user_data_key_t *key,
void * data, 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> template <typename Type>
......
...@@ -343,15 +343,21 @@ struct hb_lockable_set_t ...@@ -343,15 +343,21 @@ struct hb_lockable_set_t
hb_array_t <item_t> items; hb_array_t <item_t> items;
template <typename T> 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 (); l.lock ();
item_t *item = items.find (v); item_t *item = items.find (v);
if (item) { if (item) {
item_t old = *item; if (replace) {
*item = v; item_t old = *item;
l.unlock (); *item = v;
old.finish (); l.unlock ();
old.finish ();
}
else {
item = NULL;
l.unlock ();
}
} else { } else {
item = items.push (); item = items.push ();
if (likely (item)) if (likely (item))
......
...@@ -76,7 +76,7 @@ static struct static_shaper_list_t ...@@ -76,7 +76,7 @@ static struct static_shaper_list_t
end = p + strlen (p); end = p + strlen (p);
for (unsigned int j = i; j < ARRAY_LENGTH (shapers); j++) 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)) 0 == strncmp (shapers[j].name, p, end - p))
{ {
/* Reorder this shaper to position i */ /* Reorder this shaper to position i */
......
...@@ -175,9 +175,10 @@ hb_bool_t ...@@ -175,9 +175,10 @@ hb_bool_t
hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs, hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
hb_user_data_key_t *key, hb_user_data_key_t *key,
void * data, 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 * void *
......
...@@ -66,7 +66,8 @@ hb_bool_t ...@@ -66,7 +66,8 @@ hb_bool_t
hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs, hb_unicode_funcs_set_user_data (hb_unicode_funcs_t *ufuncs,
hb_user_data_key_t *key, hb_user_data_key_t *key,
void * data, void * data,
hb_destroy_func_t destroy); hb_destroy_func_t destroy,
hb_bool_t replace);
void * void *
......
...@@ -129,10 +129,15 @@ _hb_uniscribe_face_get_data (hb_face_t *face) ...@@ -129,10 +129,15 @@ _hb_uniscribe_face_get_data (hb_face_t *face)
DEBUG_MSG (UNISCRIBE, face, "Face AddFontMemResourceEx() failed"); DEBUG_MSG (UNISCRIBE, face, "Face AddFontMemResourceEx() failed");
if (unlikely (!hb_face_set_user_data (face, &uniscribe_face_data_key, data, 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); _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; return data;
...@@ -183,10 +188,15 @@ _hb_uniscribe_font_get_data (hb_font_t *font) ...@@ -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, 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); _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; return data;
......
...@@ -116,7 +116,7 @@ create_unicode_funcs_inert (void) ...@@ -116,7 +116,7 @@ create_unicode_funcs_inert (void)
typedef void *(*create_func_t) (void); typedef void *(*create_func_t) (void);
typedef void *(*reference_func_t) (void *obj); typedef void *(*reference_func_t) (void *obj);
typedef void (*destroy_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 * (*get_user_data_func_t) (void *obj, hb_user_data_key_t *key);
typedef void (*make_immutable_func_t) (void *obj); typedef void (*make_immutable_func_t) (void *obj);
typedef hb_bool_t (*is_immutable_func_t) (void *obj); typedef hb_bool_t (*is_immutable_func_t) (void *obj);
...@@ -247,7 +247,7 @@ test_object (void) ...@@ -247,7 +247,7 @@ test_object (void)
if (o->is_immutable) if (o->is_immutable)
g_assert (!o->is_immutable (obj)); 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]); g_assert (o->get_user_data (obj, &key[0]) == &data[0]);
if (o->is_immutable) { if (o->is_immutable) {
...@@ -256,38 +256,39 @@ test_object (void) ...@@ -256,38 +256,39 @@ test_object (void)
} }
/* Should still work even if object is made immutable */ /* 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->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->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 (data[0].freed);
g_assert (o->get_user_data (obj, &key[0]) == &data[1]); g_assert (o->get_user_data (obj, &key[0]) == &data[1]);
g_assert (!data[1].freed); g_assert (!data[1].freed);
data[0].freed = FALSE; 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 (!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); g_assert (data[0].freed);
data[0].freed = FALSE; data[0].freed = FALSE;
global_data = 0; 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_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_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); g_assert_cmpuint (global_data, ==, 1);
global_data = 0; global_data = 0;
for (j = 2; j < 1000; j++) 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++) for (j = 2; j < 1000; j++)
g_assert (o->get_user_data (obj, &key[j]) == &data[j]); g_assert (o->get_user_data (obj, &key[j]) == &data[j]);
for (j = 100; j < 1000; 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++) for (j = 2; j < 100; j++)
g_assert (o->get_user_data (obj, &key[j]) == &data[j]); g_assert (o->get_user_data (obj, &key[j]) == &data[j]);
for (j = 100; j < 1000; j++) for (j = 100; j < 1000; j++)
...@@ -298,8 +299,8 @@ test_object (void) ...@@ -298,8 +299,8 @@ test_object (void)
* Make sure it doesn't deadlock or corrupt memory. */ * Make sure it doesn't deadlock or corrupt memory. */
deadlock_test.klass = o; deadlock_test.klass = o;
deadlock_test.object = obj; 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, &deadlock_test, free_deadlock_test, TRUE));
g_assert (o->set_user_data (obj, &deadlock_test.key, NULL, NULL)); g_assert (o->set_user_data (obj, &deadlock_test.key, NULL, NULL, TRUE));
g_assert (!data[1].freed); g_assert (!data[1].freed);
o->destroy (obj); o->destroy (obj);
...@@ -321,7 +322,7 @@ test_object (void) ...@@ -321,7 +322,7 @@ test_object (void)
if (o->is_immutable) if (o->is_immutable)
g_assert (o->is_immutable (obj)); 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])); g_assert (!o->get_user_data (obj, &key[0]));
o->destroy (obj); o->destroy (obj);
...@@ -349,7 +350,7 @@ test_object (void) ...@@ -349,7 +350,7 @@ test_object (void)
if (o->is_immutable) if (o->is_immutable)
g_assert (o->is_immutable (obj)); 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])); g_assert (!o->get_user_data (obj, &key[0]));
o->destroy (obj); o->destroy (obj);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册