[gjs: 3/12] function: Define a trampoline autopointer cleanup function and use it




commit f298f86c80c42c2ff26bb2a8d5028ce124e392a0
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Wed Sep 2 19:44:10 2020 +0200

    function: Define a trampoline autopointer cleanup function and use it

 gi/arg-cache.cpp |  4 ++--
 gi/function.cpp  | 18 ++++++------------
 gi/function.h    |  5 +++++
 3 files changed, 13 insertions(+), 14 deletions(-)
---
diff --git a/gi/arg-cache.cpp b/gi/arg-cache.cpp
index c8fa3796..f06e905c 100644
--- a/gi/arg-cache.cpp
+++ b/gi/arg-cache.cpp
@@ -911,11 +911,11 @@ static bool gjs_marshal_callback_release(JSContext*, GjsArgumentCache*,
     if (!closure)
         return true;
 
-    auto trampoline = static_cast<GjsCallbackTrampoline*>(closure->user_data);
+    GjsAutoCallbackTrampoline trampoline =
+        static_cast<GjsCallbackTrampoline*>(closure->user_data);
     // CallbackTrampolines are refcounted because for notified/async closures
     // it is possible to destroy it while in call, and therefore we cannot
     // check its scope at this point
-    gjs_callback_trampoline_unref(trampoline);
     gjs_arg_unset<void*>(in_arg);
     return true;
 }
diff --git a/gi/function.cpp b/gi/function.cpp
index b0cb101b..e1e326cd 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -27,6 +27,7 @@
 #include <stdlib.h>  // for exit
 #include <string.h>  // for strcmp, memset, size_t
 
+#include <memory>  // for unique_ptr
 #include <new>
 #include <string>
 #include <type_traits>
@@ -237,22 +238,20 @@ warn_about_illegal_js_callback(const GjsCallbackTrampoline *trampoline,
 static void gjs_callback_closure(ffi_cif* cif [[maybe_unused]], void* result,
                                  void** ffi_args, void* data) {
     JSContext *context;
-    GjsCallbackTrampoline *trampoline;
     int i, n_args, n_jsargs, n_outargs, c_args_offset = 0;
     GITypeInfo ret_type;
     bool success = false;
     auto args = reinterpret_cast<GIArgument **>(ffi_args);
 
-    trampoline = (GjsCallbackTrampoline *) data;
-    g_assert(trampoline);
-    gjs_callback_trampoline_ref(trampoline);
+    g_assert(data && "Trampoline data is not set");
+    GjsAutoCallbackTrampoline trampoline(
+        static_cast<GjsCallbackTrampoline*>(data), GjsAutoTakeOwnership());
 
     if (G_UNLIKELY(!gjs_closure_is_valid(trampoline->js_function))) {
         warn_about_illegal_js_callback(trampoline, "during shutdown",
             "destroying a Clutter actor or GTK widget with ::destroy signal "
             "connected, or using the destroy(), dispose(), or remove() vfuncs");
         gjs_dumpstack();
-        gjs_callback_trampoline_unref(trampoline);
         return;
     }
 
@@ -263,14 +262,12 @@ static void gjs_callback_closure(ffi_cif* cif [[maybe_unused]], void* result,
             "destroying a Clutter actor or GTK widget with ::destroy signal "
             "connected, or using the destroy(), dispose(), or remove() vfuncs");
         gjs_dumpstack();
-        gjs_callback_trampoline_unref(trampoline);
         return;
     }
 
     if (G_UNLIKELY(!gjs->is_owner_thread())) {
         warn_about_illegal_js_callback(trampoline, "on a different thread",
             "an API not intended to be used in JS");
-        gjs_callback_trampoline_unref(trampoline);
         return;
     }
 
@@ -532,7 +529,6 @@ out:
         completed_trampolines = g_slist_prepend(completed_trampolines, trampoline);
     }
 
-    gjs_callback_trampoline_unref(trampoline);
     gjs->schedule_gc_if_needed();
 }
 
@@ -540,7 +536,7 @@ GjsCallbackTrampoline* gjs_callback_trampoline_new(
     JSContext* context, JS::HandleFunction function,
     GICallableInfo* callable_info, GIScopeType scope, bool has_scope_object,
     bool is_vfunc) {
-    GjsCallbackTrampoline *trampoline;
+    GjsAutoCallbackTrampoline trampoline;
     int n_args, i;
 
     g_assert(function);
@@ -588,7 +584,6 @@ GjsCallbackTrampoline* gjs_callback_trampoline_new(
                           is_vfunc ? "VFunc" : "Callback",
                           g_base_info_get_name(callable_info));
                 g_base_info_unref(interface_info);
-                gjs_callback_trampoline_unref(trampoline);
                 return NULL;
             }
             g_base_info_unref(interface_info);
@@ -606,7 +601,6 @@ GjsCallbackTrampoline* gjs_callback_trampoline_new(
                                   "length argument. This is not supported",
                                   is_vfunc ? "VFunc" : "Callback",
                                   g_base_info_get_name(callable_info));
-                        gjs_callback_trampoline_unref(trampoline);
                         return NULL;
                     }
 
@@ -631,7 +625,7 @@ GjsCallbackTrampoline* gjs_callback_trampoline_new(
     trampoline->scope = scope;
     trampoline->is_vfunc = is_vfunc;
 
-    return trampoline;
+    return trampoline.release();
 }
 
 /* Intended for error messages. Return value must be freed */
diff --git a/gi/function.h b/gi/function.h
index 98d09d0f..b295154c 100644
--- a/gi/function.h
+++ b/gi/function.h
@@ -34,6 +34,7 @@
 #include <js/RootingAPI.h>
 #include <js/TypeDecls.h>
 
+#include "gjs/jsapi-util.h"
 #include "gjs/macros.h"
 
 namespace JS {
@@ -70,6 +71,10 @@ void gjs_callback_trampoline_unref(GjsCallbackTrampoline *trampoline);
 GjsCallbackTrampoline* gjs_callback_trampoline_ref(
     GjsCallbackTrampoline* trampoline);
 
+using GjsAutoCallbackTrampoline =
+    GjsAutoPointer<GjsCallbackTrampoline, GjsCallbackTrampoline,
+                   gjs_callback_trampoline_unref, gjs_callback_trampoline_ref>;
+
 // Stack allocation only!
 struct GjsFunctionCallState {
     GIArgument* in_cvalues;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]