mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-24 21:16:15 +01:00
gthreadedsocketservice: Move obj reference to per-job data
Rather than keeping a reference to the GThreadedSocketService as the user_data for every thread pool job, add it to a member of the per-job data struct (GThreadedSocketServiceData). This should make no difference overall, as it’s just moving the refcounting around, but it does seem to fix an occasional double-unref crash on shutdown where the GThreadedSocketService is unreffed during finalisation. In any case, it makes the object ownership clearer. Signed-off-by: Philip Withnall <withnall@endlessm.com>
This commit is contained in:
parent
63823ae628
commit
035c5d03f1
@ -71,32 +71,33 @@ G_LOCK_DEFINE_STATIC(job_count);
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
GSocketConnection *connection;
|
GThreadedSocketService *service; /* (owned) */
|
||||||
GObject *source_object;
|
GSocketConnection *connection; /* (owned) */
|
||||||
|
GObject *source_object; /* (owned) (nullable) */
|
||||||
} GThreadedSocketServiceData;
|
} GThreadedSocketServiceData;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
g_threaded_socket_service_data_free (GThreadedSocketServiceData *data)
|
g_threaded_socket_service_data_free (GThreadedSocketServiceData *data)
|
||||||
{
|
{
|
||||||
|
g_clear_object (&data->service);
|
||||||
g_clear_object (&data->connection);
|
g_clear_object (&data->connection);
|
||||||
g_clear_object (&data->source_object);
|
g_clear_object (&data->source_object);
|
||||||
g_slice_free (GThreadedSocketServiceData, data);
|
g_slice_free (GThreadedSocketServiceData, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
g_threaded_socket_service_func (gpointer _data,
|
g_threaded_socket_service_func (gpointer job_data,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GThreadedSocketService *threaded = user_data;
|
GThreadedSocketServiceData *data = job_data;
|
||||||
GThreadedSocketServiceData *data = _data;
|
|
||||||
gboolean result;
|
gboolean result;
|
||||||
|
|
||||||
g_signal_emit (threaded, g_threaded_socket_service_run_signal,
|
g_signal_emit (data->service, g_threaded_socket_service_run_signal,
|
||||||
0, data->connection, data->source_object, &result);
|
0, data->connection, data->source_object, &result);
|
||||||
|
|
||||||
G_LOCK (job_count);
|
G_LOCK (job_count);
|
||||||
if (threaded->priv->job_count-- == threaded->priv->max_threads)
|
if (data->service->priv->job_count-- == data->service->priv->max_threads)
|
||||||
g_socket_service_start (G_SOCKET_SERVICE (threaded));
|
g_socket_service_start (G_SOCKET_SERVICE (data->service));
|
||||||
G_UNLOCK (job_count);
|
G_UNLOCK (job_count);
|
||||||
|
|
||||||
g_threaded_socket_service_data_free (data);
|
g_threaded_socket_service_data_free (data);
|
||||||
@ -112,16 +113,10 @@ g_threaded_socket_service_incoming (GSocketService *service,
|
|||||||
|
|
||||||
threaded = G_THREADED_SOCKET_SERVICE (service);
|
threaded = G_THREADED_SOCKET_SERVICE (service);
|
||||||
|
|
||||||
data = g_slice_new (GThreadedSocketServiceData);
|
data = g_slice_new0 (GThreadedSocketServiceData);
|
||||||
|
data->service = g_object_ref (threaded);
|
||||||
/* Ref the socket service for the thread */
|
|
||||||
g_object_ref (service);
|
|
||||||
|
|
||||||
data->connection = g_object_ref (connection);
|
data->connection = g_object_ref (connection);
|
||||||
if (source_object)
|
data->source_object = (source_object != NULL) ? g_object_ref (source_object) : NULL;
|
||||||
data->source_object = g_object_ref (source_object);
|
|
||||||
else
|
|
||||||
data->source_object = NULL;
|
|
||||||
|
|
||||||
G_LOCK (job_count);
|
G_LOCK (job_count);
|
||||||
if (++threaded->priv->job_count == threaded->priv->max_threads)
|
if (++threaded->priv->job_count == threaded->priv->max_threads)
|
||||||
@ -149,7 +144,7 @@ g_threaded_socket_service_constructed (GObject *object)
|
|||||||
|
|
||||||
service->priv->thread_pool =
|
service->priv->thread_pool =
|
||||||
g_thread_pool_new (g_threaded_socket_service_func,
|
g_thread_pool_new (g_threaded_socket_service_func,
|
||||||
service,
|
NULL,
|
||||||
service->priv->max_threads,
|
service->priv->max_threads,
|
||||||
FALSE,
|
FALSE,
|
||||||
NULL);
|
NULL);
|
||||||
@ -161,6 +156,8 @@ g_threaded_socket_service_finalize (GObject *object)
|
|||||||
{
|
{
|
||||||
GThreadedSocketService *service = G_THREADED_SOCKET_SERVICE (object);
|
GThreadedSocketService *service = G_THREADED_SOCKET_SERVICE (object);
|
||||||
|
|
||||||
|
/* All jobs in the pool hold a reference to this #GThreadedSocketService, so
|
||||||
|
* this should only be called once the pool is empty: */
|
||||||
g_thread_pool_free (service->priv->thread_pool, FALSE, FALSE);
|
g_thread_pool_free (service->priv->thread_pool, FALSE, FALSE);
|
||||||
|
|
||||||
G_OBJECT_CLASS (g_threaded_socket_service_parent_class)
|
G_OBJECT_CLASS (g_threaded_socket_service_parent_class)
|
||||||
|
Loading…
Reference in New Issue
Block a user