g_object_weak_ref的意义和用途

g_object_weak_ref的 意义和用途

 

引用自:http://blog.csdn.net/absurd

 

引用计数是控制对象生命周期常用的手法,对象初始引用计数为一,引用一次计数加一,反引用一次计数减一,直到计数降为零时,对象被销毁。 GObject 也实现了引用计数机制, g_object_ref 函数用于引用,增加引用计数。 g_object_unref 函数用于反引用,减少引用计数。

 

GObject 还提供了另外两个函数 : g_object_weak_ref/g_object_weak_unref weak_ref 直译过来是弱引用,但它们的意义并不是很直观,新手常常很迷惑,本文介绍它们的意义和用途。我们先看看它们的函数原型:

void        g_object_weak_ref             (GObject        *object,

                            GWeakNotify     notify,

                           gpointer        data);

void        g_object_weak_unref           (GObject        *object,

                           GWeakNotify     notify,

                           gpointer         data);

 

g_object_ref/g_object_unref 相比, g_object_weak_ref/g_object_weak_unref 的原型要复杂许多,而且也看不出它们与引用 有何关系。但从文档和代码可以很容易知道, g_object_weak_ref 的功能就是注册一个回调函数,该函数将在对象被销毁时调用。

 

这与引用有什么关系呢?我们用一个例子说明:

 

在短信应用中,假设我们只允许一个写短信的窗口存在。要进入写短信界面,第一次创建写短信窗口,并把窗口句柄保存起来。这相当于引用了该窗口,但是我们不能调用 g_object_ref 去增加窗口的引用计数,原因是没适当的时候去反引用它,这会导致窗口无法关闭。

 

第二次进入时,先判断保存的窗口句柄是否为空,如果不为空,则认为窗口已经打开,直接把它提到前面来即可。

 

窗 口不存在就创建它,存在就重用它,保证只有一个写短信的窗口存在。但上面的逻辑是有漏洞的:假设写完短信,用户通过正当或者不正当的手段关闭该窗口。窗口 已经关闭了,但外面还保存着它的句柄,这个窗口句柄指向无效的内存,若仅仅以保存的窗口句柄是否为空,来判断窗口是否已经打开,就必然会出现错误。

 

窗口本身并不知道外面是否保存了它的句柄,它不可能在销毁时去把保存的句柄置为空。怎么办呢?最简单的办法就利用 g_object_weak_ref ,向窗口注册一个回调函数,窗口在销毁时调用该回调函数,在回调函数中,可以把保存的窗口句柄置为空。

 

简单的说: g_object_weak_ref 让引用者有机会知道,引用的对象是否已经无效了,这可以防止野指针的出现。对于窗口对象,要模拟实现 g_object_weak_ref 的功能,其实有好几种方法:比如用 GTK_IS_WIDGET 判断窗口是否还有效、用 g_object_set_data_full 注册回调函数,或者注册 GtkObject destroy 信号等。当然,只有 g_object_weak_ref 是名正言顺的,也只有它是最简单的。

 

~~end~~

 

==================================================

下面来看个具体的例子:

static void
call_weak_notify (gpointer data, GObject *dead_object)
{
  GList *list = data;

  list = g_list_remove (list, dead_object);
}

void
call_list_add (GList *list, Call *call)
{
  g_object_weak_ref (G_OBJECT (call), call_weak_notify, list);

  list = g_list_prepend (list, call);
}

void
call_list_remove (GList *list, Call *call)
{
  g_object_weak_unref (G_OBJECT (call), call_weak_notify, list);

  list = g_list_remove (list, call);
}
  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Table of Contents Introduction I. Concepts Background Data types and programming Exporting a C API The Glib Dynamic Type System Copy functions Conventions Non-Instantiable non-classed fundamental types Instantiable classed types: objects Initialization and Destruction Non-instantiable classed types: Interfaces. Interface Initialization Interface Destruction The GObject base class Object instanciation Object memory management Reference count Weak References Reference counts and cycles Object properties Accessing multiple properties at once The GObject messaging system Closures C Closures non-C closures (for the fearless). Signals Signal registration Signal connection Signal emission The detail argument II. API Reference GType - The GLib Runtime type identification and management system GTypePlugin - An interface for dynamically loadable types GTypeModule - Type loading modules GObject - The base object type Enums and Flags - Enumeration and flags types GBoxed - A mechanism to wrap opaque C structures registered by the type system Generic Values - A polymorphic type that can hold values of any other type Parameters and Values - Standard Parameter and Value Types Varargs Value Collection - Converting varargs to generic values GParamSpec - Metadata for parameter specifications Signals - A means for customization of object behaviour and a general purpose notification mechanism Closures - Functions as first-class objects Value arrays - A container structure to maintain an array of generic values III. Tools Reference glib-mkenums - C language enum description generation utility glib-genmarshal - C code marshaller generation utility for GLib closures gobject-query - display a tree of types IV. Tutorial How To define and implement a new GObject? Boilerplate header code Boilerplate code Object Construction Object Destruction Object methods Non-virtual public methods Virtual public methods Virtual private Methods Chaini

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值