Remove last static initializer

We're free!  Lazy or immediate...
This commit is contained in:
Behdad Esfahbod 2012-06-05 19:23:29 -04:00
parent 4a8a529068
commit f64b2ebf82
2 changed files with 110 additions and 42 deletions

View File

@ -398,6 +398,8 @@ hb_ft_font_create (FT_Face ft_face,
} }
/* Thread-safe, lock-free, FT_Library */
static FT_Library ft_library; static FT_Library ft_library;
static static

View File

@ -47,10 +47,10 @@ typedef hb_bool_t (*hb_shape_func_t) (hb_font_t *font,
unsigned int num_features); unsigned int num_features);
#define HB_SHAPER_IMPLEMENT(name) {#name, _hb_##name##_shape} #define HB_SHAPER_IMPLEMENT(name) {#name, _hb_##name##_shape}
static struct hb_shaper_pair_t { static const struct hb_shaper_pair_t {
char name[16]; char name[16];
hb_shape_func_t func; hb_shape_func_t func;
} shapers[] = { } all_shapers[] = {
/* v--- Add new shapers in the right place here */ /* v--- Add new shapers in the right place here */
#ifdef HAVE_GRAPHITE #ifdef HAVE_GRAPHITE
HB_SHAPER_IMPLEMENT (graphite2), HB_SHAPER_IMPLEMENT (graphite2),
@ -65,55 +65,120 @@ static struct hb_shaper_pair_t {
}; };
#undef HB_SHAPER_IMPLEMENT #undef HB_SHAPER_IMPLEMENT
static struct static_shaper_list_t
/* Thread-safe, lock-free, shapers */
static hb_shaper_pair_t *static_shapers;
static
void free_static_shapers (void)
{ {
static_shaper_list_t (void) if (unlikely (static_shapers != all_shapers))
free (static_shapers);
}
static const hb_shaper_pair_t *
get_shapers (void)
{
retry:
hb_shaper_pair_t *shapers = (hb_shaper_pair_t *) hb_atomic_ptr_get (&static_shapers);
if (unlikely (!shapers))
{ {
char *env = getenv ("HB_SHAPER_LIST"); char *env = getenv ("HB_SHAPER_LIST");
if (env && *env) if (!env || !*env) {
{ hb_atomic_ptr_cmpexch (&static_shapers, NULL, (const hb_shaper_pair_t *) all_shapers);
/* Reorder shaper list to prefer requested shaper list. */ return (const hb_shaper_pair_t *) all_shapers;
unsigned int i = 0;
char *end, *p = env;
for (;;) {
end = strchr (p, ',');
if (!end)
end = p + strlen (p);
for (unsigned int j = i; j < ARRAY_LENGTH (shapers); j++)
if (end - p == (int) strlen (shapers[j].name) &&
0 == strncmp (shapers[j].name, p, end - p))
{
/* Reorder this shaper to position i */
struct hb_shaper_pair_t t = shapers[j];
memmove (&shapers[i + 1], &shapers[i], sizeof (shapers[i]) * (j - i));
shapers[i] = t;
i++;
}
if (!*end)
break;
else
p = end + 1;
}
} }
ASSERT_STATIC ((ARRAY_LENGTH (shapers) + 1) * sizeof (*shaper_list) <= sizeof (shaper_list)); /* Not found; allocate one. */
unsigned int i; shapers = (hb_shaper_pair_t *) malloc (sizeof (all_shapers));
for (i = 0; i < ARRAY_LENGTH (shapers); i++) if (unlikely (!shapers))
shaper_list[i] = shapers[i].name; return (const hb_shaper_pair_t *) all_shapers;
shaper_list[i] = NULL; memcpy (shapers, all_shapers, sizeof (all_shapers));
/* Reorder shaper list to prefer requested shapers. */
unsigned int i = 0;
char *end, *p = env;
for (;;) {
end = strchr (p, ',');
if (!end)
end = p + strlen (p);
for (unsigned int j = i; j < ARRAY_LENGTH (all_shapers); j++)
if (end - p == (int) strlen (shapers[j].name) &&
0 == strncmp (shapers[j].name, p, end - p))
{
/* Reorder this shaper to position i */
struct hb_shaper_pair_t t = shapers[j];
memmove (&shapers[i + 1], &shapers[i], sizeof (shapers[i]) * (j - i));
shapers[i] = t;
i++;
}
if (!*end)
break;
else
p = end + 1;
}
if (!hb_atomic_ptr_cmpexch (&static_shapers, NULL, shapers)) {
free (shapers);
goto retry;
}
#ifdef HAVE_ATEXIT
atexit (free_static_shapers); /* First person registers atexit() callback. */
#endif
} }
const char *shaper_list[ARRAY_LENGTH (shapers) + 1]; return shapers;
} static_shaper_list; }
static const char **static_shaper_list;
static
void free_static_shaper_list (void)
{
free (static_shaper_list);
}
const char ** const char **
hb_shape_list_shapers (void) hb_shape_list_shapers (void)
{ {
return static_shaper_list.shaper_list; retry:
const char **shaper_list = (const char **) hb_atomic_ptr_get (&static_shaper_list);
if (unlikely (!shaper_list))
{
/* Not found; allocate one. */
shaper_list = (const char **) calloc (1 + ARRAY_LENGTH (all_shapers), sizeof (const char *));
if (unlikely (!shaper_list)) {
static const char *nil_shaper_list[] = {NULL};
return nil_shaper_list;
}
const hb_shaper_pair_t *shapers = get_shapers ();
unsigned int i;
for (i = 0; i < ARRAY_LENGTH (all_shapers); i++)
shaper_list[i] = shapers[i].name;
shaper_list[i] = NULL;
if (!hb_atomic_ptr_cmpexch (&static_shaper_list, NULL, shaper_list)) {
free (shaper_list);
goto retry;
}
#ifdef HAVE_ATEXIT
atexit (free_static_shaper_list); /* First person registers atexit() callback. */
#endif
}
return shaper_list;
} }
hb_bool_t hb_bool_t
hb_shape_full (hb_font_t *font, hb_shape_full (hb_font_t *font,
hb_buffer_t *buffer, hb_buffer_t *buffer,
@ -124,14 +189,15 @@ hb_shape_full (hb_font_t *font,
hb_font_make_immutable (font); /* So we can safely cache stuff on it */ hb_font_make_immutable (font); /* So we can safely cache stuff on it */
if (likely (!shaper_list)) { if (likely (!shaper_list)) {
for (unsigned int i = 0; i < ARRAY_LENGTH (shapers); i++) const hb_shaper_pair_t *shapers = get_shapers ();
for (unsigned int i = 0; i < ARRAY_LENGTH (all_shapers); i++)
if (likely (shapers[i].func (font, buffer, features, num_features))) if (likely (shapers[i].func (font, buffer, features, num_features)))
return TRUE; return TRUE;
} else { } else {
while (*shaper_list) { while (*shaper_list) {
for (unsigned int i = 0; i < ARRAY_LENGTH (shapers); i++) for (unsigned int i = 0; i < ARRAY_LENGTH (all_shapers); i++)
if (0 == strcmp (*shaper_list, shapers[i].name)) { if (0 == strcmp (*shaper_list, all_shapers[i].name)) {
if (likely (shapers[i].func (font, buffer, features, num_features))) if (likely (all_shapers[i].func (font, buffer, features, num_features)))
return TRUE; return TRUE;
break; break;
} }