/* closure: a GClosure return_value: a GValue to store the return value. May be NULL if the callback of closure doesn't return a value. n_param_values: the length of the param_values array param_values: an array of GValues holding the arguments on which to invoke the callback of closure invocation_hint: a context-dependent invocation hint */ void g_closure_invoke (GClosure *closure, GValue /*out*/ *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint) { /* 设置状态防止重入 */ closure->ref_count += 1; closure->in_marshal = TRUE; // 得到marshal的指针 if (closure->meta_marshal) { marshal_data = closure->notifiers[0].data; marshal = (GClosureMarshal) closure->notifiers[0].notify; } else { marshal_data = NULL; marshal = closure->marshal; } /* 分别调用 pre-notifer marshal post-notifier */ closure_invoke_notifiers (closure, PRE_NOTIFY); marshal (closure, return_value, n_param_values, param_values, invocation_hint, marshal_data); closure_invoke_notifiers (closure, POST_NOTIFY); // 恢复重入状态 closure->in_marshal = in_marshal; g_closure_unref (closure); }
/** * g_closure_invoke: * @closure: a #GClosure * @return_value: a #GValue to store the return value. May be %NULL if the * callback of @closure doesn't return a value. * @n_param_values: the length of the @param_values array * @param_values: (array length=n_param_values): an array of * #GValue<!-- -->s holding the arguments on which to * invoke the callback of @closure * @invocation_hint: a context-dependent invocation hint * * Invokes the closure, i.e. executes the callback represented by the @closure. */ void g_closure_invoke (GClosure *closure, GValue /*out*/ *return_value, guint n_param_values, const GValue *param_values, gpointer invocation_hint) { g_return_if_fail (closure != NULL); g_closure_ref (closure); /* preserve floating flag */ if (!closure->is_invalid) { GClosureMarshal marshal; gpointer marshal_data; gboolean in_marshal = closure->in_marshal; g_return_if_fail (closure->marshal || closure->meta_marshal); SET (closure, in_marshal, TRUE); if (closure->meta_marshal) { marshal_data = closure->notifiers[0].data; marshal = (GClosureMarshal) closure->notifiers[0].notify; } else { marshal_data = NULL; marshal = closure->marshal; } if (!in_marshal) closure_invoke_notifiers (closure, PRE_NOTIFY); marshal (closure, return_value, n_param_values, param_values, invocation_hint, marshal_data); if (!in_marshal) closure_invoke_notifiers (closure, POST_NOTIFY); SET (closure, in_marshal, in_marshal); } g_closure_unref (closure); }
void g_closure_invalidate (GClosure *closure) { g_return_if_fail (closure != NULL); if (!closure->is_invalid) { closure->ref_count += 1; /* preserve floating flag */ closure->is_invalid = TRUE; closure_invoke_notifiers (closure, INOTIFY); g_closure_unref (closure); } }
/** * g_closure_invalidate: * @closure: GClosure to invalidate * * Sets a flag on the closure to indicate that its calling * environment has become invalid, and thus causes any future * invocations of g_closure_invoke() on this @closure to be * ignored. Also, invalidation notifiers installed on the closure will * be called at this point. Note that unless you are holding a * reference to the closure yourself, the invalidation notifiers may * unref the closure and cause it to be destroyed, so if you need to * access the closure after calling g_closure_invalidate(), make sure * that you've previously called g_closure_ref(). * * Note that g_closure_invalidate() will also be called when the * reference count of a closure drops to zero (unless it has already * been invalidated before). */ void g_closure_invalidate (GClosure *closure) { g_return_if_fail (closure != NULL); if (!closure->is_invalid) { gboolean was_invalid; g_closure_ref (closure); /* preserve floating flag */ SWAP (closure, is_invalid, TRUE, &was_invalid); /* invalidate only once */ if (!was_invalid) closure_invoke_notifiers (closure, INOTIFY); g_closure_unref (closure); } }
void g_closure_unref (GClosure *closure) { g_return_if_fail (closure != NULL); g_return_if_fail (closure->ref_count > 0); if (closure->ref_count == 1) /* last unref, invalidate first */ g_closure_invalidate (closure); closure->ref_count -= 1; if (closure->ref_count == 0) { closure_invoke_notifiers (closure, FNOTIFY); g_free (closure->notifiers); g_free (closure); } }
/** * g_closure_unref: * @closure: #GClosure to decrement the reference count on * * Decrements the reference count of a closure after it was previously * incremented by the same caller. If no other callers are using the * closure, then the closure will be destroyed and freed. */ void g_closure_unref (GClosure *closure) { guint new_ref_count; g_return_if_fail (closure != NULL); g_return_if_fail (closure->ref_count > 0); if (closure->ref_count == 1) /* last unref, invalidate first */ g_closure_invalidate (closure); DEC_ASSIGN (closure, ref_count, &new_ref_count); if (new_ref_count == 0) { closure_invoke_notifiers (closure, FNOTIFY); g_free (closure->notifiers); g_free (closure); } }