Calling base class methods

Aleksander Morgado aleksander at aleksander.es
Wed Mar 9 14:12:32 UTC 2022


Hey

> I have a question around how to properly call base class methods and
> passing the async result back to the caller. Consider the following
> scenario:
>
> * MMBroadbandBearerFibocomEcm inherits from MMBroadbandBearer
> * MMBroadbandBearerFibocomEcm implements its own connect_3gpp and
> connect_3gpp_finish
> * In certain cases MMBroadbandBearerFibocomEcm::connect_3gpp wants to
> call MMBroadbandBearer::connect_3gpp
>
> Here's what I got for MMBroadbandBearerFibocomEcm:
>
> static void
> parent_connect_ready (MMBroadbandBearer *bearer,
>                        GAsyncResult      *res,
>                        GTask             *task)
> {
>      /* TODO how to propagate the result back to the original callback? */

If you called MM_BROADBAND_BEARER_CLASS
(mm_broadband_bearer_fibocom_ecm_parent_class)->connect_3gpp(), then
you must call MM_BROADBAND_BEARER_CLASS
(mm_broadband_bearer_fibocom_ecm_parent_class)->connect_3gpp_finish()
at this point in the ready callback, in order to get the result of the
parent method, which you can then set as result in your own GTask, so
that it's then passed to your own connect_3gpp_finish().

MMBearerConnectResult *connect_result;
GError *error = NULL;

connect_result = MM_BROADBAND_BEARER_CLASS
(mm_broadband_bearer_fibocom_ecm_parent_class)->connect_3gpp_finish
(bearer, res, &error);
if (!connect_result)
    g_task_return_error (task, error);
else
   g_task_return_pointer (task, connect_result, (GDestroyNotify)
mm_bearer_connect_result_unref);
g_object_unref  (task);

> }
>
> static void
> connect_3gpp (MMBroadbandBearer *self,
>                MMBroadbandModem *modem,
>                MMPortSerialAt *primary,
>                MMPortSerialAt *secondary,
>                GCancellable *cancellable,
>                GAsyncReadyCallback callback,
>                gpointer user_data)
> {
>      GTask *task = g_task_new (self, cancellable, callback, user_data);
>      if (some_condition) {
>          MM_BROADBAND_BEARER_CLASS
> (mm_broadband_bearer_fibocom_ecm_parent_class)->connect_3gpp (
>              MM_BROADBAND_BEARER (self),
>              modem,
>              primary,
>              secondary,
>              cancellable,
>              (GAsyncReadyCallback) parent_connect_ready,
>              task
>          );

You would be missing a "return;" here. Once you pass the GTask to the
parent connect_3gpp operation, you should no longer use it in the
remaining logic.

>      } else {
>          /* some other code path */
>      }
> }
>
> Is there a way to directly invoke the original callback from the
> parent_connect_ready callback with the result res? How would I do this
> best? I don't want to re-implement everything from
> MMBroadbandBearer::connect_3gpp_ready because that does a bunch with
> connect_succeeded which is private.

You don't invoke the original callback in parent_connect_ready. What
you do in parent_connect_ready is to set as result of your own
connect_3gpp implementation the result you received from the parent.
We don't mix callbacks from different GTasks; actually, you don't even
know if that "res" you received is a GTask or a GSimpleAsyncResult, so
you just treat it as an opaque thing. What you do know is that if you
call an async method passing a ready callback, your ready callback
will be called with the operation is finished, and you should then run
the corresponding async_finish() method to get the result of that
operation. You're chainging async calls here, we don't merge them in
any way.

-- 
Aleksander
https://aleksander.es


More information about the ModemManager-devel mailing list