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

View File

@ -47,10 +47,10 @@ typedef hb_bool_t (*hb_shape_func_t) (hb_font_t *font,
unsigned int num_features);
#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];
hb_shape_func_t func;
} shapers[] = {
} all_shapers[] = {
/* v--- Add new shapers in the right place here */
#ifdef HAVE_GRAPHITE
HB_SHAPER_IMPLEMENT (graphite2),
@ -65,55 +65,120 @@ static struct hb_shaper_pair_t {
};
#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");
if (env && *env)
{
/* Reorder shaper list to prefer requested shaper list. */
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;
}
if (!env || !*env) {
hb_atomic_ptr_cmpexch (&static_shapers, NULL, (const hb_shaper_pair_t *) all_shapers);
return (const hb_shaper_pair_t *) all_shapers;
}
ASSERT_STATIC ((ARRAY_LENGTH (shapers) + 1) * sizeof (*shaper_list) <= sizeof (shaper_list));
unsigned int i;
for (i = 0; i < ARRAY_LENGTH (shapers); i++)
shaper_list[i] = shapers[i].name;
shaper_list[i] = NULL;
/* Not found; allocate one. */
shapers = (hb_shaper_pair_t *) malloc (sizeof (all_shapers));
if (unlikely (!shapers))
return (const hb_shaper_pair_t *) all_shapers;
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];
} static_shaper_list;
return shapers;
}
static const char **static_shaper_list;
static
void free_static_shaper_list (void)
{
free (static_shaper_list);
}
const char **
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_shape_full (hb_font_t *font,
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 */
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)))
return TRUE;
} else {
while (*shaper_list) {
for (unsigned int i = 0; i < ARRAY_LENGTH (shapers); i++)
if (0 == strcmp (*shaper_list, shapers[i].name)) {
if (likely (shapers[i].func (font, buffer, features, num_features)))
for (unsigned int i = 0; i < ARRAY_LENGTH (all_shapers); i++)
if (0 == strcmp (*shaper_list, all_shapers[i].name)) {
if (likely (all_shapers[i].func (font, buffer, features, num_features)))
return TRUE;
break;
}