From bc4055664b9e0c7d73a1416fd17dfd2058fe5ad5 Mon Sep 17 00:00:00 2001 From: Colin Leroy Date: Mon, 3 Jan 2005 18:03:20 +0000 Subject: [PATCH] 2005-01-03 [colin] 0.9.13cvs25.4 * src/common/utils.c * src/common/utils.h * src/gtk/prefswindow.c Move auto pointer stuff to utils.c Patch by Alfons again :) --- ChangeLog-gtk2.claws | 8 ++ PATCHSETS | 1 + configure.ac | 2 +- src/common/utils.c | 165 ++++++++++++++++++++++++++++++++++++++++++ src/common/utils.h | 13 ++++ src/gtk/prefswindow.c | 68 +---------------- 6 files changed, 189 insertions(+), 68 deletions(-) diff --git a/ChangeLog-gtk2.claws b/ChangeLog-gtk2.claws index 7f7bddfff..d3f6c02e8 100644 --- a/ChangeLog-gtk2.claws +++ b/ChangeLog-gtk2.claws @@ -1,3 +1,11 @@ +2005-01-03 [colin] 0.9.13cvs25.4 + + * src/common/utils.c + * src/common/utils.h + * src/gtk/prefswindow.c + Move auto pointer stuff to utils.c + Patch by Alfons again :) + 2005-01-03 [colin] 0.9.13cvs25.3 * src/compose.c diff --git a/PATCHSETS b/PATCHSETS index 7fe175a45..8de32c718 100644 --- a/PATCHSETS +++ b/PATCHSETS @@ -303,3 +303,4 @@ ( cvs diff -u -r 1.56.2.30 -r 1.56.2.31 src/pop.c; cvs diff -u -r 1.17.2.12 -r 1.17.2.13 src/pop.h; ) > 0.9.13cvs25.1.patchset ( cvs diff -u -r 1.115.2.25 -r 1.115.2.26 src/main.c; cvs diff -u -r 1.100.2.9 -r 1.100.2.10 AUTHORS; ) > 0.9.13cvs25.2.patchset ( cvs diff -u -r 1.382.2.81 -r 1.382.2.82 src/compose.c; cvs diff -u -r 1.10.2.8 -r 1.10.2.9 src/prefs_gtk.c; cvs diff -u -r 1.12.2.4 -r 1.12.2.5 src/prefs_template.c; cvs diff -u -r 1.96.2.37 -r 1.96.2.38 src/textview.c; ) > 0.9.13cvs25.3.patchset +( cvs diff -u -r 1.36.2.18 -r 1.36.2.19 src/common/utils.c; cvs diff -u -r 1.20.2.12 -r 1.20.2.13 src/common/utils.h; cvs diff -u -r 1.12.2.13 -r 1.12.2.14 src/gtk/prefswindow.c; ) > 0.9.13cvs25.4.patchset diff --git a/configure.ac b/configure.ac index b5c2e1ece..766f042c8 100644 --- a/configure.ac +++ b/configure.ac @@ -13,7 +13,7 @@ INTERFACE_AGE=0 BINARY_AGE=0 EXTRA_VERSION=25 EXTRA_RELEASE= -EXTRA_GTK2_VERSION=.3 +EXTRA_GTK2_VERSION=.4 if test \( $EXTRA_VERSION -eq 0 \) -o \( "x$EXTRA_RELEASE" != "x" \); then VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.${MICRO_VERSION}${EXTRA_RELEASE}${EXTRA_GTK2_VERSION} diff --git a/src/common/utils.c b/src/common/utils.c index 1bb4b7c01..b0f9e5516 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -3731,3 +3731,168 @@ void get_hex_str(gchar *out, guchar ch) INT_TO_HEX(hex, ch & 0x0f); *out++ = hex; } + +#undef REF_DEBUG +#ifndef REF_DEBUG +#define G_PRINT_REF 1 == 1 ? (void) 0 : (void) +#else +#define G_PRINT_REF g_print +#endif + +/*! + *\brief Register ref counted pointer. It is based on GBoxed, so should + * work with anything that uses the GType system. The semantics + * are similar to a C++ auto pointer, with the exception that + * C doesn't have automatic closure (calling destructors) when + * exiting a block scope. + * Use the \ref G_TYPE_AUTO_POINTER macro instead of calling this + * function directly. + * + *\return GType A GType type. + */ +GType g_auto_pointer_register(void) +{ + static GType auto_pointer_type; + if (!auto_pointer_type) + auto_pointer_type = + g_boxed_type_register_static + ("G_TYPE_AUTO_POINTER", + (GBoxedCopyFunc) g_auto_pointer_copy, + (GBoxedFreeFunc) g_auto_pointer_free); + return auto_pointer_type; +} + +/*! + *\brief Structure with g_new() allocated pointer guarded by the + * auto pointer + */ +typedef struct AutoPointerRef { + void (*free) (gpointer); + gpointer pointer; + glong cnt; +} AutoPointerRef; + +/*! + *\brief The auto pointer opaque structure that references the + * pointer guard block. + */ +typedef struct AutoPointer { + AutoPointerRef *ref; + gpointer ptr; /*!< access to protected pointer */ +} AutoPointer; + +/*! + *\brief Creates an auto pointer for a g_new()ed pointer. Example: + * + *\code + * + * ... tell gtk_list_store it should use a G_TYPE_AUTO_POINTER + * ... when assigning, copying and freeing storage elements + * + * gtk_list_store_new(N_S_COLUMNS, + * G_TYPE_AUTO_POINTER, + * -1); + * + * + * Template *precious_data = g_new0(Template, 1); + * g_pointer protect = g_auto_pointer_new(precious_data); + * + * gtk_list_store_set(container, &iter, + * S_DATA, protect, + * -1); + * + * ... the gtk_list_store has copied the pointer and + * ... incremented its reference count, we should free + * ... the auto pointer (in C++ a destructor would do + * ... this for us when leaving block scope) + * + * g_auto_pointer_free(protect); + * + * ... gtk_list_store_set() now manages the data. When + * ... *explicitly* requesting a pointer from the list + * ... store, don't forget you get a copy that should be + * ... freed with g_auto_pointer_free() eventually. + * + *\endcode + * + *\param pointer Pointer to be guarded. + * + *\return GAuto * Pointer that should be used in containers with + * GType support. + */ +GAuto *g_auto_pointer_new(gpointer p) +{ + AutoPointerRef *ref = g_new0(AutoPointerRef, 1); + AutoPointer *ptr = g_new0(AutoPointer, 1); + + ref->pointer = p; + ref->free = g_free; + ref->cnt = 1; + + ptr->ref = ref; + ptr->ptr = p; + + G_PRINT_REF ("XXXX ALLOC(%lx)\n", p); + + return ptr; +} + +/*! + *\brief Allocate an autopointer using the passed \a free function to + * free the guarded pointer + */ +GAuto *g_auto_pointer_new_with_free(gpointer p, GFreeFunc free_) +{ + AutoPointer *aptr = g_auto_pointer_new(p); + + aptr->ref->free = free_; + return aptr; +} + +gpointer g_auto_pointer_get_ptr(GAuto *auto_ptr) +{ + return ((AutoPointer *) auto_ptr)->ptr; +} + +/*! + *\brief Copies an auto pointer by. It's mostly not necessary + * to call this function directly, unless you copy/assign + * the guarded pointer. + * + *\param auto_ptr Auto pointer returned by previous call to + * g_auto_pointer_new_XXX() + * + *\return gpointer An auto pointer + */ +GAuto *g_auto_pointer_copy(GAuto *auto_ptr) +{ + AutoPointer *ptr = auto_ptr; + AutoPointerRef *ref = ptr->ref; + AutoPointer *newp = g_new0(AutoPointer, 1); + + newp->ref = ref; + newp->ptr = ref->pointer; + ++(ref->cnt); + + G_PRINT_REF ("XXXX COPY(%lx) -- REF (%d)\n", ref->pointer, ref->cnt); + + return newp; +} + +/*! + *\brief Free an auto pointer + */ +void g_auto_pointer_free(GAuto *auto_ptr) +{ + AutoPointer *ptr = auto_ptr; + AutoPointerRef *ref = ptr->ref; + + if (--(ref->cnt) == 0) { + G_PRINT_REF ("XXXX FREE(%lx) -- REF (%d)\n", ref->pointer, ref->cnt); + ref->free(ref->pointer); + g_free(ref); + } else + G_PRINT_REF ("XXXX DEREF(%lx) -- REF (%d)\n", ref->pointer, ref->cnt); + g_free(ptr); +} + diff --git a/src/common/utils.h b/src/common/utils.h index c854ab45e..faeb7114a 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -25,6 +25,7 @@ #endif #include +#include #include #include #include @@ -477,6 +478,18 @@ GNode *g_node_map(GNode *node, GNodeMapFunc func, gpointer data); gboolean get_hex_value(guchar *out, gchar c1, gchar c2); void get_hex_str(gchar *out, guchar ch); +/* auto pointer for containers that support GType system */ + +#define G_TYPE_AUTO_POINTER g_auto_pointer_register() +typedef struct AutoPointer GAuto; +GType g_auto_pointer_register (void); +GAuto *g_auto_pointer_new (gpointer pointer); +GAuto *g_auto_pointer_new_with_free (gpointer p, + GFreeFunc free); +gpointer g_auto_pointer_get_ptr (GAuto *auto_ptr); +GAuto *g_auto_pointer_copy (GAuto *auto_ptr); +void g_auto_pointer_free (GAuto *auto_ptr); + #ifdef __cplusplus } #endif diff --git a/src/gtk/prefswindow.c b/src/gtk/prefswindow.c index 5149036c6..b52e44ecb 100644 --- a/src/gtk/prefswindow.c +++ b/src/gtk/prefswindow.c @@ -72,21 +72,6 @@ struct _PrefsTreeNode gfloat treeweight; /* GTK2: not used */ }; -static GType G_TYPE_AUTO_POINTER; - -typedef struct AutoPointerRef { - gpointer pointer; - glong cnt; -} AutoPointerRef; - -typedef struct AutoPointer { - AutoPointerRef *ref; -} AutoPointer; - -static gpointer g_auto_pointer_new (gpointer pointer); -static gpointer g_auto_pointer_copy (gpointer p); -static void g_auto_pointer_free (gpointer p); - static GtkTreeStore *prefswindow_create_data_store (void); static GtkWidget *prefswindow_tree_view_create (PrefsWindow* prefswindow); static void prefs_filtering_create_tree_view_columns (GtkWidget *tree_view); @@ -272,7 +257,7 @@ static void prefswindow_build_tree(GtkWidget *tree_view, GSList *prefs_pages) PREFS_PAGE_DATA, &prefs_node, -1); } else { - gpointer autoptr; + GAuto *autoptr; /* create a new top level */ gtk_tree_store_append(store, &child, i == 0 ? NULL : &node); @@ -425,59 +410,8 @@ void prefswindow_open(const gchar *title, GSList *prefs_pages, gpointer data) prefswindow_open_full(title, prefs_pages, data, NULL); } -/* NOTE: auto pointer could be made more generic, but this works - * fine for now. */ - -static gpointer g_auto_pointer_new(gpointer p) -{ - AutoPointerRef *ref = g_new0(AutoPointerRef, 1); - AutoPointer *ptr = g_new0(AutoPointer, 1); - - ref->pointer = p; - ref->cnt = 1; - - ptr->ref = ref; - - return ptr; -} - -static gpointer g_auto_pointer_copy(gpointer p) -{ - AutoPointer *ptr = p; - AutoPointerRef *ref = ptr->ref; - AutoPointer *newp = g_new0(AutoPointer, 1); - newp->ref = ref; - - ++(ref->cnt); - return newp; -} - -static void g_auto_pointer_free(gpointer p) -{ - AutoPointer *ptr = p; - AutoPointerRef *ref = ptr->ref; - - if (--(ref->cnt) == 0) { - g_free(ref->pointer); - g_free(ref); - } - g_free(ptr); -} - -static void prefswindow_static_init(void) -{ - if (!G_TYPE_AUTO_POINTER) - G_TYPE_AUTO_POINTER = - g_boxed_type_register_static("G_TYPE_AUTO_POINTER", - g_auto_pointer_copy, - g_auto_pointer_free); -} - static GtkTreeStore *prefswindow_create_data_store(void) { - /* should always be called before using auto pointer type */ - prefswindow_static_init(); - return gtk_tree_store_new(N_PREFS_PAGE_COLUMNS, G_TYPE_STRING, G_TYPE_POINTER, -- 2.25.1