[gnio/connection-factory: 1/6] Add generic socket connection factory
- From: Alexander Larsson <alexl src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnio/connection-factory: 1/6] Add generic socket connection factory
- Date: Fri, 8 May 2009 10:25:38 -0400 (EDT)
commit fe7937c1553fb5d3eb4660b83025edc0666152b7
Author: Alexander Larsson <alexl redhat com>
Date: Fri May 8 14:33:37 2009 +0200
Add generic socket connection factory
Classes can register a specific type for a family/type/protocol tuple.
This will be used when creating a connection from a socket.
---
gio/gsocketconnection.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++
gio/gsocketconnection.h | 16 ++++-
2 files changed, 153 insertions(+), 3 deletions(-)
diff --git a/gio/gsocketconnection.c b/gio/gsocketconnection.c
index 3d9a7c1..60687e3 100644
--- a/gio/gsocketconnection.c
+++ b/gio/gsocketconnection.c
@@ -38,6 +38,9 @@
#include "gsocketinputstream.h"
#include "giostream.h"
+#include "gunixconnection.h"
+
+
static void g_socket_connection_iface_init (GIOStreamIface *iface);
G_DEFINE_TYPE_WITH_CODE (GSocketConnection,
g_socket_connection, G_TYPE_OBJECT,
@@ -204,3 +207,140 @@ g_socket_connection_iface_init (GIOStreamIface *iface)
iface->get_input_stream = g_socket_connection_get_input_stream;
iface->get_output_stream = g_socket_connection_get_output_stream;
}
+
+typedef struct {
+ GSocketFamily socket_family;
+ GSocketType socket_type;
+ char *protocol;
+ GType implementation;
+} ConnectionFactory;
+
+static guint
+connection_factory_hash (gconstpointer key)
+{
+ const ConnectionFactory *factory = key;
+ guint h;
+
+ h = factory->socket_family ^ (factory->socket_type << 4);
+ /* This is likely to be small, so spread over whole
+ hash space to get some distribution */
+ h = h ^ (h << 8) ^ (h << 16) ^ (h << 24);
+
+ if (factory->protocol)
+ h ^= g_str_hash (factory->protocol);
+ return h;
+}
+
+static gboolean
+connection_factory_equal (gconstpointer _a,
+ gconstpointer _b)
+{
+ const ConnectionFactory *a = _a;
+ const ConnectionFactory *b = _b;
+
+ if (a->socket_family != b->socket_family)
+ return FALSE;
+
+ if (a->socket_type != b->socket_type)
+ return FALSE;
+
+ if (a->protocol != b->protocol)
+ {
+ if (a->protocol == NULL || b->protocol == NULL)
+ return FALSE;
+
+ if (strcmp (a->protocol, b->protocol) != 0)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+connection_factory_free (ConnectionFactory *factory)
+{
+ g_free (factory->protocol);
+ g_free (factory);
+}
+
+static GHashTable *connection_factories = NULL;
+G_LOCK_DEFINE_STATIC(connection_factories);
+
+void
+g_socket_connection_factory_register_type (GType g_type,
+ GSocketFamily family,
+ GSocketType type,
+ const char *protocol)
+{
+ ConnectionFactory *factory;
+
+ G_LOCK (connection_factories);
+
+ if (connection_factories == NULL)
+ connection_factories = g_hash_table_new_full (connection_factory_hash,
+ connection_factory_equal,
+ (GDestroyNotify)connection_factory_free,
+ NULL);
+
+ factory = g_new0 (ConnectionFactory, 1);
+ factory->socket_family = family;
+ factory->socket_type = type;
+ factory->protocol = g_strdup (protocol);
+ factory->implementation = g_type;
+
+ g_hash_table_insert (connection_factories,
+ factory, factory);
+
+ G_UNLOCK (connection_factories);
+}
+
+static void
+init_builtin_types (void)
+{
+#ifndef G_OS_WIN32
+ volatile GType a_type;
+
+ a_type = g_unix_connection_get_type ();
+#endif
+}
+
+GType
+g_socket_connection_factory_lookup_type (GSocketFamily family,
+ GSocketType type,
+ const char *protocol)
+{
+ ConnectionFactory *factory, key;
+ GType g_type;
+
+ G_LOCK (connection_factories);
+
+ init_builtin_types ();
+
+ g_type = G_TYPE_SOCKET_CONNECTION;
+
+ if (connection_factories)
+ {
+ key.socket_family = family;
+ key.socket_type = type;
+ key.protocol = (char *)protocol;
+
+ factory = g_hash_table_lookup (connection_factories, &key);
+ if (factory)
+ g_type = factory->implementation;
+ }
+
+ G_UNLOCK (connection_factories);
+
+ return g_type;
+}
+
+GSocketConnection *
+g_socket_connection_factory_create_connection (GSocket *socket)
+{
+ GType type;
+
+ type = g_socket_connection_factory_lookup_type (g_socket_get_family (socket),
+ g_socket_get_socket_type (socket),
+ g_socket_get_protocol (socket));
+ return g_object_new (type, "socket", socket, NULL);
+}
diff --git a/gio/gsocketconnection.h b/gio/gsocketconnection.h
index 40ed737..55b1996 100644
--- a/gio/gsocketconnection.h
+++ b/gio/gsocketconnection.h
@@ -22,6 +22,7 @@
#define _gsocketconnection_h_
#include <glib-object.h>
+#include <gio/gsocket.h>
G_BEGIN_DECLS
@@ -52,10 +53,19 @@ struct _GSocketConnection
GSocketConnectionPrivate *priv;
};
-GType g_socket_connection_get_type (void);
+GType g_socket_connection_get_type (void);
-gboolean g_socket_connection_close (GSocketConnection *connection,
- GError **error);
+gboolean g_socket_connection_close (GSocketConnection *connection,
+ GError **error);
+
+void g_socket_connection_factory_register_type (GType g_type,
+ GSocketFamily family,
+ GSocketType type,
+ const char *protocol);
+GType g_socket_connection_factory_lookup_type (GSocketFamily family,
+ GSocketType type,
+ const char *protocol);
+GSocketConnection *g_socket_connection_factory_create_connection (GSocket *socket);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]