GObject 参考手册:概念:基类 GObject:对象内存管理

The memory-management API for GObjects is a bit complicated but the idea behind it is pretty simple: the goal is to provide a flexible model based on reference counting which can be integrated in applications which use or require different memory management models (such as garbage collection, aso…). The methods which are used to manipulate this reference count are described below.
GObject的内存管理相关的API有一点复杂,但是背后的主旨是相当简单的:它的目的是提供一个灵活的基于引用计数的、可以集成在使用或需要各种不同的内存管理模型(就像垃圾回收)的应用程序的模型。这些方法被用来操作它的引用数。

/*
  Refcounting
*/
gpointer    g_object_ref                      (gpointer        object);
void        g_object_unref                    (gpointer        object);
 
/*
  Weak References
*/
typedef void (*GWeakNotify)                (gpointer      data,
                                         GObject      *where_the_object_was);
void            g_object_weak_ref                      (GObject              *object,
                                               GWeakNotify     notify,
                                               gpointer               data);
void            g_object_weak_unref                      (GObject              *object,
                                               GWeakNotify     notify,
                                               gpointer               data);
void        g_object_add_weak_pointer         (GObject        *object, 
                                               gpointer       *weak_pointer_location);
void        g_object_remove_weak_pointer      (GObject        *object, 
                                               gpointer       *weak_pointer_location);
/*
  Cycle handling
*/
void        g_object_run_dispose              (GObject              *object);

Reference count
引用计数

The functions g_object_ref/g_object_unref respectively increase and decrease the reference count.These functions are thread-safe as of GLib 2.8. The reference count is, unsurprisingly, initialized to one by g_object_new which means that the caller is currently the sole owner of the newly-created reference. When the reference count reaches zero, that is, when g_object_unref is called by the last client holding a reference to the object, the dispose and the finalize class methods are invoked.
函数g_object_ref/g_object_unref 分别增加或减少引用数。在GLib 2.8中,这些函数是线程安全的。所谓引用计数,没啥悬念的,当g_object_new初始化了一个实例后,调用者即成了新创建的引用的把持者。当引用计数到达0以后,最后保持这个对象引用的客户端在调用g_object_unref后,处理和终结类方法将被调用。

Finally, after finalize is invoked, g_type_free_instance is called to free the object instance. Depending on the memory allocation policy decided when the type was registered (through one of the g_type_register_* functions), the object’s instance memory will be freed or returned to the object pool for this type. Once the object has been freed, if it was the last instance of the type, the type’s class will be destroyed as described in the section called “Instantiable classed types: objects” and the section called “Non-instantiable classed types: interfaces”.
在终结函数被调用以后,g_type_free_instance被呼叫来翻译这个对象的实例。依赖内存分配策略中类型的注册时间(通过 g_type_register函数集),对象的实例所占据的内存将被释放并将类型返回对象池中。一旦对象被释放,如果它是最后一个这个类型的实例,那么类型的类将被销毁(如前面章节所讲的销毁策略一样)。

The table below summarizes the destruction process of a GObject:
关于一个GObject的销毁过程总结如下:

Invocation time Function Invoked Function’s parameters Remark
Last call to g_object_unref for an instance of target type target type’s dispose class function GObject instance When dispose ends, the object should not hold any reference to any other member object. The object is also expected to be able to answer client method invocations (with possibly an error code but no memory violation) until finalize is executed. dispose can be executed more than once. dispose should chain up to its parent implementation just before returning to the caller.
target type’s finalize class function GObject instance Finalize is expected to complete the destruction process initiated by dispose. It should complete the object’s destruction. finalize will be executed only once. finalize should chain up to its parent implementation just before returning to the caller. The reason why the destruction process is split is two different phases is explained in the section called “Reference counts and cycles”.
Last call to g_object_unref for the last instance of target type interface’ interface_finalize function On interface’ vtable Never used in practice. Unlikely you will need it.
interface’ base_finalize function On interface’ vtable Never used in practice. Unlikely you will need it.
target type’s class_finalize function On target type’s class structure Never used in practice. Unlikely you will need it.
type’s base_finalize function On the inheritance tree of classes from fundamental type to target type. base_init is invoked once for each class structure. Never used in practice. Unlikely you will need it.

Weak References
弱引用

Weak References are used to monitor object finalization: g_object_weak_ref adds a monitoring callback which does not hold a reference to the object but which is invoked when the object runs its dispose method. As such, each weak ref can be invoked more than once upon object finalization (since dispose can run more than once during object finalization).
弱引用用来监视一个对象的终结:g_object_weak_ref加入了一个不把持对象引用的监视回调函数,但当对象运行它的处理函数时会被调用。这样的话,每个弱引用都可以在对象终结前被调用超过一次(因为处理函数在对象终结前会运行超过一次)。

g_object_weak_unref can be used to remove a monitoring callback from the object.
g_object_weak_unref可以用来从对象上移除一个监视回调函数。

Weak References are also used to implement g_object_add_weak_pointer and g_object_remove_weak_pointer. These functions add a weak reference to the object they are applied to which makes sure to nullify the pointer given by the user when object is finalized.
弱引用同样用来实现g_object_add_weak_pointer和g_object_remove_weak_pointer。这些函数用来废弃对象的指针,当对象被终结以后。

Reference counts and cycles
引用计数和周期

GObject’s memory management model was designed to be easily integrated in existing code using garbage collection. This is why the destruction process is split in two phases: the first phase, executed in the dispose handler is supposed to release all references to other member objects. The second phase, executed by the finalize handler is supposed to complete the object’s destruction process. Object methods should be able to run without program error (that is, without segfault 🙂 in-between the two phases.
GObject的内存管理模式被设计为可以容易地集成在现存的使用垃圾回收的代码中。这就是为什么销毁过程会被分离成两个阶段:第一个阶段,执行处理过程使得猜想释放了所有到其他对象的引用。第二个阶段,执行终结处理函数并猜想完成了对象销毁过程。对象的方法应该有能力在这两个阶段里无错误的情况下运行。

This two-step destruction process is very useful to break reference counting cycles. While the detection of the cycles is up to the external code, once the cycles have been detected, the external code can invoke g_object_dispose which will indeed break any existing cycles since it will run the dispose handler associated to the object and thus release all references to other objects.
这两步走的销毁过程对于打断引用计数周期是十分有用的。当在外部代码检测循环周期时,外部代码可以调用g_object_dispose来运行与这个对象相关联的处理函数来理想地打断现存的周期。

Attentive readers might now have understood one of the rules about the dispose handler we stated a bit sooner: the dispose handler can be invoked multiple times. Let’s say we have a reference count cycle: object A references B which itself references object A. Let’s say we have detected the cycle and we want to destroy the two objects. One way to do this would be to invoke g_object_dispose on one of the objects.
聪明的读者可能已经懂了处理函数的一些规则:处理函数可以被调用好几次。我们来假设一个引用计数周期:对象A引用了B,同B自己也引用了对象A。现在我们知道了这个周期,并决定销毁这两个对象。来完成这个,只要在其中一个对象调用g_object_dispose即可。

If object A releases all its references to all objects, this means it releases its reference to object B. If object B was not owned by anyone else, this is its last reference count which means this last unref runs B’s dispose handler which, in turn, releases B’s reference on object A. If this is A’s last reference count, this last unref runs A’s dispose handler which is running for the second time before A’s finalize handler is invoked !
如果对象A释放了到所有其他对象的引用,这个意味着它释放了它到对象B的引用。如果对象B已经不被其他所占有,这就是最后一次由B的处理函数进行的引用计数,释放在对象A上的引用。

Leave a Reply

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