[glib/icu/ucdn] Make the funcs object allocated on demand
authorBehdad Esfahbod <behdad@behdad.org>
Fri, 27 Oct 2017 21:26:45 +0000 (15:26 -0600)
committerBehdad Esfahbod <behdad@behdad.org>
Fri, 27 Oct 2017 21:26:45 +0000 (15:26 -0600)
src/hb-glib.cc
src/hb-icu.cc
src/hb-ucdn.cc

index 5b0a1eb325373cbfdd459b04f1e99977529a67a2..c8863ea7bafa7169a0c8c5c727ab92b41bce486e 100644 (file)
@@ -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_unicode_funcs_t *> (&_hb_glib_unicode_funcs);
+  return funcs;
 }
 
 #if GLIB_CHECK_VERSION(2,31,10)
index 01d15f48e8b1ef769b9a23feb6f459f75b3246b1..2550e438d265e6bfd1c1be66d56145ef10f4897e 100644 (file)
@@ -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);
+
+  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
 
-    nullptr, /* parent */
-    true, /* immutable */
-    {
-#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_icu_unicode_##name,
+    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;
     }
-  };
 
-#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));
-  }
+#ifdef HB_USE_ATEXIT
+    atexit (free_static_icu_funcs); /* First person registers atexit() callback. */
 #endif
-  return const_cast<hb_unicode_funcs_t *> (&_hb_icu_unicode_funcs);
+  };
+
+  return funcs;
 }
index c237ee8254510df6a33dae4dff83bd353a0eaaf2..e51f03532b5705b1ed3fe0f28c5ac70919d51c7d 100644 (file)
@@ -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);
+
+  if (unlikely (!funcs))
+  {
+    funcs = hb_unicode_funcs_create (nullptr);
 
-    nullptr, /* parent */
-    true, /* immutable */
-    {
-#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_ucdn_##name,
+#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_unicode_funcs_t *> (&_hb_ucdn_unicode_funcs);
+  return funcs;
 }
-