void finish (void) { free (lang); }
};
-static hb_threadsafe_set_t<hb_language_item_t> langs;
+static hb_static_mutex_t langs_lock;
+static hb_lockable_set_t<hb_language_item_t, hb_static_mutex_t> langs;
hb_language_t
hb_language_from_string (const char *str)
{
if (!str || !*str)
- return NULL;
+ return HB_LANGUAGE_INVALID;
- hb_language_item_t *item = langs.find_or_insert (str);
+ hb_language_item_t *item = langs.find_or_insert (str, langs_lock);
- return likely (item) ? item->lang : NULL;
+ return likely (item) ? item->lang : HB_LANGUAGE_INVALID;
}
const char *
hb_language_to_string (hb_language_t language)
{
+ /* This is actually NULL-safe! */
return language->s;
}
* should switch to using that insted for these too.
*/
-/* XXX this can result in deadlocks because we call user callbacks */
-static hb_static_mutex_t user_data_mutex;
+static hb_static_mutex_t user_data_lock;
bool
hb_user_data_array_t::set (hb_user_data_key_t *key,
if (!key)
return false;
- hb_mutex_lock (&user_data_mutex);
-
if (!data && !destroy) {
- items.remove (key);
+ items.remove (key, user_data_lock);
return true;
}
hb_user_data_item_t item = {key, data, destroy};
- bool ret = !!items.insert (item);
-
- hb_mutex_unlock (&user_data_mutex);
+ bool ret = !!items.replace_or_insert (item, user_data_lock);
return ret;
}
void *
hb_user_data_array_t::get (hb_user_data_key_t *key)
{
- hb_mutex_lock (&user_data_mutex);
+ hb_user_data_item_t item = {NULL };
- hb_user_data_item_t *item = items.find (key);
- void *ret = item ? item->data : NULL;
-
- hb_mutex_unlock (&user_data_mutex);
+ return items.find (key, &item, user_data_lock) ? item.data : NULL;
+}
- return ret;
+void
+hb_user_data_array_t::finish (void)
+{
+ items.finish (user_data_lock);
}