diff options
author | Ross Burton <ross@linux.intel.com> | 2010-02-16 11:02:48 +0000 |
---|---|---|
committer | Ross Burton <ross@linux.intel.com> | 2010-08-13 11:03:14 +0100 |
commit | 53252f0867876584274c12274b02bf75c064f6da (patch) | |
tree | 5605669251d911fc78cfdc241621575a221df8d0 | |
parent | ed45f7103124fb802f913618faf65d0e60bf1725 (diff) | |
download | librest-53252f0867876584274c12274b02bf75c064f6da.tar.gz |
Add GIO-style async invoke methods
-rw-r--r-- | rest/rest-proxy-call-private.h | 2 | ||||
-rw-r--r-- | rest/rest-proxy-call.c | 150 | ||||
-rw-r--r-- | rest/rest-proxy-call.h | 11 |
3 files changed, 163 insertions, 0 deletions
diff --git a/rest/rest-proxy-call-private.h b/rest/rest-proxy-call-private.h index 50a2a0b..8a8cbcf 100644 --- a/rest/rest-proxy-call-private.h +++ b/rest/rest-proxy-call-private.h @@ -30,6 +30,7 @@ G_BEGIN_DECLS typedef struct _RestProxyCallAsyncClosure RestProxyCallAsyncClosure; +typedef struct _InvokeData InvokeData; struct _RestProxyCallPrivate { gchar *method; @@ -48,6 +49,7 @@ struct _RestProxyCallPrivate { RestProxy *proxy; RestProxyCallAsyncClosure *cur_call_closure; + InvokeData *cur_invoke; }; G_END_DECLS diff --git a/rest/rest-proxy-call.c b/rest/rest-proxy-call.c index 007fd25..f000dc0 100644 --- a/rest/rest-proxy-call.c +++ b/rest/rest-proxy-call.c @@ -41,6 +41,15 @@ struct _RestProxyCallAsyncClosure { SoupMessage *message; }; +struct _InvokeData { + RestProxyCall *call; + GAsyncReadyCallback callback; + GObject *weak_object; + gpointer user_data; + SoupMessage *message; + GCancellable *cancellable; +}; + enum { PROP_0 = 0, @@ -940,6 +949,147 @@ rest_proxy_call_sync (RestProxyCall *call, return ret; } +static void +_invoke_finished_cb (SoupSession *session, + SoupMessage *message, + gpointer user_data) +{ + InvokeData *data; + RestProxyCall *call; + RestProxyCallPrivate *priv; + GError *error = NULL; + GSimpleAsyncResult *res; + + data = (InvokeData *)user_data; + call = data->call; + priv = GET_PRIVATE (call); + + finish_call (call, message, &error); + + if (error == NULL) { + res = g_simple_async_result_new (G_OBJECT (data->call), + data->callback, + data->user_data, + rest_proxy_call_invoke); + g_simple_async_result_set_op_res_gpointer (res, data, NULL); + g_simple_async_result_complete (res); + g_object_unref (res); + } else { + res = g_simple_async_result_new_from_error (G_OBJECT (data->call), + data->callback, + data->user_data, + error); + g_simple_async_result_set_op_res_gpointer (res, data, NULL); + g_simple_async_result_complete (res); + g_error_free (error); + g_object_unref (res); + } +} + +void +rest_proxy_call_invoke (RestProxyCall *call, + GCancellable *cancellable, + GObject *weak_object, + GAsyncReadyCallback callback, + gpointer user_data) +{ + RestProxyCallPrivate *priv; + RestProxyCallClass *call_class; + SoupMessage *message; + InvokeData *data = NULL; + GSimpleAsyncResult *result; + GError *error; + + g_return_if_fail (REST_IS_PROXY_CALL (call)); + priv = GET_PRIVATE (call); + call_class = REST_PROXY_CALL_GET_CLASS (call); + + if (priv->cur_invoke) { + g_warning (G_STRLOC ": Call already in progress."); + error = g_error_new_literal (REST_PROXY_CALL_ERROR, + REST_PROXY_ERROR_FAILED, + "Call already in progress"); + goto error; + } + + message = prepare_message (call, &error); + if (message == NULL) { + error = g_error_new_literal (REST_PROXY_CALL_ERROR, + REST_PROXY_ERROR_FAILED, + "prepare_message failed"); + goto error; + } + + data = g_slice_new0 (InvokeData); + data->call = g_object_ref (call); + data->callback = callback; + data->weak_object = weak_object; + data->message = message; + data->user_data = user_data; + + priv->cur_invoke = data; + + /* Weakly reference this object. We remove our callback if it goes away. */ + if (data->weak_object) + { + g_object_weak_ref (data->weak_object, + (GWeakNotify)_call_async_weak_notify_cb, + data); + } + + _rest_proxy_queue_message (priv->proxy, message, _invoke_finished_cb, data); + g_free (priv->url); + priv->url = NULL; + return; + +error: + g_free (priv->url); + priv->url = NULL; + + result = g_simple_async_result_new_from_error (G_OBJECT (call), + callback, + user_data, + error); + g_simple_async_result_complete (result); + g_error_free (error); + g_object_unref (result); + if (data) + g_slice_free (InvokeData, data); +} + +gboolean +rest_proxy_call_invoke_finish (RestProxyCall *call, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + InvokeData *data; + + g_return_val_if_fail (REST_IS_PROXY_CALL (call), FALSE); + g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + g_warn_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (call), rest_proxy_call_invoke)); + data = g_simple_async_result_get_op_res_gpointer (simple); + + /* TOOD: do this here or in the callback? */ + if (data->weak_object) { + g_object_weak_unref (data->weak_object, + (GWeakNotify)_call_async_weak_notify_cb, + data); + } + + call->priv->cur_invoke = NULL; + g_object_unref (data->call); + g_slice_free (InvokeData, data); + + if (g_simple_async_result_propagate_error (simple, error)) + return FALSE; + else + return TRUE; +} + + /** * rest_proxy_call_lookup_response_header: * @call: The #RestProxyCall diff --git a/rest/rest-proxy-call.h b/rest/rest-proxy-call.h index c9648b2..4299c10 100644 --- a/rest/rest-proxy-call.h +++ b/rest/rest-proxy-call.h @@ -24,6 +24,7 @@ #define _REST_PROXY_CALL #include <glib-object.h> +#include <gio/gio.h> #include <rest/rest-params.h> G_BEGIN_DECLS @@ -159,6 +160,16 @@ gboolean rest_proxy_call_cancel (RestProxyCall *call); gboolean rest_proxy_call_sync (RestProxyCall *call, GError **error_out); +void rest_proxy_call_invoke (RestProxyCall *call, + GCancellable *cancellable, + GObject *weak_object, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean rest_proxy_call_invoke_finish (RestProxyCall *call, + GAsyncResult *result, + GError **error); + /* Functions for dealing with responses */ const gchar *rest_proxy_call_lookup_response_header (RestProxyCall *call, |