[gjs: 11/18] gi: Use GjsSmartPointer to handle destruction of Wrapped objects




commit 76563efb16f563cb337701da65b63cefa261aed7
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Thu Oct 1 18:02:22 2020 +0200

    gi: Use GjsSmartPointer to handle destruction of Wrapped objects
    
    With the introduction of GjsSmartPointer we can easily generate smart
    pointer types at build-time depending on template arguments and with the
    same size of a normal pointer, so use this for WrapperUtils.
    
    Don't change the default behavior for base class, so introduce a fake
    smart-pointer using a custom type that has no free function set, while
    use it to handle automatically some basic types we have (so far just
    GError and GObject will take advantage).
    
    However this opens the gates to a creation of custom specializations of
    BoxedInstance that we may use to create different compile-time codepaths
    avoiding various dynamic checks.

 gi/boxed.cpp      | 10 ++++------
 gi/gerror.cpp     |  1 -
 gi/object.cpp     | 18 +++++++++---------
 gi/wrapperutils.h | 14 +++++++++++---
 4 files changed, 24 insertions(+), 19 deletions(-)
---
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index 2b000280..96fdc89d 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -419,18 +419,16 @@ BoxedInstance::~BoxedInstance() {
     if (m_owning_ptr) {
         if (m_allocated_directly) {
             if (gtype() == G_TYPE_VALUE)
-                g_value_unset(static_cast<GValue*>(m_ptr));
-            g_free(m_ptr);
+                g_value_unset(m_ptr.as<GValue>());
+            g_free(m_ptr.release());
         } else {
             if (g_type_is_a(gtype(), G_TYPE_BOXED))
-                g_boxed_free(gtype(), m_ptr);
+                g_boxed_free(gtype(), m_ptr.release());
             else if (g_type_is_a(gtype(), G_TYPE_VARIANT))
-                g_variant_unref(static_cast<GVariant*>(m_ptr));
+                g_variant_unref(static_cast<GVariant*>(m_ptr.release()));
             else
                 g_assert_not_reached ();
         }
-
-        m_ptr = nullptr;
     }
 
     GJS_DEC_COUNTER(boxed_instance);
diff --git a/gi/gerror.cpp b/gi/gerror.cpp
index 04e88f7c..3d01390c 100644
--- a/gi/gerror.cpp
+++ b/gi/gerror.cpp
@@ -47,7 +47,6 @@ ErrorInstance::ErrorInstance(JSContext* cx, JS::HandleObject obj)
 }
 
 ErrorInstance::~ErrorInstance(void) {
-    g_clear_error(&m_ptr);
     GJS_DEC_COUNTER(gerror_instance);
 }
 
diff --git a/gi/object.cpp b/gi/object.cpp
index 17b1bedd..abbf0b35 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -191,7 +191,7 @@ bool ObjectInstance::check_gobject_disposed(const char* for_what) const {
         "it. This might be caused by the object having been destroyed from C "
         "code using something such as destroy(), dispose(), or remove() "
         "vfuncs.",
-        ns(), name(), m_ptr, for_what);
+        ns(), name(), m_ptr.get(), for_what);
     gjs_dumpstack();
     return false;
 }
@@ -218,7 +218,7 @@ ObjectInstance::check_js_object_finalized(void)
             "Object %p (a %s) resurfaced after the JS wrapper was finalized. "
             "This is some library doing dubious memory management inside "
             "dispose()",
-            m_ptr, type_name());
+            m_ptr.get(), type_name());
         m_wrapper_finalized = false;
         g_assert(!m_wrapper);  /* should associate again with a new wrapper */
     }
@@ -1285,10 +1285,10 @@ ObjectInstance::release_native_object(void)
 {
     discard_wrapper();
     if (m_uses_toggle_ref)
-        g_object_remove_toggle_ref(m_ptr, wrapped_gobj_toggle_notify, nullptr);
+        g_object_remove_toggle_ref(m_ptr.release(), wrapped_gobj_toggle_notify,
+                                   nullptr);
     else
-        g_object_unref(m_ptr);
-    m_ptr = nullptr;
+        m_ptr = nullptr;
 }
 
 /* At shutdown, we need to ensure we've cleared the context of any
@@ -1467,15 +1467,15 @@ ObjectInstance::disassociate_js_gobject(void)
     bool had_toggle_down, had_toggle_up;
 
     if (!m_gobj_disposed)
-        g_object_weak_unref(m_ptr, wrapped_gobj_dispose_notify, this);
+        g_object_weak_unref(m_ptr.get(), wrapped_gobj_dispose_notify, this);
 
     auto& toggle_queue = ToggleQueue::get_default();
-    std::tie(had_toggle_down, had_toggle_up) = toggle_queue.cancel(m_ptr);
+    std::tie(had_toggle_down, had_toggle_up) = toggle_queue.cancel(m_ptr.get());
     if (had_toggle_down != had_toggle_up) {
         g_error(
             "JS object wrapper for GObject %p (%s) is being released while "
             "toggle references are still pending.",
-            m_ptr, type_name());
+            m_ptr.get(), type_name());
     }
 
     /* Fist, remove the wrapper pointer from the wrapped GObject */
@@ -2462,7 +2462,7 @@ bool ObjectBase::transfer_to_gi_argument(JSContext* cx, JS::HandleObject obj,
 // Overrides GIWrapperInstance::typecheck_impl()
 bool ObjectInstance::typecheck_impl(JSContext* cx, GIBaseInfo* expected_info,
                                     GType expected_type) const {
-    g_assert(m_gobj_disposed || gtype() == G_OBJECT_TYPE(m_ptr));
+    g_assert(m_gobj_disposed || gtype() == G_OBJECT_TYPE(m_ptr.as<GObject*>()));
     return GIWrapperInstance::typecheck_impl(cx, expected_info, expected_type);
 }
 
diff --git a/gi/wrapperutils.h b/gi/wrapperutils.h
index 2745c5bc..4b38cb2f 100644
--- a/gi/wrapperutils.h
+++ b/gi/wrapperutils.h
@@ -996,6 +996,13 @@ class GIWrapperPrototype : public Base {
     void trace_impl(JSTracer*) {}
 };
 
+using GIWrappedUnowned = void;
+template <>
+struct GjsSmartPointer<GIWrappedUnowned>
+    : GjsAutoPointer<GIWrappedUnowned, void, nullptr> {
+    using GjsAutoPointer::GjsAutoPointer;
+};
+
 /*
  * GIWrapperInstance:
  *
@@ -1007,10 +1014,11 @@ class GIWrapperPrototype : public Base {
  * GIWrapperInstance", because of the unusual polymorphism scheme, in order for
  * Base to call methods such as trace_impl().
  */
-template <class Base, class Prototype, class Instance, typename Wrapped = void>
+template <class Base, class Prototype, class Instance,
+          typename Wrapped = GIWrappedUnowned>
 class GIWrapperInstance : public Base {
  protected:
-    Wrapped* m_ptr = nullptr;
+    GjsSmartPointer<Wrapped> m_ptr;
 
     explicit GIWrapperInstance(JSContext* cx, JS::HandleObject obj)
         : Base(Prototype::for_js_prototype(cx, obj)), m_ptr(nullptr) {
@@ -1061,7 +1069,7 @@ class GIWrapperInstance : public Base {
      * Like ptr(), but returns a byte pointer for use in byte arithmetic.
      */
     [[nodiscard]] uint8_t* raw_ptr() const {
-        return reinterpret_cast<uint8_t*>(m_ptr);
+        return reinterpret_cast<uint8_t*>(ptr());
     }
 
     // JSClass operations


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