2013-10-23 109 views
0

我在C中使用了GLib/GObject,並且在某些情況下我想要類似靜態構造函數的東西,即存在於C#和Java中的東西。如何在GObject中獲得類似初始化的靜態構造函數?

靜態構造函數只能在首次創建對象時運行一次。關於C#或Java中靜態構造函數的一個很好的特性是它們是線程安全。即使多個線程同時創建該類的對象,只有一個線程會執行靜態構造函數,而其他線程(常規,非靜態)構造函數會阻塞,直到該線程完成。

這讓靜態構造函數的線程安全的靜態字段初始化一個完美的地方(這只是在C/GObject的全局變量)。

如果你不能想到哪裏就需要這樣的功能,ckeckout這個問題,這將是很容易解決的靜態構造函數的情況:How to cleanly instantiate a global mutex that is shared by threads in one of the threads itself

回答

2

把它放在類初始化函數。如果你不確定如何做到這一點,這裏是一個微不足道的例子:

#include <glib.h> 
#include <glib-object.h> 


#define TYPE_FOO (foo_get_type()) 
#define FOO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_FOO, Foo)) 
#define FOO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_FOO, FooClass)) 
#define IS_FOO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_FOO)) 
#define IS_FOO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_FOO)) 
#define FOO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_FOO, FooClass)) 

typedef struct _Foo Foo; 
typedef struct _FooClass FooClass; 
typedef struct _FooPrivate FooPrivate; 

struct _Foo { 
    GObject parent_instance; 
    FooPrivate * priv; 
}; 

struct _FooClass { 
    GObjectClass parent_class; 
}; 


static gpointer foo_parent_class = NULL; 

GType foo_get_type (void) G_GNUC_CONST; 
enum { 
    FOO_DUMMY_PROPERTY 
}; 
Foo* foo_new (void); 
Foo* foo_construct (GType object_type); 


Foo* foo_construct (GType object_type) { 
    Foo * self = NULL; 
    self = (Foo*) g_object_new (object_type, NULL); 
    return self; 
} 


Foo* foo_new (void) { 
    return foo_construct (TYPE_FOO); 
} 


static void foo_class_init (FooClass * klass) { 
    foo_parent_class = g_type_class_peek_parent (klass); 
    /* static construct code goes here */ 
} 


static void foo_instance_init (Foo * self) { 
} 


GType foo_get_type (void) { 
    static volatile gsize foo_type_id__volatile = 0; 
    if (g_once_init_enter (&foo_type_id__volatile)) { 
     static const GTypeInfo g_define_type_info = { sizeof (FooClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) foo_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Foo), 0, (GInstanceInitFunc) foo_instance_init, NULL }; 
     GType foo_type_id; 
     foo_type_id = g_type_register_static (G_TYPE_OBJECT, "Foo", &g_define_type_info, 0); 
     g_once_init_leave (&foo_type_id__volatile, foo_type_id); 
    } 
    return foo_type_id__volatile; 
} 
+0

我想知道爲什麼這是線程安全的。什麼時候_class_init函數準確執行? – Dyna

+0

@Dyna它在'g_type_register_static'中執行,即。第一次請求輸入「Foo」的類型。正如你所看到的,這部分功能是線程安全的。 – Ancurio

相關問題