提交 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
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 *
......
......@@ -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 *
......
......@@ -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 *
......
......@@ -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,
......
......@@ -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;
}
......
......@@ -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 *
......
......@@ -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 *
......
......@@ -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>
......
......@@ -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))
......
......@@ -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 */
......
......@@ -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 *
......
......@@ -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 *
......
......@@ -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;
......
......@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册