diff options
author | Colin Walters <walters@verbum.org> | 2017-05-19 15:54:39 -0400 |
---|---|---|
committer | Colin Walters <walters@verbum.org> | 2017-06-14 14:45:45 -0400 |
commit | 017f78d77f0bf2bed749e21199ea89d75e56ab69 (patch) | |
tree | 64d2a72544548385f9cdfe29475e464c01e8576a | |
parent | ac0b0c84f7d310012d6960d96bb5daa62b8d2d48 (diff) | |
download | glib-017f78d77f0bf2bed749e21199ea89d75e56ab69.tar.gz |
gtype: Add private DEFINE_TYPE with prelude to workaround gtype deadlocks
And use it in GSocket, as it had a real-world case reported.
https://bugzilla.gnome.org/show_bug.cgi?id=674885
-rw-r--r-- | gio/gsocket.c | 24 | ||||
-rw-r--r-- | gobject/gtype-private.h | 11 | ||||
-rw-r--r-- | gobject/gtype.h | 16 |
3 files changed, 42 insertions, 9 deletions
diff --git a/gio/gsocket.c b/gio/gsocket.c index 2f04055cb..248074a49 100644 --- a/gio/gsocket.c +++ b/gio/gsocket.c @@ -52,6 +52,9 @@ #include <sys/uio.h> #endif +#define GOBJECT_COMPILATION +#include "gobject/gtype-private.h" /* For _PRELUDE type define */ +#undef GOBJECT_COMPILATION #include "gcancellable.h" #include "gdatagrambased.h" #include "gioenumtypes.h" @@ -267,13 +270,20 @@ struct _GSocketPrivate } recv_addr_cache[RECV_ADDR_CACHE_SIZE]; }; -G_DEFINE_TYPE_WITH_CODE (GSocket, g_socket, G_TYPE_OBJECT, - G_ADD_PRIVATE (GSocket) - g_networking_init (); - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - g_socket_initable_iface_init); - G_IMPLEMENT_INTERFACE (G_TYPE_DATAGRAM_BASED, - g_socket_datagram_based_iface_init)); +_G_DEFINE_TYPE_EXTENDED_WITH_PRELUDE (GSocket, g_socket, G_TYPE_OBJECT, 0, + /* Need a prelude for https://bugzilla.gnome.org/show_bug.cgi?id=674885 */ + g_type_ensure (G_TYPE_SOCKET_FAMILY); + g_type_ensure (G_TYPE_SOCKET_TYPE); + g_type_ensure (G_TYPE_SOCKET_PROTOCOL); + g_type_ensure (G_TYPE_SOCKET_ADDRESS); + /* And networking init is appropriate for the prelude */ + g_networking_init (); + , /* And now the regular type init code */ + G_ADD_PRIVATE (GSocket) + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + g_socket_initable_iface_init); + G_IMPLEMENT_INTERFACE (G_TYPE_DATAGRAM_BASED, + g_socket_datagram_based_iface_init)); static int get_socket_errno (void) diff --git a/gobject/gtype-private.h b/gobject/gtype-private.h index 1d05755c7..5f2f13b47 100644 --- a/gobject/gtype-private.h +++ b/gobject/gtype-private.h @@ -90,6 +90,17 @@ void _g_closure_invoke_va (GClosure *closure, int n_params, GType *param_types); +/** + * _G_DEFINE_TYPE_EXTENDED_WITH_PRELUDE: + * + * See also G_DEFINE_TYPE_EXTENDED(). This macro is generally only + * necessary as a workaround for classes which have properties of + * object types that may be initialized in distinct threads. See: + * https://bugzilla.gnome.org/show_bug.cgi?id=674885 + * + * Currently private. + */ +#define _G_DEFINE_TYPE_EXTENDED_WITH_PRELUDE(TN, t_n, T_P, _f_, _P_, _C_) _G_DEFINE_TYPE_EXTENDED_BEGIN_PRE (TN, t_n, T_P) {_P_;} _G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER (TN, t_n, T_P, _f_){_C_;} _G_DEFINE_TYPE_EXTENDED_END() G_END_DECLS diff --git a/gobject/gtype.h b/gobject/gtype.h index ab8f97c35..89c1bec16 100644 --- a/gobject/gtype.h +++ b/gobject/gtype.h @@ -1943,7 +1943,8 @@ static void type_name##_class_intern_init (gpointer klass) \ } #endif /* GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_38 */ -#define _G_DEFINE_TYPE_EXTENDED_BEGIN(TypeName, type_name, TYPE_PARENT, flags) \ +/* Added for _G_DEFINE_TYPE_EXTENDED_WITH_PRELUDE */ +#define _G_DEFINE_TYPE_EXTENDED_BEGIN_PRE(TypeName, type_name, TYPE_PARENT) \ \ static void type_name##_init (TypeName *self); \ static void type_name##_class_init (TypeName##Class *klass); \ @@ -1962,7 +1963,11 @@ type_name##_get_instance_private (TypeName *self) \ GType \ type_name##_get_type (void) \ { \ - static volatile gsize g_define_type_id__volatile = 0; \ + static volatile gsize g_define_type_id__volatile = 0; + /* Prelude goes here */ + +/* Added for _G_DEFINE_TYPE_EXTENDED_WITH_PRELUDE */ +#define _G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER(TypeName, type_name, TYPE_PARENT, flags) \ if (g_once_init_enter (&g_define_type_id__volatile)) \ { \ GType g_define_type_id = \ @@ -1982,6 +1987,13 @@ type_name##_get_type (void) \ return g_define_type_id__volatile; \ } /* closes type_name##_get_type() */ +/* This was defined before we had G_DEFINE_TYPE_WITH_CODE_AND_PRELUDE, it's simplest + * to keep it. + */ +#define _G_DEFINE_TYPE_EXTENDED_BEGIN(TypeName, type_name, TYPE_PARENT, flags) \ + _G_DEFINE_TYPE_EXTENDED_BEGIN_PRE(TypeName, type_name, TYPE_PARENT) \ + _G_DEFINE_TYPE_EXTENDED_BEGIN_REGISTER(TypeName, type_name, TYPE_PARENT, flags) \ + #define _G_DEFINE_INTERFACE_EXTENDED_BEGIN(TypeName, type_name, TYPE_PREREQ) \ \ static void type_name##_default_init (TypeName##Interface *klass); \ |