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~~

 

原文地址:https://www.cnblogs.com/zhangyunlin/p/6167737.html