[gjs] object: Use template-based definitions for signal action functions
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs] object: Use template-based definitions for signal action functions
- Date: Sat, 8 Aug 2020 19:44:08 +0000 (UTC)
commit 388609bc9e2cbd5b4db47aa56a62b51e1292f469
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date: Mon May 11 18:34:31 2020 +0200
object: Use template-based definitions for signal action functions
We've quite a lot of code generated via a macro to just repeat the same
actions actions for signals, where the only difference is the match
function used (and some debugging data), reduce the number of functions
by just using two template-functions that do the same thing but that use
a different match function, passed via template.
Use the match function also to compute the debugging string
gi/object.cpp | 151 +++++++++++++++++++++++++++++++++-------------------------
gi/object.h | 21 ++++----
2 files changed, 94 insertions(+), 78 deletions(-)
---
diff --git a/gi/object.cpp b/gi/object.cpp
index d9a946cd..c8fcad74 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -2103,64 +2103,80 @@ bool ObjectInstance::signal_find_impl(JSContext* cx, const JS::CallArgs& args) {
return true;
}
-#define DEFINE_SIGNAL_MATCH_METHOD(action) \
- bool ObjectBase::signals_##action(JSContext* cx, unsigned argc, \
- JS::Value* vp) { \
- GJS_GET_WRAPPER_PRIV(cx, argc, vp, args, obj, ObjectBase, priv); \
- if (!priv->check_is_instance(cx, #action " signal")) { \
- return false; \
- } \
- return priv->to_instance()->signals_##action##_impl(cx, args); \
- } \
- \
- bool ObjectInstance::signals_##action##_impl(JSContext* cx, \
- const JS::CallArgs& args) { \
- gjs_debug_gsignal("[Gi.signals_" #action \
- "_symbol]() obj %p priv %p argc %d", \
- m_wrapper.get(), this, args.length()); \
- \
- if (!check_gobject_disposed(#action " any signal on")) { \
- return true; \
- } \
- JS::RootedObject match(cx); \
- if (!gjs_parse_call_args(cx, "[Gi.signals_" #action "_symbol]", args, \
- "o", "match", &match)) { \
- return false; \
- } \
- GSignalMatchType mask; \
- unsigned signal_id; \
- GQuark detail; \
- JS::RootedFunction func(cx); \
- if (!signal_match_arguments_from_object(cx, match, &mask, &signal_id, \
- &detail, &func)) { \
- return false; \
- } \
- unsigned n_matched = 0; \
- if (!func) { \
- n_matched = g_signal_handlers_##action##_matched( \
- m_ptr, mask, signal_id, detail, nullptr, nullptr, nullptr); \
- } else { \
- std::vector<GClosure*> candidates; \
- for (GClosure* candidate : m_closures) { \
- if (gjs_closure_get_callable(candidate) == func) \
- candidates.push_back(candidate); \
- } \
- for (GClosure* candidate : candidates) { \
- n_matched += g_signal_handlers_##action##_matched( \
- m_ptr, mask, signal_id, detail, candidate, nullptr, \
- nullptr); \
- } \
- } \
- \
- args.rval().setNumber(n_matched); \
- return true; \
- }
-
-DEFINE_SIGNAL_MATCH_METHOD(block)
-DEFINE_SIGNAL_MATCH_METHOD(unblock)
-DEFINE_SIGNAL_MATCH_METHOD(disconnect)
-
-#undef DEFINE_SIGNAL_MATCH_METHOD
+template <ObjectBase::SignalMatchFunc(*MatchFunc)>
+static inline const char* signal_match_to_action_name();
+
+template <>
+inline const char*
+signal_match_to_action_name<&g_signal_handlers_block_matched>() {
+ return "block";
+}
+
+template <>
+inline const char*
+signal_match_to_action_name<&g_signal_handlers_unblock_matched>() {
+ return "unblock";
+}
+
+template <>
+inline const char*
+signal_match_to_action_name<&g_signal_handlers_disconnect_matched>() {
+ return "disconnect";
+}
+
+template <ObjectBase::SignalMatchFunc(*MatchFunc)>
+bool ObjectBase::signals_action(JSContext* cx, unsigned argc, JS::Value* vp) {
+ GJS_GET_WRAPPER_PRIV(cx, argc, vp, args, obj, ObjectBase, priv);
+ const std::string action_name = signal_match_to_action_name<MatchFunc>();
+ if (!priv->check_is_instance(cx, (action_name + " signal").c_str()))
+ return false;
+
+ return priv->to_instance()->signals_action_impl<MatchFunc>(cx, args);
+}
+
+template <ObjectBase::SignalMatchFunc(*MatchFunc)>
+bool ObjectInstance::signals_action_impl(JSContext* cx,
+ const JS::CallArgs& args) {
+ const std::string action_name = signal_match_to_action_name<MatchFunc>();
+ const std::string action_tag = "[Gi.signals_" + action_name + "_symbol]";
+ gjs_debug_gsignal("[%s]() obj %p priv %p argc %d", action_tag.c_str(),
+ m_wrapper.get(), this, args.length());
+
+ if (!check_gobject_disposed((action_name + " any signal on").c_str())) {
+ return true;
+ }
+ JS::RootedObject match(cx);
+ if (!gjs_parse_call_args(cx, action_tag.c_str(), args, "o", "match",
+ &match)) {
+ return false;
+ }
+ GSignalMatchType mask;
+ unsigned signal_id;
+ GQuark detail;
+ JS::RootedFunction func(cx);
+ if (!signal_match_arguments_from_object(cx, match, &mask, &signal_id,
+ &detail, &func)) {
+ return false;
+ }
+ unsigned n_matched = 0;
+ if (!func) {
+ n_matched = MatchFunc(m_ptr, mask, signal_id, detail, nullptr, nullptr,
+ nullptr);
+ } else {
+ std::vector<GClosure*> candidates;
+ for (GClosure* candidate : m_closures) {
+ if (gjs_closure_get_callable(candidate) == func)
+ candidates.push_back(candidate);
+ }
+ for (GClosure* candidate : candidates) {
+ n_matched += MatchFunc(m_ptr, mask, signal_id, detail, candidate,
+ nullptr, nullptr);
+ }
+ }
+
+ args.rval().setNumber(n_matched);
+ return true;
+}
bool ObjectBase::to_string(JSContext* cx, unsigned argc, JS::Value* vp) {
GJS_GET_WRAPPER_PRIV(cx, argc, vp, args, obj, ObjectBase, priv);
@@ -2282,15 +2298,18 @@ bool ObjectPrototype::define_class(JSContext* context,
JS_DefineFunctionById(context, prototype, atoms.signal_find(),
&ObjectBase::signal_find, 1,
GJS_MODULE_PROP_FLAGS) &&
- JS_DefineFunctionById(context, prototype, atoms.signals_block(),
- &ObjectBase::signals_block, 1,
- GJS_MODULE_PROP_FLAGS) &&
- JS_DefineFunctionById(context, prototype, atoms.signals_unblock(),
- &ObjectBase::signals_unblock, 1,
- GJS_MODULE_PROP_FLAGS) &&
+ JS_DefineFunctionById(
+ context, prototype, atoms.signals_block(),
+ &ObjectBase::signals_action<&g_signal_handlers_block_matched>, 1,
+ GJS_MODULE_PROP_FLAGS) &&
+ JS_DefineFunctionById(
+ context, prototype, atoms.signals_unblock(),
+ &ObjectBase::signals_action<&g_signal_handlers_unblock_matched>,
+ 1, GJS_MODULE_PROP_FLAGS) &&
JS_DefineFunctionById(context, prototype, atoms.signals_disconnect(),
- &ObjectBase::signals_disconnect, 1,
- GJS_MODULE_PROP_FLAGS);
+ &ObjectBase::signals_action<
+ &g_signal_handlers_disconnect_matched>,
+ 1, GJS_MODULE_PROP_FLAGS);
}
/*
diff --git a/gi/object.h b/gi/object.h
index 81648ddd..d865c9c4 100644
--- a/gi/object.h
+++ b/gi/object.h
@@ -105,6 +105,8 @@ class ObjectBase
: GIWrapperBase(proto) {}
public:
+ using SignalMatchFunc = guint(gpointer, GSignalMatchType, guint, GQuark,
+ GClosure*, gpointer, gpointer);
static const GjsDebugTopic debug_topic = GJS_DEBUG_GOBJECT;
static constexpr const char* debug_tag = "GObject";
@@ -179,12 +181,10 @@ class ObjectBase
static bool emit(JSContext* cx, unsigned argc, JS::Value* vp);
GJS_JSAPI_RETURN_CONVENTION
static bool signal_find(JSContext* cx, unsigned argc, JS::Value* vp);
- GJS_JSAPI_RETURN_CONVENTION
- static bool signals_block(JSContext* cx, unsigned argc, JS::Value* vp);
- GJS_JSAPI_RETURN_CONVENTION
- static bool signals_unblock(JSContext* cx, unsigned argc, JS::Value* vp);
- GJS_JSAPI_RETURN_CONVENTION
- static bool signals_disconnect(JSContext* cx, unsigned argc, JS::Value* vp);
+ template <SignalMatchFunc(*MATCH_FUNC)>
+ GJS_JSAPI_RETURN_CONVENTION static bool signals_action(JSContext* cx,
+ unsigned argc,
+ JS::Value* vp);
GJS_JSAPI_RETURN_CONVENTION
static bool to_string(JSContext* cx, unsigned argc, JS::Value* vp);
[[nodiscard]] const char* to_string_kind() const;
@@ -476,12 +476,9 @@ class ObjectInstance : public GIWrapperInstance<ObjectBase, ObjectPrototype,
bool emit_impl(JSContext* cx, const JS::CallArgs& args);
GJS_JSAPI_RETURN_CONVENTION
bool signal_find_impl(JSContext* cx, const JS::CallArgs& args);
- GJS_JSAPI_RETURN_CONVENTION
- bool signals_block_impl(JSContext* cx, const JS::CallArgs& args);
- GJS_JSAPI_RETURN_CONVENTION
- bool signals_unblock_impl(JSContext* cx, const JS::CallArgs& args);
- GJS_JSAPI_RETURN_CONVENTION
- bool signals_disconnect_impl(JSContext* cx, const JS::CallArgs& args);
+ template <SignalMatchFunc(*MATCH_FUNC)>
+ GJS_JSAPI_RETURN_CONVENTION bool signals_action_impl(
+ JSContext* cx, const JS::CallArgs& args);
GJS_JSAPI_RETURN_CONVENTION
bool init_impl(JSContext* cx, const JS::CallArgs& args,
JS::MutableHandleObject obj);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]