SlideShare uma empresa Scribd logo
1 de 11
Baixar para ler offline
.
......
Reference Counting
April 19, 2013
........ ..... ................. ................. ................. .... .... . .... ........ .
.....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
.....
.
....
.
....
.
資源管理
• 在 concurrent 的環境很難確定 object 何時才沒有被使用
• 此時 reference counting 是一個不錯的管理方法
• object 紀錄目前 reference 的個數
• 當個數變為 0 時就做 deallocation
Reference Counting April 19, 2013 2 / 11
.....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
.....
.
....
.
....
.
實作
struct Obj {
guint ref_count;
};
struct Obj * obj_ref(struct Obj *o) {
if (o) {
.. g_atomic_int_inc(&o->ref_count);
}
return o;
}
void obj_unref(struct Object *o) {
if (o && ..g_atomic_int_dec_and_test(&o->ref_count) ) {
obj_free(o);
}
}
..
遞增個數
.
遞減並檢查個數
Reference Counting April 19, 2013 3 / 11
.....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
.....
.
....
.
....
.
使用規則
..1 複製 object pointer 前要先做 obj_ref,尤其是 asynchronous call 的
時候
..2 當 object 使用完要做 obj_unref
..3 如果 object pointer 沒有做過 obj_ref,要確保 obj_ref 完成前不會做
obj_unref
Reference Counting April 19, 2013 4 / 11
.....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
.....
.
....
.
....
.
規則 1
gpointer thread(struct Obj *o) {
obj_unref(o);
return NULL;
}
void f(void) {
struct Obj *o = obj_new();
g_timeout_add_full(
G_PRIORITY_DEFAULT , 1000,
timeout , ..obj_ref(o) , (GDestroyNotify)obj_unref;
);
g_thread_new(NULL, (GThreadFunc)thread, ..obj_ref(o) );
obj_unref(o);
}
..
確保 object 在 timeout 時還存在
.
確保 object 在 thread 執行時還存在
Reference Counting April 19, 2013 5 / 11
.....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
.....
.
....
.
....
.
規則 2
gpointer thread(struct Obj *o) {
.. obj_unref(o);
return NULL;
}
void f(void) {
struct Obj *o = obj_new();
g_timeout_add_full(
G_PRIORITY_DEFAULT , 1000,
timeout , obj_ref(o), (GDestroyNotify)..obj_unref ;
);
g_thread_new(NULL, (GThreadFunc)thread, obj_ref(o));
.. obj_unref(o);
}
..
lifetime 結束
.
lifetime 結束
.
lifetime 結束
Reference Counting April 19, 2013 6 / 11
.....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
.....
.
....
.
....
.
規則 3
struct Obj * obj_table_get(gpointer key) {
struct Obj *o;
.. G_LOCK(lock);
.. o = g_hash_table_lookup(table, key);
o = obj_ref(o);
.. G_UNLOCK(lock);
return o;
}
void obj_table_put(struct Obj *o) {
.. G_LOCK(lock);
obj_unref(o);
.. G_UNLOCK(lock);
}
..
object 還沒做過 obj_ref
.
lock 起來確保順序是對的
.
lock 起來確保順序是對的
Reference Counting April 19, 2013 7 / 11
.....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
.....
.
....
.
....
.
Global variable 的情況
static struct Obj *glob;
struct Obj * glob_get(void) {
struct Obj *o;
.. G_LOCK(lock);
o = obj_ref(glob);
.. G_UNLOCK(lock)
return o;
}
void glob_put(struct Obj *o) {
.. G_LOCK(lock);
obj_unref(o);
.. G_UNLOCK(lock)
}
void glob_set(struct Obj *o) {
.. G_LOCK(lock);
obj_unref(glob);
glob = obj_ref(o);
.. G_UNLOCK(lock)
}
..
一樣要 lock
.
一樣要 lock
.
一樣要 lock
Reference Counting April 19, 2013 8 / 11
.....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
.....
.
....
.
....
.
Reference cycle
struct Obj * obj_new(void) {
struct Obj *o = g_malloc0(sizeof(*o));
o->ref_count = 1;
o->timeout = g_timeout_source_new(1000);
g_source_set_callback(
o->timeout , timeout ,
.. obj_ref(o) , (GDestroyNotify)obj_unref
);
g_source_attach(o->timeout , NULL);
g_source_unref(o->timeout);
return o;
}
void obj_table_add(gpointer key) {
G_LOCK(lock);
.. g_hash_table_insert(table, key, obj_new());
G_UNLOCK(lock);
}
..
reference cycle
Reference Counting April 19, 2013 9 / 11
.....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
.....
.
....
.
....
.
解除 cycle
void obj_destroy(struct Obj *o) {
.. g_source_destroy(o->timeout);
obj_unref(o);
}
void obj_table_remove(gpointer key) {
G_LOCK(lock);
.. g_hash_table_remove(table, key);
G_UNLOCK(lock);
}
void obj_table_init(void) {
table = g_hash_table_new_full(
g_direct_hash , g_direct_equal ,
NULL, (GDestroyNotify)..obj_destroy
);
}
..
主動結束 child object 的 lifetime
.
value destructor
Reference Counting April 19, 2013 10 / 11
.....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
....
.
....
.
.....
.
....
.
.....
.
....
.
....
.
參考資料
• https://www.kernel.org/doc/Documentation/kref.txt
Reference Counting April 19, 2013 11 / 11

Mais conteúdo relacionado

Mais procurados

Mais procurados (6)

Jug bizus (4)
Jug   bizus (4)Jug   bizus (4)
Jug bizus (4)
 
Jug bizus
Jug   bizusJug   bizus
Jug bizus
 
Mágica com qt’s meta object system
Mágica com qt’s meta object systemMágica com qt’s meta object system
Mágica com qt’s meta object system
 
Javascript avançado
Javascript avançadoJavascript avançado
Javascript avançado
 
JavaScript Hacks
JavaScript HacksJavaScript Hacks
JavaScript Hacks
 
Javascript Ilegível
Javascript IlegívelJavascript Ilegível
Javascript Ilegível
 

Reference Counting: Resource Management and Memory Leak Prevention