[glib-networking/mcatanzaro/tls-thread: 13/19] progress
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib-networking/mcatanzaro/tls-thread: 13/19] progress
- Date: Sat, 10 Aug 2019 00:43:43 +0000 (UTC)
commit b675ebb462786e34d6e5501fdc6ef9b0884f3502
Author: Michael Catanzaro <mcatanzaro gnome org>
Date: Fri Aug 9 15:23:15 2019 -0500
progress
tls/base/gtlsthread.c | 138 ++++++++++++++++++++++++++++++++++++--------------
1 file changed, 100 insertions(+), 38 deletions(-)
---
diff --git a/tls/base/gtlsthread.c b/tls/base/gtlsthread.c
index eec2798..ad611a0 100644
--- a/tls/base/gtlsthread.c
+++ b/tls/base/gtlsthread.c
@@ -64,10 +64,19 @@ struct _GTlsThread {
GObject parent_instance;
GTlsConnectionBase *connection; /* unowned */
- GThread *thread;
+
+ GThread *op_thread;
+ GMainContext *op_thread_context;
+
+ /* When pushing ops onto the queue, call g_main_context_wakeup() on
+ * op_thread_context to ensure the op is noticed.
+ */
GAsyncQueue *queue;
};
+static gboolean process_op (GAsyncQueue *queue,
+ GMainLoop *main_loop);
+
typedef enum {
G_TLS_THREAD_OP_READ,
G_TLS_THREAD_OP_SHUTDOWN
@@ -75,7 +84,7 @@ typedef enum {
typedef struct {
GTlsThreadOperationType type;
- GTlsConnectionBase *connection; /* FIXME: threadsafety nightmare */
+ GTlsConnectionBase *connection; /* FIXME: threadsafety nightmare, not OK */
void *data; /* unowned */
gsize size;
gint64 timeout;
@@ -160,6 +169,7 @@ g_tls_thread_read (GTlsThread *self,
buffer, size, timeout,
cancellable, main_loop);
g_async_queue_push (self->queue, op);
+ g_main_context_wakeup (self->op_thread_context);
g_main_loop_run (main_loop);
@@ -213,12 +223,11 @@ tls_op_queue_source_prepare (GSource *source,
GTlsOpQueueSource *op_source = (GTlsOpQueueSource *)source;
gboolean ready;
- /* FIXME: is using -1 timeout OK here? Probably not.
- * The GAsyncQueue could become ready before the timeout of another op expires.
- * So an op with a long timeout could improperly block the queue op.
- * But we cannot use 0 because that would churn the CPU. What's to do?
- */
ready = queue_has_pending_op (op_source->queue);
+
+ /* Why is it safe to use -1 as the timeout here? Because
+ * g_main_context_wakeup() will be called when pushing ops onto the queue!
+ */
*timeout = ready ? 0 : -1;
return ready;
@@ -270,6 +279,60 @@ tls_op_queue_source_new (GAsyncQueue *queue)
return (GSource *)source;
}
+typedef struct
+{
+ GAsyncQueue *queue;
+ GMainLoop *main_loop;
+} DelayedOpAsyncData;
+
+static DelayedOpAsyncData *
+delayed_op_async_data_new (GAsyncQueue *queue,
+ GMainLoop *main_loop)
+{
+ DelayedOpAsyncData *data;
+
+ data = g_new (DelayedOpAsyncData, 1);
+
+ /* No refs because these are guaranteed to outlive data. */
+ data->queue = queue;
+ data->main_loop = main_loop;
+
+ return data;
+}
+
+static void
+delayed_op_async_data_free (DelayedOpAsyncData *data)
+{
+ g_free (data);
+}
+
+static gboolean
+resume_tls_op (GObject *pollable_stream,
+ gpointer user_data)
+{
+ DelayedOpAsyncData *data = (DelayedOpAsyncData *)user_data;
+
+ process_op (data->queue, data->main_loop);
+
+ delayed_op_async_data_free (data);
+
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean
+resume_dtls_op (GDatagramBased *datagram_based,
+ GIOCondition condition,
+ gpointer user_data)
+{
+ DelayedOpAsyncData *data = (DelayedOpAsyncData *)user_data;
+
+ process_op (data->queue, data->main_loop);
+
+ delayed_op_async_data_free (data);
+
+ return G_SOURCE_REMOVE;
+}
+
static gboolean
process_op (GAsyncQueue *queue,
GMainLoop *main_loop)
@@ -294,7 +357,6 @@ process_op (GAsyncQueue *queue,
{
/* FIXME: handle all op types, including handshake and directional closes */
case G_TLS_THREAD_OP_READ:
- /* FIXME: do something with op->timeout */
op->result = G_TLS_CONNECTION_BASE_GET_CLASS (op->connection)->read_fn (op->connection,
op->data, op->size,
&op->count,
@@ -306,38 +368,31 @@ process_op (GAsyncQueue *queue,
g_assert_not_reached ();
}
-//////
- GDatagramBasedSourceFunc datagram_based_func = (GDatagramBasedSourceFunc)callback;
- GPollableSourceFunc pollable_func = (GPollableSourceFunc)callback;
- GTlsConnectionBaseSource *tls_source = (GTlsConnectionBaseSource *)source;
- gboolean ret;
-
- if (G_IS_DATAGRAM_BASED (tls_source->base))
- ret = (*datagram_based_func) (G_DATAGRAM_BASED (tls_source->base),
- tls_source->condition, user_data);
- else
- ret = (*pollable_func) (tls_source->base, user_data);
-//////
-
if (op->result == G_TLS_CONNECTION_BASE_WOULD_BLOCK)
{
GSource *tls_source;
+ GSource *timeout_source;
GMainContext *main_context;
+ DelayedOpAsyncData *data;
tls_source = g_tls_connection_base_create_source (op->connection,
condition,
op->cancellable);
- main_context = g_main_loop_get_context (main_loop);
+ /* tls_source should fire if (a) we're ready to ready/write without
+ * blocking, or (b) the timeout has elasped.
+ */
+ timeout_source = g_timeout_source_new (op->timeout);
+ g_source_add_child_source (tls_source, timeout_source);
+ g_source_unref (timeout_source);
+
+ data = delayed_op_async_data_new (queue, main_loop);
if (G_IS_DATAGRAM_BASED (op->connection))
- {
- g_source_set_callback (tls_source, G_SOURCE_FUNC ());
- }
+ g_source_set_callback (tls_source, G_SOURCE_FUNC (resume_dtls_op), data, NULL);
else
- {
-
- }
+ g_source_set_callback (tls_source, G_SOURCE_FUNC (resume_tls_op), data, NULL);
+ main_context = g_main_loop_get_context (main_loop);
g_source_attach (tls_source, main_context);
}
else
@@ -354,9 +409,9 @@ process_op (GAsyncQueue *queue,
}
static gpointer
-tls_thread (gpointer data)
+tls_op_thread (gpointer data)
{
- GAsyncQueue *queue = data;
+ GTlsThread *self = G_TLS_THREAD (data);
GMainContext *main_context;
GMainLoop *main_loop;
GSource *source;
@@ -366,17 +421,20 @@ tls_thread (gpointer data)
g_main_context_push_thread_default (main_context);
- source = tls_op_queue_source_new (queue);
+ source = tls_op_queue_source_new (self->queue);
g_source_set_callback (source, G_SOURCE_FUNC (process_op), main_loop, NULL);
g_source_attach (source, main_context);
g_main_loop_run (main_loop);
+ /* FIXME FIXME: what happens if there are still ops in progress?
+ * They should be cancelled somehow. Figure out how. Assert this has happened?
+ */
+
g_main_context_pop_thread_default (main_context);
g_main_loop_unref (main_loop);
g_main_context_unref (main_context);
- g_async_queue_unref (queue);
return NULL;
}
@@ -432,9 +490,10 @@ static void
g_tls_thread_init (GTlsThread *self)
{
self->queue = g_async_queue_new_full ((GDestroyNotify)g_tls_thread_operation_free);
- self->thread = g_thread_new ("[glib-networking] GTlsThreadBase TLS operations thread",
- tls_thread,
- g_async_queue_ref (self->queue));
+ self->op_thread_context = g_main_context_new ();
+ self->op_thread = g_thread_new ("[glib-networking] GTlsThreadBase TLS operations thread",
+ tls_op_thread,
+ self);
}
static void
@@ -442,12 +501,15 @@ g_tls_thread_finalize (GObject *object)
{
GTlsThread *self = G_TLS_THREAD (object);
- g_clear_weak_pointer (&self->connection);
-
g_async_queue_push (self->queue, g_tls_thread_shutdown_operation_new ());
- g_clear_pointer (&self->thread, g_thread_join);
+ g_main_context_wakeup (self->op_thread_context);
+
+ g_clear_pointer (&self->op_thread, g_thread_join);
+ g_clear_pointer (&self->op_thread_context, g_main_context_unref);
g_clear_pointer (&self->queue, g_async_queue_unref);
+ g_clear_weak_pointer (&self->connection);
+
G_OBJECT_CLASS (g_tls_thread_parent_class)->finalize (object);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]