[gjs: 7/10] native: Use static destructor to free native modules registry



commit f3b84828abc7640be28d0a48e70ed60faf7fcaae
Author: Philip Chimento <philip chimento gmail com>
Date:   Sun Feb 24 12:51:52 2019 -0800

    native: Use static destructor to free native modules registry
    
    Valgrind shows that the string keys used to register native modules are
    leaked. (Valgrind must have gotten better at detecting this, in recent
    versions.)
    
    The simplest solution is to change the static GHashTable (which must be
    freed at end of process) to a static std::unordered_map (which will have
    its destructor called automatically at end of process.) Static
    destructors can be tricky, but the only things being freed here are
    std::string keys, so there should not be any ordering dependencies
    between this and any other static destructors.

 gjs/native.cpp | 39 ++++++++++++++-------------------------
 1 file changed, 14 insertions(+), 25 deletions(-)
---
diff --git a/gjs/native.cpp b/gjs/native.cpp
index be77dec1..4dfe8950 100644
--- a/gjs/native.cpp
+++ b/gjs/native.cpp
@@ -23,31 +23,28 @@
 
 #include <config.h>
 
-#include <gmodule.h>
+#include <string>
+#include <unordered_map>
 
-#include <util/log.h>
+#include "gjs/jsapi-util.h"
+#include "gjs/jsapi-wrapper.h"
+#include "gjs/native.h"
+#include "util/log.h"
 
-#include "native.h"
-#include "jsapi-wrapper.h"
-#include "jsapi-util.h"
-
-static GHashTable *modules = NULL;
+static std::unordered_map<std::string, GjsDefineModuleFunc> modules;
 
 void
 gjs_register_native_module (const char          *module_id,
                             GjsDefineModuleFunc  func)
 {
-    if (modules == NULL)
-        modules = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
-
-    if (g_hash_table_lookup(modules, module_id) != NULL) {
+    bool inserted;
+    std::tie(std::ignore, inserted) = modules.insert({module_id, func});
+    if (!inserted) {
         g_warning("A second native module tried to register the same id '%s'",
                   module_id);
         return;
     }
 
-    g_hash_table_replace(modules, g_strdup(module_id), (void*) func);
-
     gjs_debug(GJS_DEBUG_NATIVE,
               "Registered native JS module '%s'",
               module_id);
@@ -62,10 +59,7 @@ gjs_register_native_module (const char          *module_id,
  * builtin module without starting to try and load it.
  */
 bool gjs_is_registered_native_module(const char* name) {
-    if (modules == NULL)
-        return false;
-
-    return g_hash_table_lookup(modules, name) != NULL;
+    return modules.count(name) > 0;
 }
 
 /**
@@ -85,23 +79,18 @@ gjs_load_native_module(JSContext              *context,
                        const char             *parse_name,
                        JS::MutableHandleObject module_out)
 {
-    GjsDefineModuleFunc func;
-
     gjs_debug(GJS_DEBUG_NATIVE,
               "Defining native module '%s'",
               parse_name);
 
-    if (modules != NULL)
-        func = (GjsDefineModuleFunc) g_hash_table_lookup(modules, parse_name);
-    else
-        func = NULL;
+    const auto& iter = modules.find(parse_name);
 
-    if (!func) {
+    if (iter == modules.end()) {
         gjs_throw(context,
                   "No native module '%s' has registered itself",
                   parse_name);
         return false;
     }
 
-    return func (context, module_out);
+    return iter->second(context, module_out);
 }


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