zoukankan      html  css  js  c++  java
  • TinyMail研究—类型系统

     

    TinyMail研究—类型系统

     

    转载时请注明出处和作者联系方式:http://blog.csdn.net/absurd

    作者联系方式:李先静<xianjimli at hotmail dot com>

    更新时间:2007-4-11

     

    TinyMail是一套针对移动设备设计的邮件系统框架,为了达到最大的灵活性,它采用了很多设计模式和先进的编程技术,让框架的每一部分都可以定制和配置。TinyMail流行的趋势非常明显,Nokia770/800GPE Phone Edition等项目中都使用了它。因为我们也要开发邮件系统,所以花了几天时间去研究它的实现,这里记录一些研究笔记,供有兴趣的朋友参考。本文介绍一下TinyMail类型系统

     

    TinyMail虽然是用C语言开发的,但完全采用了面向对象的设计方法,为此它实现了自己的类型系统。TinyMail的类型系统和glib的类型系统极为类似,让人奇怪的是,TinyMail本身已经使用了glib,为什么它不用gobject的类型系统,而要自己实现一套呢?抱着这个疑问,我花了一些时间去研究它的实现:

     

    1.         ObjectObjectClass

    gobject一样,每个类都由两个基本结构组成:ObjectObjectClass

     

    Object结构定义了对象的数据成员,每个对象实例都有自己的拷贝。该结构的第一个成员用来实现继承关系,这是C语言中实现继承的常用手法。比如(CamelService继承于CamelObject)

    struct _CamelService {

        CamelObject parent_object;

        struct _CamelServicePrivate *priv;

     

        CamelSession *session;

        CamelProvider *provider;

        CamelServiceConnectionStatus status;

        CamelOperation *connect_op;

        CamelURL *url;

        gpointer data;

    };

     

    ObjectClass定义了对象的行为和所有实例的共享数据。对象的行为也就是一些函数指针,用来实现虚函数。该结构的第一个成员用来实现继承关系,这是C语言中实现继承的常用手法。如(CamelServiceClass继承于CamelObjectClass)

    typedef struct {

        CamelObjectClass parent_class;

       

        void      (*construct)         (CamelService *service,

                        CamelSession *session,

                        CamelProvider *provider,

                        CamelURL *url,

                        CamelException *ex);

     

        gboolean  (*connect)           (CamelService *service,

                        CamelException *ex);

        gboolean  (*disconnect)        (CamelService *service,

                        gboolean clean,

                        CamelException *ex);

        void      (*cancel_connect)    (CamelService *service);

     

        GList *   (*query_auth_types)  (CamelService *service,

                        CamelException *ex);

       

        char *    (*get_name)          (CamelService *service,

                        gboolean brief);

        char *    (*get_path)          (CamelService *service);

     

    } CamelServiceClass;

     

    这与glib相似。

     

    2.         类型的注册。

    可以调用函数camel_type_register向类型系统注册新类型,注册时要提供下列信息:

    l         父类的类型。

    l         名称。

    l         Object的大小。

    l         ObjectClass的大小。

    l         ObjectClass的初始化函数。

    l         ObjectClass的释放函数。

    l         Object的初始化函数。

    l         Object的释放函数。

     

    camel_interface_register是对camel_type_register的包装,用于注册接口。由于接口只有虚函数,没有数据成员,所以Object的大小为0,也没有Object的初始化函数和释放函数。

     

    camel_type_register调用co_type_register完成注册。在注册时,co_type_register先建立类型的层次关系,然后插入到hash表中,最后调用ObjectClass的初始化函数。在调用ObjectClass的初始化函数时,它会从最顶层基类的ObjectClass的初始化函数一直调到当前类的ObjectClass的初始化函数。

     

    这与glib相似。

     

    3.         对象的创建。

    可以调用camel_object_new创建对象实例,该函数要求一个指明对象类型的参数。也可以调用camel_object_new_name创建对象实例,该函数是对camel_object_new包装,它先通过类型名称获得类型,然后调用camel_object_new创建对象。

     

    camel_object_new首先根据注册时指定的对象大小分配一块内存,然后调用Object的初始化函数初始化它,然后返回指向该内存块的指针。在调用Object的初始化函数时,它会从最顶层基类的Object的初始化函数一直调到当前类的Object的初始化函数。

     

    这与glib相似。

     

    4.         对象的销毁。

    虽然在注册类型时,指定了Object的释放函数,但不直接调用它去销毁对象,而是由对象的引用计数来决定是否真正销毁对象。

     

    camel_object_unref用于将对象的引用计数减一,当对象的引用计数为0时,它会:

    l         触发finalize信号,让相关对象得到通知。

    l         从当前类的Object的释放函数一直调到最顶层基类的Object的释放函数。

    l         释放内存。

     

    glib相比,对象的销毁不再分disposefinalize两阶段,对于互相引用的对象可能存在问题。

     

    5.         对象的引用计数。

    camel_object_ref增加引用计数。

    camel_object_unref减少引用计数。

     

    glib相比,缺少弱引用(weak ref)功能,但可以通过finalize信号来模拟实现。

     

    6.         对象的属性。

    camel_object_set/camel_object_setv可以用来设置对象的属性。

    camel_object_get/camel_object_getv/camel_object_get_ptr/camel_object_get_int可以用来获取对象的属性。

     

    glib相比,不需要安装属性的spec

          

    7.         signal(event)机制。

    camel_object_hook_event用于注册。

    camel_object_remove_event/camel_object_unhook_event用于注销。

    camel_object_trigger_event用于触发。

     

    glib相比,不需要那套复杂的marshal机制,所有参数都是gpointer格式,但使用简单的同时也失去类型检查的好处。

     

    8.         持久化。

    camel_object_state_write负责保存对象状态。

    camel_object_state_read负责恢复对象状态。

     

    glib相比,这是一个特有的功能。

     

    综上所述,我觉得TinyMail的类型系统虽然实现很精巧,但完全可以建立在glib的类型系统之上,没有必要自己重搞一套。

     

    ~~end~~

     

  • 相关阅读:
    正则表达式
    浏览器加载时间线
    浏览器事件
    脚本化CSS
    定时器元素大小位置属性等 20181231
    关于行内元素 20181229
    个人冲刺01
    周总结
    团队冲刺10
    团队冲刺09
  • 原文地址:https://www.cnblogs.com/zhangyunlin/p/6167737.html
Copyright © 2011-2022 走看看