[glib/wip/danw/gnetworkconnectivity: 2/3] gio: make GNetworkMonitorBase public
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/wip/danw/gnetworkconnectivity: 2/3] gio: make GNetworkMonitorBase public
- Date: Wed, 3 Dec 2014 14:09:05 +0000 (UTC)
commit d214cba8bb04fd7607436e9432f0d66d216e0872
Author: Dan Winship <danw gnome org>
Date: Wed Apr 16 10:39:06 2014 -0400
gio: make GNetworkMonitorBase public
Make GNetworkMonitorBase public, so that other external-to-glib
network monitors can be built on top of it. (eg, in NetworkManager)
FIXME bug number
gio/Makefile.am | 2 +-
gio/gio.h | 1 +
gio/gnetworkmonitorbase.c | 159 ++++++++++++++++++++++++++++++++-----------
gio/gnetworkmonitorbase.h | 12 ++-
gio/tests/network-monitor.c | 4 -
5 files changed, 130 insertions(+), 48 deletions(-)
---
diff --git a/gio/Makefile.am b/gio/Makefile.am
index e993e2f..c157e45 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -406,7 +406,6 @@ libgio_2_0_la_SOURCES = \
gnetworkingprivate.h \
gnetworkmonitor.c \
gnetworkmonitorbase.c \
- gnetworkmonitorbase.h \
gnetworkservice.c \
goutputstream.c \
gpermission.c \
@@ -577,6 +576,7 @@ gio_headers = \
gnativevolumemonitor.h \
gnetworkaddress.h \
gnetworkmonitor.h \
+ gnetworkmonitorbase.h \
gnetworkservice.h \
goutputstream.h \
gpermission.h \
diff --git a/gio/gio.h b/gio/gio.h
index 3cc4af3..51f34cb 100644
--- a/gio/gio.h
+++ b/gio/gio.h
@@ -92,6 +92,7 @@
#include <gio/gnativevolumemonitor.h>
#include <gio/gnetworkaddress.h>
#include <gio/gnetworkmonitor.h>
+#include <gio/gnetworkmonitorbase.h>
#include <gio/gnetworkservice.h>
#include <gio/goutputstream.h>
#include <gio/gpermission.h>
diff --git a/gio/gnetworkmonitorbase.c b/gio/gnetworkmonitorbase.c
index ead9e64..5ff2f36 100644
--- a/gio/gnetworkmonitorbase.c
+++ b/gio/gnetworkmonitorbase.c
@@ -31,6 +31,35 @@
#include "gtask.h"
#include "glibintl.h"
+/**
+ * SECTION:gnetworkmonitorbase
+ * @title: GNetworkMonitorBase
+ * @short_description: Base GNetworkMonitor implementation
+ * @include: gio/gio.h
+ *
+ * #GNetworkMonitorBase is a base for implementations of
+ * #GNetworkMonitor. Subclasses can call
+ * g_network_monitor_base_add_network(),
+ * g_network_monitor_base_remove_network(), and
+ * g_network_monitor_base_set_networks(), and #GNetworkMonitorBase
+ * handles the #GNetworkMonitor properties and signals, and
+ * implements g_network_monitor_can_reach(), based on that data.
+ *
+ * #GNetworkMonitorBase is thread-safe, so subclasses can modify the
+ * list of networks from any thread, and signals and property
+ * notifications will automatically be proxied to monitor's
+ * thread-default context.
+ */
+
+/**
+ * GNetworkMonitorBase:
+ *
+ * #GNetworkMonitorBase is a base for implementations of
+ * #GNetworkMonitor.
+ *
+ * Since: 2.42
+ */
+
static void g_network_monitor_base_iface_init (GNetworkMonitorInterface *iface);
static void g_network_monitor_base_initable_iface_init (GInitableIface *iface);
@@ -43,6 +72,8 @@ enum
struct _GNetworkMonitorBasePrivate
{
+ GMutex mutex;
+
GPtrArray *networks;
gboolean have_ipv4_default_route;
gboolean have_ipv6_default_route;
@@ -73,6 +104,8 @@ static void
g_network_monitor_base_init (GNetworkMonitorBase *monitor)
{
monitor->priv = g_network_monitor_base_get_instance_private (monitor);
+
+ g_mutex_init (&monitor->priv->mutex);
monitor->priv->networks = g_ptr_array_new_with_free_func (g_object_unref);
monitor->priv->context = g_main_context_get_thread_default ();
if (monitor->priv->context)
@@ -129,6 +162,7 @@ g_network_monitor_base_finalize (GObject *object)
{
GNetworkMonitorBase *monitor = G_NETWORK_MONITOR_BASE (object);
+ g_mutex_clear (&monitor->priv->mutex);
g_ptr_array_free (monitor->priv->networks, TRUE);
if (monitor->priv->network_changed_source)
{
@@ -153,6 +187,7 @@ g_network_monitor_base_class_init (GNetworkMonitorBaseClass *monitor_class)
g_object_class_override_property (gobject_class, PROP_NETWORK_AVAILABLE, "network-available");
}
+/* Assumes base->priv->mutex is locked */
static gboolean
g_network_monitor_base_can_reach_sockaddr (GNetworkMonitorBase *base,
GSocketAddress *sockaddr)
@@ -182,6 +217,7 @@ g_network_monitor_base_can_reach (GNetworkMonitor *monitor,
GNetworkMonitorBase *base = G_NETWORK_MONITOR_BASE (monitor);
GSocketAddressEnumerator *enumerator;
GSocketAddress *addr;
+ gboolean can_reach = FALSE;
if (base->priv->networks->len == 0)
{
@@ -199,34 +235,39 @@ g_network_monitor_base_can_reach (GNetworkMonitor *monitor,
return FALSE;
}
+ g_mutex_lock (&base->priv->mutex);
+
if (base->priv->have_ipv4_default_route &&
base->priv->have_ipv6_default_route)
{
- g_object_unref (enumerator);
- g_object_unref (addr);
- return TRUE;
+ can_reach = TRUE;
+ goto done;
}
while (addr)
{
if (g_network_monitor_base_can_reach_sockaddr (base, addr))
{
- g_object_unref (addr);
- g_object_unref (enumerator);
- return TRUE;
+ can_reach = TRUE;
+ goto done;
}
g_object_unref (addr);
addr = g_socket_address_enumerator_next (enumerator, cancellable, error);
}
- g_object_unref (enumerator);
if (error && !*error)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_HOST_UNREACHABLE,
_("Host unreachable"));
}
- return FALSE;
+
+ done:
+ g_object_unref (enumerator);
+ g_clear_object (&addr);
+ g_mutex_unlock (&base->priv->mutex);
+
+ return can_reach;
}
static void
@@ -238,6 +279,7 @@ can_reach_async_got_address (GObject *object,
GTask *task = user_data;
GNetworkMonitorBase *base = g_task_get_source_object (task);
GSocketAddress *addr;
+ gboolean can_reach;
GError *error = NULL;
addr = g_socket_address_enumerator_next_finish (enumerator, result, &error);
@@ -260,18 +302,22 @@ can_reach_async_got_address (GObject *object,
}
}
- if (g_network_monitor_base_can_reach_sockaddr (base, addr))
+ g_mutex_lock (&base->priv->mutex);
+ can_reach = g_network_monitor_base_can_reach_sockaddr (base, addr);
+ g_mutex_unlock (&base->priv->mutex);
+ g_object_unref (addr);
+
+ if (can_reach)
{
- g_object_unref (addr);
g_task_return_boolean (task, TRUE);
g_object_unref (task);
- return;
}
- g_object_unref (addr);
-
- g_socket_address_enumerator_next_async (enumerator,
- g_task_get_cancellable (task),
- can_reach_async_got_address, task);
+ else
+ {
+ g_socket_address_enumerator_next_async (enumerator,
+ g_task_get_cancellable (task),
+ can_reach_async_got_address, task);
+ }
}
static void
@@ -281,18 +327,22 @@ g_network_monitor_base_can_reach_async (GNetworkMonitor *monitor,
GAsyncReadyCallback callback,
gpointer user_data)
{
+ GNetworkMonitorBase *base = G_NETWORK_MONITOR_BASE (monitor);
GTask *task;
GSocketAddressEnumerator *enumerator;
task = g_task_new (monitor, cancellable, callback, user_data);
- if (G_NETWORK_MONITOR_BASE (monitor)->priv->networks->len == 0)
+ g_mutex_lock (&base->priv->mutex);
+ if (base->priv->networks->len == 0)
{
+ g_mutex_unlock (&base->priv->mutex);
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NETWORK_UNREACHABLE,
_("Network unreachable"));
g_object_unref (task);
return;
}
+ g_mutex_unlock (&base->priv->mutex);
enumerator = g_socket_connectable_proxy_enumerate (connectable);
g_socket_address_enumerator_next_async (enumerator, cancellable,
@@ -338,9 +388,10 @@ static gboolean
emit_network_changed (gpointer user_data)
{
GNetworkMonitorBase *monitor = user_data;
- gboolean is_available;
+ gboolean available_changed = FALSE, network_changed = FALSE;
+ gboolean is_available = FALSE;
- g_object_ref (monitor);
+ g_mutex_lock (&monitor->priv->mutex);
if (monitor->priv->initializing)
monitor->priv->initializing = FALSE;
@@ -351,19 +402,27 @@ emit_network_changed (gpointer user_data)
if (monitor->priv->is_available != is_available)
{
monitor->priv->is_available = is_available;
- g_object_notify (G_OBJECT (monitor), "network-available");
+ available_changed = TRUE;
}
- g_signal_emit (monitor, network_changed_signal, 0, is_available);
+ network_changed = TRUE;
}
g_source_unref (monitor->priv->network_changed_source);
monitor->priv->network_changed_source = NULL;
+ g_mutex_unlock (&monitor->priv->mutex);
+ g_object_ref (monitor);
+ if (available_changed)
+ g_object_notify (G_OBJECT (monitor), "network-available");
+ if (network_changed)
+ g_signal_emit (monitor, network_changed_signal, 0, is_available);
g_object_unref (monitor);
+
return FALSE;
}
+/* Assumes monitor->priv->mutex is locked */
static void
queue_network_changed (GNetworkMonitorBase *monitor)
{
@@ -395,18 +454,9 @@ queue_network_changed (GNetworkMonitorBase *monitor)
}
}
-/**
- * g_network_monitor_base_add_network:
- * @monitor: the #GNetworkMonitorBase
- * @network: a #GInetAddressMask
- *
- * Adds @network to @monitor's list of available networks.
- *
- * Since: 2.32
- */
-void
-g_network_monitor_base_add_network (GNetworkMonitorBase *monitor,
- GInetAddressMask *network)
+static void
+g_network_monitor_base_add_network_unlocked (GNetworkMonitorBase *monitor,
+ GInetAddressMask *network)
{
int i;
@@ -443,13 +493,35 @@ g_network_monitor_base_add_network (GNetworkMonitorBase *monitor,
}
/**
+ * g_network_monitor_base_add_network:
+ * @monitor: the #GNetworkMonitorBase
+ * @network: a #GInetAddressMask
+ *
+ * Adds @network to @monitor's list of available networks and queues
+ * a #GNetworkMonitor:network-changed signal emission in @monitor's
+ * #GMainContext.
+ *
+ * Since: 2.42
+ */
+void
+g_network_monitor_base_add_network (GNetworkMonitorBase *monitor,
+ GInetAddressMask *network)
+{
+ g_mutex_lock (&monitor->priv->mutex);
+ g_network_monitor_base_add_network_unlocked (monitor, network);
+ g_mutex_unlock (&monitor->priv->mutex);
+}
+
+/**
* g_network_monitor_base_remove_network:
* @monitor: the #GNetworkMonitorBase
* @network: a #GInetAddressMask
*
- * Removes @network from @monitor's list of available networks.
+ * Removes @network from @monitor's list of available networks and
+ * queues a #GNetworkMonitor:network-changed signal emission in
+ * @monitor's #GMainContext.
*
- * Since: 2.32
+ * Since: 2.42
*/
void
g_network_monitor_base_remove_network (GNetworkMonitorBase *monitor,
@@ -457,6 +529,8 @@ g_network_monitor_base_remove_network (GNetworkMonitorBase *monitor,
{
int i;
+ g_mutex_lock (&monitor->priv->mutex);
+
for (i = 0; i < monitor->priv->networks->len; i++)
{
if (g_inet_address_mask_equal (monitor->priv->networks->pdata[i], network))
@@ -479,9 +553,11 @@ g_network_monitor_base_remove_network (GNetworkMonitorBase *monitor,
}
queue_network_changed (monitor);
- return;
+ break;
}
}
+
+ g_mutex_unlock (&monitor->priv->mutex);
}
/**
@@ -490,8 +566,9 @@ g_network_monitor_base_remove_network (GNetworkMonitorBase *monitor,
* @networks: (array length=length): an array of #GInetAddressMask
* @length: length of @networks
*
- * Drops @monitor's current list of available networks and replaces
- * it with @networks.
+ * Drops @monitor's current list of available networks and replaces it
+ * with @networks, and queues a #GNetworkMonitor:network-changed
+ * signal emission in @monitor's #GMainContext.
*/
void
g_network_monitor_base_set_networks (GNetworkMonitorBase *monitor,
@@ -500,10 +577,14 @@ g_network_monitor_base_set_networks (GNetworkMonitorBase *monitor,
{
int i;
+ g_mutex_lock (&monitor->priv->mutex);
+
g_ptr_array_set_size (monitor->priv->networks, 0);
monitor->priv->have_ipv4_default_route = FALSE;
monitor->priv->have_ipv6_default_route = FALSE;
for (i = 0; i < length; i++)
- g_network_monitor_base_add_network (monitor, networks[i]);
+ g_network_monitor_base_add_network_unlocked (monitor, networks[i]);
+
+ g_mutex_unlock (&monitor->priv->mutex);
}
diff --git a/gio/gnetworkmonitorbase.h b/gio/gnetworkmonitorbase.h
index 7970f7c..e04acaf 100644
--- a/gio/gnetworkmonitorbase.h
+++ b/gio/gnetworkmonitorbase.h
@@ -19,6 +19,10 @@
#ifndef __G_NETWORK_MONITOR_BASE_H__
#define __G_NETWORK_MONITOR_BASE_H__
+#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
+#error "Only <gio/gio.h> can be included directly."
+#endif
+
#include <gio/giotypes.h>
G_BEGIN_DECLS
@@ -48,17 +52,17 @@ struct _GNetworkMonitorBaseClass {
gpointer padding[8];
};
-GLIB_AVAILABLE_IN_ALL
+GLIB_AVAILABLE_IN_2_42
GType g_network_monitor_base_get_type (void);
/*< protected >*/
-GLIB_AVAILABLE_IN_2_32
+GLIB_AVAILABLE_IN_2_42
void g_network_monitor_base_add_network (GNetworkMonitorBase *monitor,
GInetAddressMask *network);
-GLIB_AVAILABLE_IN_2_32
+GLIB_AVAILABLE_IN_2_42
void g_network_monitor_base_remove_network (GNetworkMonitorBase *monitor,
GInetAddressMask *network);
-GLIB_AVAILABLE_IN_ALL
+GLIB_AVAILABLE_IN_2_42
void g_network_monitor_base_set_networks (GNetworkMonitorBase *monitor,
GInetAddressMask **networks,
gint length);
diff --git a/gio/tests/network-monitor.c b/gio/tests/network-monitor.c
index 08d6008..1482ceb 100644
--- a/gio/tests/network-monitor.c
+++ b/gio/tests/network-monitor.c
@@ -18,10 +18,6 @@
#include "gio.h"
-/* hack */
-#define GIO_COMPILATION
-#include "gnetworkmonitorbase.h"
-
#include <string.h>
/* Test data; the GInetAddresses and GInetAddressMasks get filled in
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]