📄 gobject.c
字号:
#ifdef G_ENABLE_DEBUG IF_DEBUG (OBJECTS) { /* catch objects not chaining finalize handlers */ G_LOCK (debug_objects); g_assert (g_hash_table_lookup (debug_objects_ht, object) == NULL); G_UNLOCK (debug_objects); }#endif /* G_ENABLE_DEBUG */ g_type_free_instance ((GTypeInstance*) object); }}static voidg_object_dispatch_properties_changed (GObject *object, guint n_pspecs, GParamSpec **pspecs){ guint i; for (i = 0; i < n_pspecs; i++) g_signal_emit (object, gobject_signals[NOTIFY], g_quark_from_string (pspecs[i]->name), pspecs[i]);}voidg_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);}voidg_object_freeze_notify (GObject *object){ g_return_if_fail (G_IS_OBJECT (object)); if (!object->ref_count) return; g_object_ref (object); g_object_notify_queue_freeze (object, &property_notify_context); g_object_unref (object);}voidg_object_notify (GObject *object, const gchar *property_name){ GParamSpec *pspec; g_return_if_fail (G_IS_OBJECT (object)); g_return_if_fail (property_name != NULL); if (!object->ref_count) return; g_object_ref (object); pspec = g_param_spec_pool_lookup (pspec_pool, property_name, G_OBJECT_TYPE (object), TRUE); if (!pspec) g_warning ("%s: object class `%s' has no property named `%s'", G_STRLOC, G_OBJECT_TYPE_NAME (object), property_name); else { GObjectNotifyQueue *nqueue = g_object_notify_queue_freeze (object, &property_notify_context); g_object_notify_queue_add (object, nqueue, pspec); g_object_notify_queue_thaw (object, nqueue); } g_object_unref (object);}voidg_object_thaw_notify (GObject *object){ GObjectNotifyQueue *nqueue; g_return_if_fail (G_IS_OBJECT (object)); if (!object->ref_count) return; g_object_ref (object); nqueue = g_object_notify_queue_from_object (object, &property_notify_context); if (!nqueue || !nqueue->freeze_count) g_warning (G_STRLOC ": property-changed notification for %s(%p) is not frozen", G_OBJECT_TYPE_NAME (object), object); else g_object_notify_queue_thaw (object, nqueue); g_object_unref (object);}static inline voidobject_get_property (GObject *object, GParamSpec *pspec, GValue *value){ GObjectClass *class = g_type_class_peek (pspec->owner_type); class->get_property (object, PARAM_SPEC_PARAM_ID (pspec), value, pspec);}static inline voidobject_set_property (GObject *object, GParamSpec *pspec, const GValue *value, GObjectNotifyQueue *nqueue){ GValue tmp_value = { 0, }; GObjectClass *class = g_type_class_peek (pspec->owner_type); /* provide a copy to work from, convert (if necessary) and validate */ g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec)); if (!g_value_transform (value, &tmp_value)) g_warning ("unable to set property `%s' of type `%s' from value of type `%s'", pspec->name, g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)), G_VALUE_TYPE_NAME (value)); else if (g_param_value_validate (pspec, &tmp_value) && !(pspec->flags & G_PARAM_LAX_VALIDATION)) { gchar *contents = g_strdup_value_contents (value); g_warning ("value \"%s\" of type `%s' is invalid for property `%s' of type `%s'", contents, G_VALUE_TYPE_NAME (value), pspec->name, g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec))); g_free (contents); } else { class->set_property (object, PARAM_SPEC_PARAM_ID (pspec), &tmp_value, pspec); g_object_notify_queue_add (object, nqueue, pspec); } g_value_unset (&tmp_value);}gpointerg_object_new (GType object_type, const gchar *first_property_name, ...){ GObject *object; va_list var_args; g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL); va_start (var_args, first_property_name); object = g_object_new_valist (object_type, first_property_name, var_args); va_end (var_args); return object;}gpointerg_object_newv (GType object_type, guint n_parameters, GParameter *parameters){ GObjectConstructParam *cparams, *oparams; GObjectNotifyQueue *nqueue; GObject *object; GObjectClass *class; GSList *slist; guint n_total_cparams = 0, n_cparams = 0, n_oparams = 0, n_cvalues; GValue *cvalues; GList *clist = NULL; guint i; g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL); class = g_type_class_ref (object_type); for (slist = class->construct_properties; slist; slist = slist->next) { clist = g_list_prepend (clist, slist->data); n_total_cparams += 1; } /* collect parameters, sort into construction and normal ones */ oparams = g_new (GObjectConstructParam, n_parameters); cparams = g_new (GObjectConstructParam, n_total_cparams); for (i = 0; i < n_parameters; i++) { GValue *value = ¶meters[i].value; GParamSpec *pspec = g_param_spec_pool_lookup (pspec_pool, parameters[i].name, object_type, TRUE); if (!pspec) { g_warning ("%s: object class `%s' has no property named `%s'", G_STRLOC, g_type_name (object_type), parameters[i].name); continue; } if (!(pspec->flags & G_PARAM_WRITABLE)) { g_warning ("%s: property `%s' of object class `%s' is not writable", G_STRLOC, pspec->name, g_type_name (object_type)); continue; } if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY)) { GList *list = g_list_find (clist, pspec); if (!list) { g_warning (G_STRLOC ": construct property \"%s\" for object `%s' can't be set twice", pspec->name, g_type_name (object_type)); continue; } cparams[n_cparams].pspec = pspec; cparams[n_cparams].value = value; n_cparams++; if (!list->prev) clist = list->next; else list->prev->next = list->next; if (list->next) list->next->prev = list->prev; g_list_free_1 (list); } else { oparams[n_oparams].pspec = pspec; oparams[n_oparams].value = value; n_oparams++; } } /* set remaining construction properties to default values */ n_cvalues = n_total_cparams - n_cparams; cvalues = g_new (GValue, n_cvalues); while (clist) { GList *tmp = clist->next; GParamSpec *pspec = clist->data; GValue *value = cvalues + n_total_cparams - n_cparams - 1; value->g_type = 0; g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec)); g_param_value_set_default (pspec, value); cparams[n_cparams].pspec = pspec; cparams[n_cparams].value = value; n_cparams++; g_list_free_1 (clist); clist = tmp; } /* construct object from construction parameters */ object = class->constructor (object_type, n_total_cparams, cparams); /* free construction values */ g_free (cparams); while (n_cvalues--) g_value_unset (cvalues + n_cvalues); g_free (cvalues); /* release g_object_init() notification queue freeze_count */ nqueue = g_object_notify_queue_freeze (object, &property_notify_context); g_object_notify_queue_thaw (object, nqueue); /* set remaining properties */ for (i = 0; i < n_oparams; i++) object_set_property (object, oparams[i].pspec, oparams[i].value, nqueue); g_free (oparams); g_type_class_unref (class); /* release our own freeze count and handle notifications */ g_object_notify_queue_thaw (object, nqueue); return object;}GObject*g_object_new_valist (GType object_type, const gchar *first_property_name, va_list var_args){ GObjectClass *class; GParameter *params; const gchar *name; GObject *object; guint n_params = 0, n_alloced_params = 16; g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL); if (!first_property_name) return g_object_newv (object_type, 0, NULL); class = g_type_class_ref (object_type); params = g_new (GParameter, n_alloced_params); name = first_property_name; while (name) { gchar *error = NULL; GParamSpec *pspec = g_param_spec_pool_lookup (pspec_pool, name, object_type, TRUE); if (!pspec) { g_warning ("%s: object class `%s' has no property named `%s'", G_STRLOC, g_type_name (object_type), name); break; } if (n_params >= n_alloced_params) { n_alloced_params += 16; params = g_renew (GParameter, params, n_alloced_params); } params[n_params].name = name; params[n_params].value.g_type = 0; g_value_init (¶ms[n_params].value, G_PARAM_SPEC_VALUE_TYPE (pspec)); G_VALUE_COLLECT (¶ms[n_params].value, var_args, 0, &error); if (error) { g_warning ("%s: %s", G_STRLOC, error); g_free (error); /* we purposely leak the value here, it might not be * in a sane state if an error condition occoured */ break; } n_params++; name = va_arg (var_args, gchar*); } object = g_object_newv (object_type, n_params, params); while (n_params--) g_value_unset (¶ms[n_params].value); g_free (params); g_type_class_unref (class); return object;}static GObject*g_object_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_params){ GObject *object; /* create object */ object = (GObject*) g_type_create_instance (type); /* set construction parameters */ if (n_construct_properties) { GObjectNotifyQueue *nqueue = g_object_notify_queue_freeze (object, &property_notify_context); /* set construct properties */ while (n_construct_properties--) { GValue *value = construct_params->value; GParamSpec *pspec = construct_params->pspec; construct_params++; object_set_property (object, pspec, value, nqueue); } g_object_notify_queue_thaw (object, nqueue); /* the notification queue is still frozen from g_object_init(), so * we don't need to handle it here, g_object_newv() takes * care of that */ } return object;}voidg_object_set_valist (GObject *object, const gchar *first_property_name, va_list var_args){ GObjectNotifyQueue *nqueue; const gchar *name; g_return_if_fail (G_IS_OBJECT (object)); g_object_ref (object); nqueue = g_object_notify_queue_freeze (object, &property_notify_context); name = first_property_name; while (name) { GValue value = { 0, }; GParamSpec *pspec; gchar *error = NULL; pspec = g_param_spec_pool_lookup (pspec_pool, name, G_OBJECT_TYPE (object), TRUE); if (!pspec) { g_warning ("%s: object class `%s' has no property named `%s'", G_STRLOC, G_OBJECT_TYPE_NAME (object), name); break; } if (!(pspec->flags & G_PARAM_WRITABLE)) { g_warning ("%s: property `%s' of object class `%s' is not writable", G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (object)); break; } g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)); G_VALUE_COLLECT (&value, var_args, 0, &error); if (error) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -