type.h

os posted @ 2013年8月10日 17:13 in GObject , 1080 阅读

gobjec相关学习文章的list.

Read the source code!

看再多的文档,最后都要回归到code上面来。

Gtype.h:

/* Basic Type Macros

 */

#define G_TYPE_FUNDAMENTAL(type)                (g_type_fundamental (type))

#define                G_TYPE_FUNDAMENTAL_MAX                 (255 << G_TYPE_FUNDAMENTAL_SHIFT) //1020

#define G_TYPE_INVALID                                            G_TYPE_MAKE_FUNDAMENTAL (0) //0

#define G_TYPE_NONE                                                G_TYPE_MAKE_FUNDAMENTAL (1)   //4

#define G_TYPE_INTERFACE                      G_TYPE_MAKE_FUNDAMENTAL (2)   //8

#define G_TYPE_CHAR                                 G_TYPE_MAKE_FUNDAMENTAL (3)   //12

#define G_TYPE_UCHAR                                              G_TYPE_MAKE_FUNDAMENTAL (4) //16

#define G_TYPE_BOOLEAN                                         G_TYPE_MAKE_FUNDAMENTAL (5) //20

#define G_TYPE_INT                                      G_TYPE_MAKE_FUNDAMENTAL (6)  //24

#define G_TYPE_UINT                                  G_TYPE_MAKE_FUNDAMENTAL (7)

#define G_TYPE_LONG                                 G_TYPE_MAKE_FUNDAMENTAL (8)

#define G_TYPE_ULONG                                             G_TYPE_MAKE_FUNDAMENTAL (9)

#define G_TYPE_INT64                                 G_TYPE_MAKE_FUNDAMENTAL (10)

#define G_TYPE_UINT64                                              G_TYPE_MAKE_FUNDAMENTAL (11)

#define G_TYPE_ENUM                                               G_TYPE_MAKE_FUNDAMENTAL (12)

#define G_TYPE_FLAGS                                                G_TYPE_MAKE_FUNDAMENTAL (13)

#define G_TYPE_FLOAT                                                G_TYPE_MAKE_FUNDAMENTAL (14)

#define G_TYPE_DOUBLE                                            G_TYPE_MAKE_FUNDAMENTAL (15)

#define G_TYPE_STRING                                             G_TYPE_MAKE_FUNDAMENTAL (16)

#define G_TYPE_POINTER                                           G_TYPE_MAKE_FUNDAMENTAL (17)

#define G_TYPE_BOXED                                               G_TYPE_MAKE_FUNDAMENTAL (18)

#define G_TYPE_PARAM                                             G_TYPE_MAKE_FUNDAMENTAL (19)

#define G_TYPE_OBJECT                                              G_TYPE_MAKE_FUNDAMENTAL (20)

#define                G_TYPE_VARIANT                  G_TYPE_MAKE_FUNDAMENTAL (21) //84

有个疑问:为什么要shift移位?:

#define                G_TYPE_FUNDAMENTAL_SHIFT               (2)
  1. 定义Type ID时,左移;
  2. 保存指针到数组时,又右移,取得数组的index
  if (!pnode)					      /* offset fundamental types */
    {
      node = G_STRUCT_MEMBER_P (node, SIZEOF_FUNDAMENTAL_INFO);
      static_fundamental_type_nodes[ftype >> G_TYPE_FUNDAMENTAL_SHIFT] = node;
      type = ftype;
    }
  1. 在从数组中提取时,又右移
static inline TypeNode*
lookup_type_node_I (register GType utype)
{
  if (utype > G_TYPE_FUNDAMENTAL_MAX)
    return (TypeNode*) (utype & ~TYPE_ID_MASK);
  else
    return static_fundamental_type_nodes[utype >> G_TYPE_FUNDAMENTAL_SHIFT];
}

这种左移,右移的移位操作,本身效率是高,但是为什么要这样做?

类函数何时用?

 

GType boilerplate:

模板文件,这些宏,在后面用户自定义GObject时非常有用,

要理解他们,用好他们;

 

Gtype.c:

/* --- structures --- */

struct _TypeNode

{

  guint volatile ref_count;

  GTypePlugin *plugin;

  guint        n_children; /* writable with lock */  //子辈的个数

  guint        n_supers : 8; //父辈的个数

  guint        n_prerequisites : 9;

  guint        is_classed : 1;

  guint        is_instantiatable : 1;

  guint        mutatable_check_cache : 1;   /* combines some common path checks */

GType       *children; /* writable with lock */ //指针数组,用来保持孩子的信息:pnode->children[i] = type; pnode->children = g_renew (GType, pnode->children, pnode->n_children);


  TypeData * volatile data;

  GQuark       qname;

  GData       *global_gdata;

  union {

    GAtomicArray iface_entries;                  /* for !iface types */

    GAtomicArray offsets;

  } _prot;

  GType       *prerequisites;

  GType        supers[1]; /* flexible array */ //直接用memory copy进行增长

};



#define NODE_TYPE(node)                                                         (node->supers[0]) //自己

#define NODE_PARENT_TYPE(node)                                      (node->supers[1]) //父亲

#define NODE_FUNDAMENTAL_TYPE(node)                      (node->supers[node->n_supers]) //最顶层的父亲,就是基本类型


/* --- type nodes --- */

static GHashTable       *static_type_nodes_ht = NULL;

static TypeNode                               *static_fundamental_type_nodes[(G_TYPE_FUNDAMENTAL_MAX >> G_TYPE_FUNDAMENTAL_SHIFT) + 1] = { NULL, }; //全局的指针数组,用来保存基本类型,256个

static GType                       static_fundamental_next = G_TYPE_RESERVED_USER_FIRST;


?为什么需要一个hash table和一个全局的指针数组来保存Node节点呢?

数组查找快?

下面这个函数,同时操作上面的hash table和全局数组static_fundamental_type_nodes[]


static TypeNode*

type_node_any_new_W (TypeNode             *pnode,

                                     GType                 ftype,

                                     const gchar          *name,

                                     GTypePlugin          *plugin,

                                     GTypeFundamentalFlags type_flags)

{

  guint n_supers;

  GType type;

  TypeNode *node;

  guint i, node_size = 0;


  n_supers = pnode ? pnode->n_supers + 1 : 0; //如果有父类,则父类加1,否则父类为0


  //如果没有父类,则按照基础类型大小

  if (!pnode)

node_size += SIZEOF_FUNDAMENTAL_INFO;                      /* fundamental type info */


  node_size += SIZEOF_BASE_TYPE_NODE ();            /* TypeNode structure */

node_size += (sizeof (GType) * (1 + n_supers + 1)); /* self + ancestors + (0) for ->supers[] */


//给新节点分配内存

node = g_malloc0 (node_size);


//如果没有父节点,则直接保存在基础类型static_fundamental_type_nodes数组中

  if (!pnode)                                                                              /* offset fundamental types */

    {

      node = G_STRUCT_MEMBER_P (node, SIZEOF_FUNDAMENTAL_INFO);

      static_fundamental_type_nodes[ftype >> G_TYPE_FUNDAMENTAL_SHIFT] = node;

      type = ftype;

    }

  else

    type = (GType) node; //如果有父节点,则新分配的节点作为当前节点


  g_assert ((type & TYPE_ID_MASK) == 0);


  node->n_supers = n_supers; //记录有几个父节点

  if (!pnode)

    { //如果没有父节点

      node->supers[0] = type; //第一个节点就是,自己

      node->supers[1] = 0;

     

      node->is_classed = (type_flags & G_TYPE_FLAG_CLASSED) != 0;

      node->is_instantiatable = (type_flags & G_TYPE_FLAG_INSTANTIATABLE) != 0;

     

      if (NODE_IS_IFACE (node))

                {

          IFACE_NODE_N_PREREQUISITES (node) = 0;

                  IFACE_NODE_PREREQUISITES (node) = NULL;

                }

      else

                _g_atomic_array_init (CLASSED_NODE_IFACES_ENTRIES (node));

    }

  else

    { //如果有父节点

      node->supers[0] = type; //第一个节点就是自己


      //node->supers+1,指针后移动

     //把父节点的所有数据,都复制一份给当前节点,作为当前节点的父类信息

      memcpy (node->supers + 1, pnode->supers, sizeof (GType) * (1 + pnode->n_supers + 1));

     

      node->is_classed = pnode->is_classed;

      node->is_instantiatable = pnode->is_instantiatable;

     

      if (NODE_IS_IFACE (node))

                {

                  IFACE_NODE_N_PREREQUISITES (node) = 0;

                  IFACE_NODE_PREREQUISITES (node) = NULL;

                }

      else

                {

                  guint j;

                  IFaceEntries *entries;


                  entries = _g_atomic_array_copy (CLASSED_NODE_IFACES_ENTRIES (pnode),

                                                                                  IFACE_ENTRIES_HEADER_SIZE,

                                                                                  0);

                  if (entries)

                    {

                      for (j = 0; j < IFACE_ENTRIES_N_ENTRIES (entries); j++)

                                {

                                  entries->entry[j].vtable = NULL;

                                  entries->entry[j].init_state = UNINITIALIZED;

                                }

                      _g_atomic_array_update (CLASSED_NODE_IFACES_ENTRIES (node),

                                                                      entries);

                    }

                }

      //再和父类建立好关系

      i = pnode->n_children++;

      pnode->children = g_renew (GType, pnode->children, pnode->n_children);

      pnode->children[i] = type;

    }


  TRACE(GOBJECT_TYPE_NEW(name, node->supers[1], type));


  node->plugin = plugin;

  node->n_children = 0;

  node->children = NULL;

  node->data = NULL;

  node->qname = g_quark_from_string (name);

  node->global_gdata = NULL;


 //同时压入hash table中

  g_hash_table_insert (static_type_nodes_ht,

                                       GUINT_TO_POINTER (node->qname),

                                       (gpointer) type);

  return node;

}

上面提到的那个静态全局数组:TypeNode * static_fundamental_type_nodes[256];

TypeNode *

TypeNode *

TypeNode *

……

TypeNode *

保存的基础节点,即:没有父类的节点类型:同时,这些type也是可以做父亲的类型

|
`Void

|
`GInterface
|
`GTypePlugin
|
`gchar
|
`guchar
|
`gboolean
|
`gint
|
`guint
|
`glong
|
`gulong
|
`gint64
|
`guint64
|
`GEnum
|
`GFlags
|
`gfloat
|
`gdouble
|
`gchararray
|
`gpointer
|
`GType
|
`GBoxed
|
`GValueArray
|
`GParam
|
`GParamVariant
|
`GObject
|
`GVariant

下面是个内联函数,可以取代宏,有编译器直接展开,效率高;

同时,也可以检查参数的有效性;

static inline TypeNode*

lookup_type_node_I (register GType utype)

{

  if (utype > G_TYPE_FUNDAMENTAL_MAX)

    return (TypeNode*) (utype & ~TYPE_ID_MASK);

  else

    return static_fundamental_type_nodes[utype >> G_TYPE_FUNDAMENTAL_SHIFT];

}

数组的直接访问,效率是非常高的。

 

另外一个Hash Table:  GHashTable       *static_type_nodes_ht = NULL;

只有一个函数进行了调用:

GType

g_type_from_name (const gchar *name)

{

  GType type = 0;

  GQuark quark;


  g_return_val_if_fail (name != NULL, 0);


  quark = g_quark_try_string (name);

  if (quark)

    {

      G_READ_LOCK (&type_rw_lock);

      type = (GType) g_hash_table_lookup (static_type_nodes_ht, GUINT_TO_POINTER (quark));

      G_READ_UNLOCK (&type_rw_lock);

    }


  return type;

}

根据“名字”来查询,Hash Table的效率要高;

 

gobjec相关学习文章的list.


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter