Commit 69f32ba7 authored by Tim Janik's avatar Tim Janik Committed by Tim Janik

added g_list_insert_before().

Sat Jun 30 23:14:32 2001  Tim Janik  <timj@gtk.org>

        * glib/glist.[hc]: added g_list_insert_before().

        * glib/gslist.c (g_slist_insert_before): provide an implementation,
        prototype was already present...

Sat Jun 30 11:07:00 2001  Tim Janik  <timj@gtk.org>

        * gobject.[hc]: provide weak_ref/weak_unref functions,
        invoked from ->dispose. renamed ->shutdown() to ->dispose(),
        provide "public" API entry here: g_object_run_dispose(), this
        fucntion should _only_ be called from object system implementations
        (e.g. gtkobject.c) if at all.

        * gtypemodule.c (g_type_module_dispose): s/shutdown/dispose/

        * gsignal.h: removed compat aliases.

        * gobject.c (g_object_connect): support data objects.
parent 4f96a13c
Sat Jun 30 23:14:32 2001 Tim Janik <timj@gtk.org>
* glib/glist.[hc]: added g_list_insert_before().
* glib/gslist.c (g_slist_insert_before): provide an implementation,
prototype was already present...
Sun Jul 1 20:16:25 2001 Owen Taylor <otaylor@redhat.com>
* glib/guniprop.c (g_unichar_totitle): Use G_N_ELEMENTS
......
Sat Jun 30 23:14:32 2001 Tim Janik <timj@gtk.org>
* glib/glist.[hc]: added g_list_insert_before().
* glib/gslist.c (g_slist_insert_before): provide an implementation,
prototype was already present...
Sun Jul 1 20:16:25 2001 Owen Taylor <otaylor@redhat.com>
* glib/guniprop.c (g_unichar_totitle): Use G_N_ELEMENTS
......
Sat Jun 30 23:14:32 2001 Tim Janik <timj@gtk.org>
* glib/glist.[hc]: added g_list_insert_before().
* glib/gslist.c (g_slist_insert_before): provide an implementation,
prototype was already present...
Sun Jul 1 20:16:25 2001 Owen Taylor <otaylor@redhat.com>
* glib/guniprop.c (g_unichar_totitle): Use G_N_ELEMENTS
......
Sat Jun 30 23:14:32 2001 Tim Janik <timj@gtk.org>
* glib/glist.[hc]: added g_list_insert_before().
* glib/gslist.c (g_slist_insert_before): provide an implementation,
prototype was already present...
Sun Jul 1 20:16:25 2001 Owen Taylor <otaylor@redhat.com>
* glib/guniprop.c (g_unichar_totitle): Use G_N_ELEMENTS
......
Sat Jun 30 23:14:32 2001 Tim Janik <timj@gtk.org>
* glib/glist.[hc]: added g_list_insert_before().
* glib/gslist.c (g_slist_insert_before): provide an implementation,
prototype was already present...
Sun Jul 1 20:16:25 2001 Owen Taylor <otaylor@redhat.com>
* glib/guniprop.c (g_unichar_totitle): Use G_N_ELEMENTS
......
Sat Jun 30 23:14:32 2001 Tim Janik <timj@gtk.org>
* glib/glist.[hc]: added g_list_insert_before().
* glib/gslist.c (g_slist_insert_before): provide an implementation,
prototype was already present...
Sun Jul 1 20:16:25 2001 Owen Taylor <otaylor@redhat.com>
* glib/guniprop.c (g_unichar_totitle): Use G_N_ELEMENTS
......
Sat Jun 30 23:14:32 2001 Tim Janik <timj@gtk.org>
* glib/glist.[hc]: added g_list_insert_before().
* glib/gslist.c (g_slist_insert_before): provide an implementation,
prototype was already present...
Sun Jul 1 20:16:25 2001 Owen Taylor <otaylor@redhat.com>
* glib/guniprop.c (g_unichar_totitle): Use G_N_ELEMENTS
......
Sat Jun 30 23:14:32 2001 Tim Janik <timj@gtk.org>
* glib/glist.[hc]: added g_list_insert_before().
* glib/gslist.c (g_slist_insert_before): provide an implementation,
prototype was already present...
Sun Jul 1 20:16:25 2001 Owen Taylor <otaylor@redhat.com>
* glib/guniprop.c (g_unichar_totitle): Use G_N_ELEMENTS
......
......@@ -61,6 +61,23 @@
@closure:
@Returns:
<!-- ##### MACRO g_signal_newc ##### -->
<para>
</para>
@Returns:
@signal_name:
@itype:
@signal_flags:
@class_offset:
@accumulator:
@accu_data:
@c_marshaller:
@return_type:
@n_params:
@Varargs:
<!-- ##### FUNCTION g_type_value_is_a ##### -->
<para>
Determines if @value is a #GValue whose type conforms to @type.
......
......@@ -207,25 +207,6 @@ filled in by the g_signal_query() function.
<!-- ##### MACRO g_signal_newc ##### -->
<para>
</para>
@Returns:
<!-- # Unused Parameters # -->
@signal_name:
@itype:
@signal_flags:
@class_offset:
@accumulator:
@accu_data:
@c_marshaller:
@return_type:
@n_params:
@Varargs:
<!-- ##### FUNCTION g_signal_newv ##### -->
<para>
......
......@@ -317,6 +317,56 @@ g_list_insert (GList *list,
return list;
}
GList*
g_list_insert_before (GList *list,
GList *sibling,
gpointer data)
{
if (!list)
{
list = g_list_alloc ();
list->data = data;
g_return_val_if_fail (sibling == NULL, list);
return list;
}
else if (sibling)
{
GList *node;
node = g_list_alloc ();
node->data = data;
if (sibling->prev)
{
node->prev = sibling->prev;
node->prev->next = node;
node->next = sibling;
sibling->prev = node;
return list;
}
else
{
node->next = sibling;
sibling->prev = node;
g_return_val_if_fail (sibling == list, node);
return node;
}
}
else
{
GList *last;
last = list;
while (last->next)
last = last->next;
last->next = g_list_alloc ();
last->next->data = data;
last->next->prev = last;
return list;
}
}
GList *
g_list_concat (GList *list1, GList *list2)
{
......
......@@ -57,6 +57,9 @@ GList* g_list_insert (GList *list,
GList* g_list_insert_sorted (GList *list,
gpointer data,
GCompareFunc func);
GList* g_list_insert_before (GList *list,
GList *sibling,
gpointer data);
GList* g_list_concat (GList *list1,
GList *list2);
GList* g_list_remove (GList *list,
......
......@@ -307,6 +307,45 @@ g_slist_insert (GSList *list,
return list;
}
GSList*
g_slist_insert_before (GSList *slist,
GSList *sibling,
gpointer data)
{
if (!slist)
{
slist = g_slist_alloc ();
slist->data = data;
g_return_val_if_fail (sibling == NULL, slist);
return slist;
}
else
{
GSList *node, *last = NULL;
for (node = slist; node; last = node, node = last->next)
if (node == sibling)
break;
if (!last)
{
node = g_slist_alloc ();
node->data = data;
node->next = slist;
return node;
}
else
{
node = g_slist_alloc ();
node->data = data;
node->next = last->next;
last->next = node;
return slist;
}
}
}
GSList *
g_slist_concat (GSList *list1, GSList *list2)
{
......
Sat Jun 30 11:07:00 2001 Tim Janik <timj@gtk.org>
* gobject.[hc]: provide weak_ref/weak_unref functions,
invoked from ->dispose. renamed ->shutdown() to ->dispose(),
provide "public" API entry here: g_object_run_dispose(), this
fucntion should _only_ be called from object system implementations
(e.g. gtkobject.c) if at all.
* gtypemodule.c (g_type_module_dispose): s/shutdown/dispose/
* gsignal.h: removed compat aliases.
* gobject.c (g_object_connect): support data objects.
Sat Jun 30 13:17:12 2001 Owen Taylor <otaylor@redhat.com>
* testgruntime.c (test_object_class_init)
......
......@@ -61,7 +61,7 @@ static GObject* g_object_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_params);
static void g_object_last_unref (GObject *object);
static void g_object_shutdown (GObject *object);
static void g_object_real_dispose (GObject *object);
static void g_object_finalize (GObject *object);
static void g_object_do_set_property (GObject *object,
guint property_id,
......@@ -103,6 +103,7 @@ static inline void object_set_property (GObject *object,
/* --- variables --- */
static GQuark quark_closure_array = 0;
static GQuark quark_weak_refs = 0;
static GParamSpecPool *pspec_pool = NULL;
static GObjectNotifyContext property_notify_context = { 0, };
static gulong gobject_signals[LAST_SIGNAL] = { 0, };
......@@ -133,11 +134,8 @@ debug_objects_atexit (void)
IF_DEBUG (OBJECTS)
{
G_LOCK (debug_objects);
if (debug_objects_ht)
{
g_message ("stale GObjects: %u", debug_objects_count);
g_hash_table_foreach (debug_objects_ht, debug_objects_foreach, NULL);
}
g_message ("stale GObjects: %u", debug_objects_count);
g_hash_table_foreach (debug_objects_ht, debug_objects_foreach, NULL);
G_UNLOCK (debug_objects);
}
}
......@@ -186,7 +184,10 @@ g_object_type_init (void) /* sync with gtype.c */
#ifdef G_ENABLE_DEBUG
IF_DEBUG (OBJECTS)
g_atexit (debug_objects_atexit);
{
debug_objects_ht = g_hash_table_new (g_direct_hash, NULL);
g_atexit (debug_objects_atexit);
}
#endif /* G_ENABLE_DEBUG */
}
......@@ -236,6 +237,7 @@ static void
g_object_do_class_init (GObjectClass *class)
{
quark_closure_array = g_quark_from_static_string ("GObject-closure-array");
quark_weak_refs = g_quark_from_static_string ("GObject-weak-references");
pspec_pool = g_param_spec_pool_new (TRUE);
property_notify_context.quark_notify_queue = g_quark_from_static_string ("GObject-notify-queue");
property_notify_context.dispatcher = g_object_notify_dispatcher;
......@@ -243,7 +245,7 @@ g_object_do_class_init (GObjectClass *class)
class->constructor = g_object_constructor;
class->set_property = g_object_do_set_property;
class->get_property = g_object_do_get_property;
class->shutdown = g_object_shutdown;
class->dispose = g_object_real_dispose;
class->finalize = g_object_finalize;
class->dispatch_properties_changed = g_object_dispatch_properties_changed;
class->notify = NULL;
......@@ -344,8 +346,6 @@ g_object_init (GObject *object)
IF_DEBUG (OBJECTS)
{
G_LOCK (debug_objects);
if (!debug_objects_ht)
debug_objects_ht = g_hash_table_new (g_direct_hash, NULL);
debug_objects_count++;
g_hash_table_insert (debug_objects_ht, object, object);
G_UNLOCK (debug_objects);
......@@ -381,13 +381,47 @@ g_object_do_get_property (GObject *object,
}
}
static void
g_object_real_dispose (GObject *object)
{
guint ref_count;
g_signal_handlers_destroy (object);
g_datalist_id_set_data (&object->qdata, quark_closure_array, NULL);
/* yes, temporarily altering the ref_count is hackish, but that
* enforces people not jerking around with weak_ref notifiers
*/
ref_count = object->ref_count;
object->ref_count = 0;
g_datalist_id_set_data (&object->qdata, quark_weak_refs, NULL);
object->ref_count = ref_count;
}
static void
g_object_finalize (GObject *object)
{
g_datalist_clear (&object->qdata);
#ifdef G_ENABLE_DEBUG
IF_DEBUG (OBJECTS)
{
G_LOCK (debug_objects);
g_assert (g_hash_table_lookup (debug_objects_ht, object) == object);
g_hash_table_remove (debug_objects_ht, object);
debug_objects_count--;
G_UNLOCK (debug_objects);
}
#endif /* G_ENABLE_DEBUG */
}
static void
g_object_last_unref (GObject *object)
{
g_return_if_fail (object->ref_count > 0);
if (object->ref_count == 1) /* may have been re-referenced meanwhile */
G_OBJECT_GET_CLASS (object)->shutdown (object);
G_OBJECT_GET_CLASS (object)->dispose (object);
#ifdef G_ENABLE_DEBUG
if (g_trap_object_ref == object)
......@@ -398,15 +432,14 @@ g_object_last_unref (GObject *object)
if (object->ref_count == 0) /* may have been re-referenced meanwhile */
{
g_signal_handlers_destroy (object);
g_object_set_qdata (object, quark_closure_array, NULL);
g_datalist_id_set_data (&object->qdata, quark_weak_refs, NULL);
G_OBJECT_GET_CLASS (object)->finalize (object);
#ifdef G_ENABLE_DEBUG
IF_DEBUG (OBJECTS)
{
/* catch objects not chaining finalize handlers */
G_LOCK (debug_objects);
if (debug_objects_ht)
g_assert (g_hash_table_lookup (debug_objects_ht, object) == NULL);
g_assert (g_hash_table_lookup (debug_objects_ht, object) == NULL);
G_UNLOCK (debug_objects);
}
#endif /* G_ENABLE_DEBUG */
......@@ -414,33 +447,6 @@ g_object_last_unref (GObject *object)
}
}
static void
g_object_shutdown (GObject *object)
{
/* this function needs to be always present for unconditional
* chaining, we also might add some code here later.
* beware though, subclasses may invoke shutdown() arbitrarily.
*/
}
static void
g_object_finalize (GObject *object)
{
g_signal_handlers_destroy (object);
g_datalist_clear (&object->qdata);
#ifdef G_ENABLE_DEBUG
IF_DEBUG (OBJECTS)
{
G_LOCK (debug_objects);
g_assert (g_hash_table_lookup (debug_objects_ht, object) == object);
g_hash_table_remove (debug_objects_ht, object);
debug_objects_count--;
G_UNLOCK (debug_objects);
}
#endif /* G_ENABLE_DEBUG */
}
static void
g_object_dispatch_properties_changed (GObject *object,
guint n_pspecs,
......@@ -452,6 +458,17 @@ g_object_dispatch_properties_changed (GObject *object,
g_signal_emit (object, gobject_signals[NOTIFY], g_quark_from_string (pspecs[i]->name), pspecs[i]);
}
void
g_object_run_dispose (GObject *object)
{
g_return_if_fail (G_IS_OBJECT (object));
g_return_if_fail (object->ref_count > 0);
g_object_ref (object);
G_OBJECT_GET_CLASS (object)->dispose (object);
g_object_unref (object);
}
void
g_object_freeze_notify (GObject *object)
{
......@@ -1068,24 +1085,40 @@ g_object_connect (gpointer _object,
{
gpointer callback = va_arg (var_args, gpointer);
gpointer data = va_arg (var_args, gpointer);
guint sid;
gulong sid;
if (strncmp (signal_spec, "signal::", 8) == 0)
sid = g_signal_connect_data (object, signal_spec + 8,
callback, data, NULL,
0);
else if (strncmp (signal_spec, "object_signal::", 15) == 0)
sid = g_signal_connect_object (object, signal_spec + 15,
callback, data,
0);
else if (strncmp (signal_spec, "swapped_signal::", 16) == 0)
sid = g_signal_connect_data (object, signal_spec + 16,
callback, data, NULL,
G_CONNECT_SWAPPED);
else if (strncmp (signal_spec, "swapped_object_signal::", 23) == 0)
sid = g_signal_connect_object (object, signal_spec + 23,
callback, data,
G_CONNECT_SWAPPED);
else if (strncmp (signal_spec, "signal_after::", 14) == 0)
sid = g_signal_connect_data (object, signal_spec + 14,
callback, data, NULL,
G_CONNECT_AFTER);
else if (strncmp (signal_spec, "object_signal_after::", 21) == 0)
sid = g_signal_connect_object (object, signal_spec + 21,
callback, data,
G_CONNECT_AFTER);
else if (strncmp (signal_spec, "swapped_signal_after::", 22) == 0)
sid = g_signal_connect_data (object, signal_spec + 22,
callback, data, NULL,
G_CONNECT_SWAPPED | G_CONNECT_AFTER);
else if (strncmp (signal_spec, "swapped_object_signal_after::", 29) == 0)
sid = g_signal_connect_object (object, signal_spec + 29,
callback, data,
G_CONNECT_SWAPPED | G_CONNECT_AFTER);
else
{
g_warning ("%s: invalid signal spec \"%s\"", G_STRLOC, signal_spec);
......@@ -1146,6 +1179,88 @@ g_object_disconnect (gpointer _object,
return object;
}
typedef struct {
guint n_weak_refs;
struct {
GWeakNotify notify;
gpointer data;
} weak_refs[1]; /* flexible array */
} WeakRefStack;
static void
weak_refs_notify (gpointer data)
{
WeakRefStack *wstack = data;
guint i;
for (i = 0; i < wstack->n_weak_refs; i++)
wstack->weak_refs[i].notify (wstack->weak_refs[i].data);
g_free (wstack);
}
void
g_object_weak_ref (GObject *object,
GWeakNotify notify,
gpointer data)
{
WeakRefStack *wstack;
guint i;
g_return_if_fail (G_IS_OBJECT (object));
g_return_if_fail (notify != NULL);
g_return_if_fail (object->ref_count >= 1);
wstack = g_datalist_id_remove_no_notify (&object->qdata, quark_weak_refs);
if (wstack)
{
i = wstack->n_weak_refs++;
wstack = g_realloc (wstack, sizeof (*wstack) + sizeof (wstack->weak_refs[0]) * i);
}
else
{
wstack = g_renew (WeakRefStack, NULL, 1);
wstack->n_weak_refs = 1;
i = wstack->n_weak_refs;
}
wstack->weak_refs[i].notify = notify;
wstack->weak_refs[i].data = data;
g_datalist_id_set_data_full (&object->qdata, quark_weak_refs, wstack, weak_refs_notify);
}
void
g_object_weak_unref (GObject *object,
GWeakNotify notify,
gpointer data)
{
WeakRefStack *wstack;
gboolean found_one = FALSE;
g_return_if_fail (G_IS_OBJECT (object));
g_return_if_fail (notify != NULL);
wstack = g_datalist_id_get_data (&object->qdata, quark_weak_refs);
if (wstack)
{
guint i;
for (i = 0; i < wstack->n_weak_refs; i++)
if (wstack->weak_refs[i].notify == notify &&
wstack->weak_refs[i].data == data)
{
found_one = TRUE;
wstack->n_weak_refs -= 1;
if (i != wstack->n_weak_refs)
{
wstack->weak_refs[i].notify = wstack->weak_refs[wstack->n_weak_refs].notify;
wstack->weak_refs[i].data = wstack->weak_refs[wstack->n_weak_refs].data;
}
break;
}
}
if (!found_one)
g_warning (G_STRLOC ": couldn't find weak ref %p(%p)", notify, data);
}
gpointer
g_object_ref (gpointer _object)
{
......@@ -1482,6 +1597,7 @@ g_object_watch_closure (GObject *object,
GClosure *closure)
{
CArray *carray;
guint i;
g_return_if_fail (G_IS_OBJECT (object));
g_return_if_fail (closure != NULL);
......@@ -1493,23 +1609,21 @@ g_object_watch_closure (GObject *object,
g_closure_add_marshal_guards (closure,
object, (GClosureNotify) g_object_ref,
object, (GClosureNotify) g_object_unref);
carray = g_object_steal_qdata (object, quark_closure_array);
carray = g_datalist_id_remove_no_notify (&object->qdata, quark_closure_array);
if (!carray)
{
carray = g_renew (CArray, NULL, 1);
carray->object = object;
carray->n_closures = 1;
carray->closures[0] = closure;
g_object_set_qdata_full (object, quark_closure_array, carray, destroy_closure_array);
i = carray->n_closures;
}
else
{
guint i = carray->n_closures++;
i = carray->n_closures++;
carray = g_realloc (carray, sizeof (*carray) + sizeof (carray->closures[0]) * i);
carray->closures[i] = closure;
g_object_set_qdata_full (object, quark_closure_array, carray, destroy_closure_array);
}
carray->closures[i] = closure;
g_datalist_id_set_data_full (&object->qdata, quark_closure_array, carray, destroy_closure_array);
}
GClosure*
......
......@@ -54,6 +54,7 @@ typedef void (*GObjectSetPropertyFunc) (GObject *object,
const GValue *value,
GParamSpec *pspec);
typedef void (*GObjectFinalizeFunc) (GObject *object);
typedef void (*GWeakNotify) (gpointer data);
struct _GObject
{
GTypeInstance g_type_instance;
......@@ -73,17 +74,17 @@ struct _GObjectClass
GObject* (*constructor) (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties);
void (*set_property) (GObject *object,
void (*set_property) (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
void (*get_property) (GObject *object,
void (*get_property) (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
void (*shutdown) (GObject *object);
void (*finalize) (GObject *object);
void (*dispose) (GObject *object);
void (*finalize) (GObject *object);
/* seldomly overidden */
void (*dispatch_properties_changed) (GObject *object,
guint n_pspecs,
......@@ -147,6 +148,12 @@ void g_object_notify (GObject *object,
void g_object_thaw_notify (GObject *object);
gpointer g_object_ref (gpointer object);
void g_object_unref (gpointer object);
void g_object_weak_ref (GObject *object,
GWeakNotify notify,
gpointer data);
void g_object_weak_unref (GObject *object,
GWeakNotify notify,
gpointer data);
gpointer g_object_get_qdata (GObject *object,
GQuark quark);
void g_object_set_qdata (GObject *object,
......@@ -188,6 +195,10 @@ guint g_signal_connect_object (gpointer instance,
GConnectFlags connect_flags);
/*< protected >*/
void g_object_run_dispose (GObject *object);
/* --- implementation macros --- */
#define G_OBJECT_WARN_INVALID_PSPEC(object, pname, property_id, pspec) \
G_STMT_START { \
......
......@@ -238,15 +238,6 @@ guint g_signal_handlers_disconnect_matched (gpointer instance,
g_signal_handlers_unblock_matched ((instance), G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, \
0, 0, NULL, (func), (data))
#ifndef G_DISABLE_COMPAT
/* tmp compat, to be nuked soon */
#define g_signal_connectc(instance, detailed_signal, c_handler, data, swapped) \
g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, (swapped)?G_CONNECT_SWAPPED:0);
#define g_signal_newc g_signal_new
#define g_signal_disconnect_by_func g_signal_handlers_disconnect_by_func
#define g_signal_block_by_func g_signal_handlers_block_by_func
#define g_signal_unblock_by_func g_signal_handlers_unblock_by_func
#endif
/*< private >*/
void g_signal_handlers_destroy (gpointer instance);
......
......@@ -171,7 +171,7 @@ struct _GTypeQuery
#define G_TYPE_FROM_INTERFACE(g_iface) (((GTypeInterface*) (g_iface))->g_type)
/* debug flags for g_type_init() */
/* debug flags for g_type_init_with_debug_flags() */
typedef enum /*< skip >*/
{
G_TYPE_DEBUG_NONE = 0,
......
......@@ -51,21 +51,21 @@ static void g_type_module_complete_interface_info (GTypePlugin *plugin,
GType interface_type,
GInterfaceInfo *info);
static GObjectClass *parent_class;
static gpointer parent_class = NULL;
static void
g_type_module_shutdown (GObject *object)
g_type_module_dispose (GObject *object)
{
GTypeModule *module = G_TYPE_MODULE (object);
if (module->type_infos || module->interface_infos)
{
g_warning (G_STRLOC ": shutdown should never happen for static type plugins once types or interfaces have been registered");
g_warning (G_STRLOC ": unsolicitated invocation of g_object_dispose() on GTypeModule");
g_object_ref (object);
}
parent_class->shutdown (object);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
......@@ -75,7 +75,7 @@ g_type_module_finalize (GObject *object)