mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-26 12:12:10 +01:00
Refactor GStaticPrivate accessors to facilitate protecting them with locks
* g_static_private_get: have a single entry and exit * g_static_private_set: delay creation of GArray so the whole tail of the function can be under the private_data lock without risking deadlock with the g_thread lock; call the destructor last, after we could have unlocked * g_static_private_free: choose next thread in list before accessing private_data, to keep all accesses together * g_thread_cleanup: steal private_data first, then work exclusively with the stolen array (which doesn't need to be under a lock any more) Bug: https://bugzilla.gnome.org/show_bug.cgi?id=642026 Bug-NB: NB#257512
This commit is contained in:
parent
b05f0b351c
commit
83f1b12388
@ -1653,18 +1653,15 @@ g_static_private_get (GStaticPrivate *private_key)
|
|||||||
{
|
{
|
||||||
GRealThread *self = (GRealThread*) g_thread_self ();
|
GRealThread *self = (GRealThread*) g_thread_self ();
|
||||||
GArray *array;
|
GArray *array;
|
||||||
|
gpointer ret = NULL;
|
||||||
|
|
||||||
array = self->private_data;
|
array = self->private_data;
|
||||||
if (!array)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (!private_key->index)
|
if (array && private_key->index != 0 && private_key->index <= array->len)
|
||||||
return NULL;
|
ret = g_array_index (array, GStaticPrivateNode,
|
||||||
else if (private_key->index <= array->len)
|
|
||||||
return g_array_index (array, GStaticPrivateNode,
|
|
||||||
private_key->index - 1).data;
|
private_key->index - 1).data;
|
||||||
else
|
|
||||||
return NULL;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1696,13 +1693,8 @@ g_static_private_set (GStaticPrivate *private_key,
|
|||||||
GArray *array;
|
GArray *array;
|
||||||
static guint next_index = 0;
|
static guint next_index = 0;
|
||||||
GStaticPrivateNode *node;
|
GStaticPrivateNode *node;
|
||||||
|
gpointer ddata = NULL;
|
||||||
array = self->private_data;
|
GDestroyNotify ddestroy = NULL;
|
||||||
if (!array)
|
|
||||||
{
|
|
||||||
array = g_array_new (FALSE, TRUE, sizeof (GStaticPrivateNode));
|
|
||||||
self->private_data = array;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!private_key->index)
|
if (!private_key->index)
|
||||||
{
|
{
|
||||||
@ -1725,25 +1717,26 @@ g_static_private_set (GStaticPrivate *private_key,
|
|||||||
G_UNLOCK (g_thread);
|
G_UNLOCK (g_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
array = self->private_data;
|
||||||
|
if (!array)
|
||||||
|
{
|
||||||
|
array = g_array_new (FALSE, TRUE, sizeof (GStaticPrivateNode));
|
||||||
|
self->private_data = array;
|
||||||
|
}
|
||||||
|
|
||||||
if (private_key->index > array->len)
|
if (private_key->index > array->len)
|
||||||
g_array_set_size (array, private_key->index);
|
g_array_set_size (array, private_key->index);
|
||||||
|
|
||||||
node = &g_array_index (array, GStaticPrivateNode, private_key->index - 1);
|
node = &g_array_index (array, GStaticPrivateNode, private_key->index - 1);
|
||||||
if (node->destroy)
|
|
||||||
{
|
ddata = node->data;
|
||||||
gpointer ddata = node->data;
|
ddestroy = node->destroy;
|
||||||
GDestroyNotify ddestroy = node->destroy;
|
|
||||||
|
|
||||||
node->data = data;
|
node->data = data;
|
||||||
node->destroy = notify;
|
node->destroy = notify;
|
||||||
|
|
||||||
|
if (ddestroy)
|
||||||
ddestroy (ddata);
|
ddestroy (ddata);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
node->data = data;
|
|
||||||
node->destroy = notify;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1761,7 +1754,7 @@ void
|
|||||||
g_static_private_free (GStaticPrivate *private_key)
|
g_static_private_free (GStaticPrivate *private_key)
|
||||||
{
|
{
|
||||||
guint idx = private_key->index;
|
guint idx = private_key->index;
|
||||||
GRealThread *thread;
|
GRealThread *thread, *next;
|
||||||
GArray *garbage = NULL;
|
GArray *garbage = NULL;
|
||||||
|
|
||||||
if (!idx)
|
if (!idx)
|
||||||
@ -1772,10 +1765,14 @@ g_static_private_free (GStaticPrivate *private_key)
|
|||||||
G_LOCK (g_thread);
|
G_LOCK (g_thread);
|
||||||
|
|
||||||
thread = g_thread_all_threads;
|
thread = g_thread_all_threads;
|
||||||
while (thread)
|
|
||||||
|
for (thread = g_thread_all_threads; thread; thread = next)
|
||||||
{
|
{
|
||||||
GArray *array = thread->private_data;
|
GArray *array;
|
||||||
thread = thread->next;
|
|
||||||
|
next = thread->next;
|
||||||
|
|
||||||
|
array = thread->private_data;
|
||||||
|
|
||||||
if (array && idx <= array->len)
|
if (array && idx <= array->len)
|
||||||
{
|
{
|
||||||
@ -1832,9 +1829,13 @@ g_thread_cleanup (gpointer data)
|
|||||||
if (data)
|
if (data)
|
||||||
{
|
{
|
||||||
GRealThread* thread = data;
|
GRealThread* thread = data;
|
||||||
if (thread->private_data)
|
GArray *array;
|
||||||
|
|
||||||
|
array = thread->private_data;
|
||||||
|
thread->private_data = NULL;
|
||||||
|
|
||||||
|
if (array)
|
||||||
{
|
{
|
||||||
GArray* array = thread->private_data;
|
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
for (i = 0; i < array->len; i++ )
|
for (i = 0; i < array->len; i++ )
|
||||||
|
Loading…
x
Reference in New Issue
Block a user