diff --git a/src/hb-glib.cc b/src/hb-glib.cc index 5b0a1eb32..c8863ea7b 100644 --- a/src/hb-glib.cc +++ b/src/hb-glib.cc @@ -364,22 +364,44 @@ hb_glib_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs HB_UNUSED, return utf8_decomposed_len; } +static hb_unicode_funcs_t *static_glib_funcs = nullptr; + +#ifdef HB_USE_ATEXIT +static +void free_static_glib_funcs (void) +{ + hb_unicode_funcs_destroy (static_glib_funcs); +} +#endif + hb_unicode_funcs_t * hb_glib_get_unicode_funcs (void) { - static const hb_unicode_funcs_t _hb_glib_unicode_funcs = { - HB_OBJECT_HEADER_STATIC, +retry: + hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_glib_funcs); - nullptr, /* parent */ - true, /* immutable */ - { -#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_glib_unicode_##name, + if (unlikely (!funcs)) + { + funcs = hb_unicode_funcs_create (nullptr); + +#define HB_UNICODE_FUNC_IMPLEMENT(name) \ + hb_unicode_funcs_set_##name##_func (funcs, hb_glib_unicode_##name, nullptr, nullptr); HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS #undef HB_UNICODE_FUNC_IMPLEMENT + + hb_unicode_funcs_make_immutable (funcs); + + if (!hb_atomic_ptr_cmpexch (&static_glib_funcs, nullptr, funcs)) { + hb_unicode_funcs_destroy (funcs); + goto retry; } + +#ifdef HB_USE_ATEXIT + atexit (free_static_glib_funcs); /* First person registers atexit() callback. */ +#endif }; - return const_cast (&_hb_glib_unicode_funcs); + return funcs; } #if GLIB_CHECK_VERSION(2,31,10) diff --git a/src/hb-icu.cc b/src/hb-icu.cc index 01d15f48e..2550e438d 100644 --- a/src/hb-icu.cc +++ b/src/hb-icu.cc @@ -345,27 +345,50 @@ hb_icu_unicode_decompose_compatibility (hb_unicode_funcs_t *ufuncs HB_UNUSED, } +static hb_unicode_funcs_t *static_icu_funcs = nullptr; + +#ifdef HB_USE_ATEXIT +static +void free_static_icu_funcs (void) +{ + hb_unicode_funcs_destroy (static_icu_funcs); +} +#endif + hb_unicode_funcs_t * hb_icu_get_unicode_funcs (void) { - static const hb_unicode_funcs_t _hb_icu_unicode_funcs = { - HB_OBJECT_HEADER_STATIC, +retry: + hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_icu_funcs); - nullptr, /* parent */ - true, /* immutable */ - { -#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_icu_unicode_##name, + if (unlikely (!funcs)) + { +#if U_ICU_VERSION_MAJOR_NUM >= 49 + if (!hb_atomic_ptr_get (&normalizer)) { + UErrorCode icu_err = U_ZERO_ERROR; + /* We ignore failure in getNFCInstace(). */ + (void) hb_atomic_ptr_cmpexch (&normalizer, nullptr, unorm2_getNFCInstance (&icu_err)); + } +#endif + + funcs = hb_unicode_funcs_create (nullptr); + +#define HB_UNICODE_FUNC_IMPLEMENT(name) \ + hb_unicode_funcs_set_##name##_func (funcs, hb_icu_unicode_##name, nullptr, nullptr); HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS #undef HB_UNICODE_FUNC_IMPLEMENT + + hb_unicode_funcs_make_immutable (funcs); + + if (!hb_atomic_ptr_cmpexch (&static_icu_funcs, nullptr, funcs)) { + hb_unicode_funcs_destroy (funcs); + goto retry; } + +#ifdef HB_USE_ATEXIT + atexit (free_static_icu_funcs); /* First person registers atexit() callback. */ +#endif }; -#if U_ICU_VERSION_MAJOR_NUM >= 49 - if (!hb_atomic_ptr_get (&normalizer)) { - UErrorCode icu_err = U_ZERO_ERROR; - /* We ignore failure in getNFCInstace(). */ - (void) hb_atomic_ptr_cmpexch (&normalizer, nullptr, unorm2_getNFCInstance (&icu_err)); - } -#endif - return const_cast (&_hb_icu_unicode_funcs); + return funcs; } diff --git a/src/hb-ucdn.cc b/src/hb-ucdn.cc index c237ee825..e51f03532 100644 --- a/src/hb-ucdn.cc +++ b/src/hb-ucdn.cc @@ -231,22 +231,43 @@ hb_ucdn_decompose_compatibility(hb_unicode_funcs_t *ufuncs HB_UNUSED, return ucdn_compat_decompose(u, decomposed); } +static hb_unicode_funcs_t *static_ucdn_funcs = nullptr; + +#ifdef HB_USE_ATEXIT +static +void free_static_ucdn_funcs (void) +{ + hb_unicode_funcs_destroy (static_ucdn_funcs); +} +#endif + extern "C" HB_INTERNAL hb_unicode_funcs_t * hb_ucdn_get_unicode_funcs (void) { - static const hb_unicode_funcs_t _hb_ucdn_unicode_funcs = { - HB_OBJECT_HEADER_STATIC, +retry: + hb_unicode_funcs_t *funcs = (hb_unicode_funcs_t *) hb_atomic_ptr_get (&static_ucdn_funcs); - nullptr, /* parent */ - true, /* immutable */ - { -#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_ucdn_##name, + if (unlikely (!funcs)) + { + funcs = hb_unicode_funcs_create (nullptr); + +#define HB_UNICODE_FUNC_IMPLEMENT(name) \ + hb_unicode_funcs_set_##name##_func (funcs, hb_ucdn_##name, nullptr, nullptr); HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS #undef HB_UNICODE_FUNC_IMPLEMENT + + hb_unicode_funcs_make_immutable (funcs); + + if (!hb_atomic_ptr_cmpexch (&static_ucdn_funcs, nullptr, funcs)) { + hb_unicode_funcs_destroy (funcs); + goto retry; } + +#ifdef HB_USE_ATEXIT + atexit (free_static_ucdn_funcs); /* First person registers atexit() callback. */ +#endif }; - return const_cast (&_hb_ucdn_unicode_funcs); + return funcs; } -