[PATCH 6/8] libqmi-glib, device: port qmi_device_release_client to use GTask

Ben Chan benchan at chromium.org
Tue Apr 18 14:47:01 UTC 2017


On Tue, Apr 18, 2017 at 6:58 AM, Aleksander Morgado
<aleksander at aleksander.es> wrote:
>
> Hey Ben,
>
> See below.
>
> On 12/04/17 22:15, Ben Chan wrote:
> > ---
> >  src/libqmi-glib/qmi-device.c | 56 ++++++++++++++------------------------------
> >  1 file changed, 18 insertions(+), 38 deletions(-)
> >
> > diff --git a/src/libqmi-glib/qmi-device.c b/src/libqmi-glib/qmi-device.c
> > index 108b605..bc9480c 100644
> > --- a/src/libqmi-glib/qmi-device.c
> > +++ b/src/libqmi-glib/qmi-device.c
> > @@ -1120,32 +1120,18 @@ qmi_device_allocate_client (QmiDevice *self,
> >  /*****************************************************************************/
> >  /* Release client */
> >
> > -typedef struct {
> > -    QmiClient *client;
> > -    GSimpleAsyncResult *result;
> > -} ReleaseClientContext;
> > -
> > -static void
> > -release_client_context_complete_and_free (ReleaseClientContext *ctx)
> > -{
> > -    g_simple_async_result_complete_in_idle (ctx->result);
> > -    g_object_unref (ctx->result);
> > -    g_object_unref (ctx->client);
> > -    g_slice_free (ReleaseClientContext, ctx);
> > -}
> > -
> >  gboolean
> >  qmi_device_release_client_finish (QmiDevice *self,
> >                                    GAsyncResult *res,
> >                                    GError **error)
> >  {
> > -    return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
> > +    return g_task_propagate_boolean (G_TASK (res), error);
> >  }
> >
> >  static void
> >  client_ctl_release_cid_ready (QmiClientCtl *client_ctl,
> >                                GAsyncResult *res,
> > -                              ReleaseClientContext *ctx)
> > +                              GTask *task)
> >  {
> >      GError *error = NULL;
> >      QmiMessageCtlReleaseCidOutput *output;
> > @@ -1156,21 +1142,21 @@ client_ctl_release_cid_ready (QmiClientCtl *client_ctl,
> >      /* Check result of the async operation */
> >      output = qmi_client_ctl_release_cid_finish (client_ctl, res, &error);
> >      if (!output) {
> > -        g_simple_async_result_take_error (ctx->result, error);
> > -        release_client_context_complete_and_free (ctx);
> > +        g_task_return_error (task, error);
> > +        g_object_unref (task);
> >          return;
> >      }
> >
> >      /* Check result of the QMI operation */
> >      if (!qmi_message_ctl_release_cid_output_get_result (output, &error)) {
> > -        g_simple_async_result_take_error (ctx->result, error);
> > -        release_client_context_complete_and_free (ctx);
> > +        g_task_return_error (task, error);
> > +        g_object_unref (task);
> >          qmi_message_ctl_release_cid_output_unref (output);
> >          return;
> >      }
> >
> > -    g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
> > -    release_client_context_complete_and_free (ctx);
> > +    g_task_return_boolean (task, TRUE);
> > +    g_object_unref (task);
> >      qmi_message_ctl_release_cid_output_unref (output);
> >  }
> >
> > @@ -1183,7 +1169,7 @@ qmi_device_release_client (QmiDevice *self,
> >                             GAsyncReadyCallback callback,
> >                             gpointer user_data)
> >  {
> > -    ReleaseClientContext *ctx;
> > +    GTask *task;
> >      QmiService service;
> >      guint8 cid;
> >      gchar *flags_str;
> > @@ -1206,21 +1192,15 @@ qmi_device_release_client (QmiDevice *self,
> >
> >      /* NOTE! The operation must not take a reference to self, or we won't be
> >       * able to use it implicitly from our dispose() */
>
> This previous comment is misleading and obsolete, and we should remove
> it. There is no explicit CID releasing done during dispose(), and
> therefore we can (must I would say) take a reference to self in the GTask.
>
> > -
> > -    ctx = g_slice_new0 (ReleaseClientContext);
> > -    ctx->client = g_object_ref (client);
> > -    ctx->result = g_simple_async_result_new (G_OBJECT (self),
> > -                                             callback,
> > -                                             user_data,
> > -                                             qmi_device_release_client);
> > +    task = g_task_new (client, cancellable, callback, user_data);
> >
>
> The source_object for the GTask *must* be 'self', not 'client'. This is
> because during the task completion, the first argument given to the
> finish() function will be this object and that would be a QmiDevice.
> Now, this is really not required as the pointer is anyway not used in
> the finish() method, but we should keep it consistent.
>
> And if we do this, beware, because a bit further down in the logic there
> is a unregister_client() call that will remove the internal reference to
> the client (and therefore may be the last one), and just after that we
> do a g_object_set() on the client object. This worked always before
> because there was a client reference in the Context; but now there
> isn't. We cannot remove the g_object_set() call, as we don't know
> whether the caller holds a full reference or not, so the correct thing
> to do would be to make sure there is an explicit valid reference to the
> client object around those calls; or just set a full client reference as
> task data.
>

How about we put unregister_client after g_object_set?

Looking from another angle, should the caller keep a reference to client?

> >      /* Do not try to release an already released client */
> >      if (cid == QMI_CID_NONE) {
> > -        g_simple_async_result_set_error (ctx->result,
> > -                                         QMI_CORE_ERROR,
> > -                                         QMI_CORE_ERROR_INVALID_ARGS,
> > -                                         "Client is already released");
> > -        release_client_context_complete_and_free (ctx);
> > +        g_task_return_new_error (task,
> > +                                 QMI_CORE_ERROR,
> > +                                 QMI_CORE_ERROR_INVALID_ARGS,
> > +                                 "Client is already released");
> > +        g_object_unref (task);
> >          return;
> >      }
> >
> > @@ -1252,15 +1232,15 @@ qmi_device_release_client (QmiDevice *self,
> >                                      timeout,
> >                                      cancellable,
> >                                      (GAsyncReadyCallback)client_ctl_release_cid_ready,
> > -                                    ctx);
> > +                                    task);
> >
> >          qmi_message_ctl_release_cid_input_unref (input);
> >          return;
> >      }
> >
> >      /* No need to release the CID, so just done */
> > -    g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
> > -    release_client_context_complete_and_free (ctx);
> > +    g_task_return_boolean (task, TRUE);
> > +    g_object_unref (task);
> >      return;
> >  }
> >
> >
>
>
> --
> Aleksander
> https://aleksander.es


More information about the libqmi-devel mailing list