一个实现 GAsyncInitable 接口类的例子

GAsyncInitable 是一个支持异步的、可失败的对象初始化接口类,开发时需要支持异步创建对象并存在失败的可能(多数用于包含 I/O 操作的对象)即可实现此接口类。

完整的示例代码

HevIObj 类是基于 GObject 类的,类中对象实例的创建有两个方法:

void hev_iobj_new_async(GCancellable *cancellable,
                        GAsyncReadyCallback callback, gpointer user_data);
GObject * hev_iobj_new_finish(GAsyncInitable *initable,
                        GAsyncResult *res, GError **error);

对象实例化时先通过调用 hev_iobj_new_async 方法并传入回调函数,当对象初始化好后传入的回调函数将被调用,在回调函数中再调用对象的 hev_iobj_new_finish 方法即可得到类的新对象实例。

接口类的实现

static void hev_iobj_async_initable_iface_init(GAsyncInitableIface *iface);
static void hev_iobj_async_initable_init_async(GAsyncInitable *initable,
                        gint io_priority, GCancellable *cancellable,
                        GAsyncReadyCallback callback, gpointer user_data);
static gboolean hev_iobj_async_initable_init_finish(GAsyncInitable *initable,
                        GAsyncResult *result, GError **error);
 
G_DEFINE_TYPE_WITH_CODE(HevIObj, hev_iobj, G_TYPE_OBJECT,
                G_IMPLEMENT_INTERFACE(G_TYPE_ASYNC_INITABLE, hev_iobj_async_initable_iface_init));

与实现其它接口类没有什么区别,通过宏 G_IMPLEMENT_INTERFACE 格式的写入接口类型和接口类初始化函数,hev_iobj_async_initable_iface_init 接口类初始化函数中进行接口方法的重载:

static void hev_iobj_async_initable_iface_init(GAsyncInitableIface *iface)
{
        g_debug("%s:%d[%s]", __FILE__, __LINE__, __FUNCTION__);
 
        iface->init_async = hev_iobj_async_initable_init_async;
        iface->init_finish = hev_iobj_async_initable_init_finish;
}

重载的异步实例初始化函数 hev_iobj_async_initable_init_async 将在 hev_iobj_new_async 方法后被调用,它先创建一个 GSimpleAsyncResult 实例,用于返回异步操作的结果。如果异步操作支持取消,g_simple_async_result_set_check_cancellable 应该在 GSimpleAsyncResult 实例创建后立即调用,GIO 的异步操作实例是通过线程的方式实现的,g_simple_async_result_run_in_thread 方法则是创建一个新的线程并执行异步操作,传入的线程的处理函数完成后 hev_iobj_async_initable_init_finish 即被调用。详见示例代码:

static void hev_iobj_async_initable_init_async(GAsyncInitable *initable,
                        gint io_priority, GCancellable *cancellable,
                        GAsyncReadyCallback callback, gpointer user_data)
{
        HevIObj *self = HEV_IOBJ(initable);
        HevIObjPrivate *priv = HEV_IOBJ_GET_PRIVATE(self);
        GSimpleAsyncResult *simple = NULL;
 
        g_debug("%s:%d[%s]", __FILE__, __LINE__, __FUNCTION__);
 
        simple = g_simple_async_result_new(G_OBJECT(initable),
                                callback, user_data, hev_iobj_async_initable_init_async);
        g_simple_async_result_set_check_cancellable(simple, cancellable);
        g_simple_async_result_run_in_thread(simple, async_result_run_in_thread_handler,
                                io_priority, cancellable);
        g_object_unref(simple);
}

当异步操作完成后, hev_iobj_async_initable_init_finish 将被调用,在里面可通过 GError 向外抛出错误(如果出错 hev_iobj_new_finish 方法传入的 error 将被填充),并通过此函数的返回值控制对象的初始化是否完成。

static gboolean hev_iobj_async_initable_init_finish(GAsyncInitable *initable,
                        GAsyncResult *result, GError **error)
{
        g_debug("%s:%d[%s]", __FILE__, __LINE__, __FUNCTION__);
 
        g_return_val_if_fail(g_simple_async_result_is_valid(result,
                                        G_OBJECT(initable), hev_iobj_async_initable_init_async),
                                FALSE);
        if(g_simple_async_result_propagate_error(G_SIMPLE_ASYNC_RESULT(result),
                                        error))
          return FALSE;
 
        return TRUE;
}

Debug 信息显示出的对象创建和销毁的整个流程

** (process:21875): DEBUG: hev-iobj.c:137[hev_iobj_new_async]
** (process:21875): DEBUG: hev-iobj.c:70[hev_iobj_class_init]
** (process:21875): DEBUG: hev-iobj.c:82[hev_iobj_async_initable_iface_init]
** (process:21875): DEBUG: hev-iobj.c:54[hev_iobj_constructor]
** (process:21875): DEBUG: hev-iobj.c:92[hev_iobj_init]
** (process:21875): DEBUG: hev-iobj.c:61[hev_iobj_constructed]
** (process:21875): DEBUG: hev-iobj.c:109[hev_iobj_async_initable_init_async]
** (process:21875): DEBUG: hev-iobj.c:98[async_result_run_in_thread_handler]
** (process:21875): DEBUG: hev-iobj.c:146[hev_iobj_new_finish]
** (process:21875): DEBUG: hev-iobj.c:122[hev_iobj_async_initable_init_finish]
** (process:21875): DEBUG: hev-iobj.c:37[hev_iobj_dispose]
** (process:21875): DEBUG: hev-iobj.c:47[hev_iobj_finalize]

Over!

Leave a Reply

Your email address will not be published. Required fields are marked *