[gjs] mem: Reimplement counters using c++ atomic and constexpr expressions



commit 2044362468e4db707d6dab2ec3aff8fbb499d6c7
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Wed May 12 17:27:23 2021 +0200

    mem: Reimplement counters using c++ atomic and constexpr expressions
    
    We still rely on macros to repeat calls, but they do the bare minimum
    now.

 gjs/mem-private.h | 52 ++++++++++++++++++++++++++++++++++------------------
 gjs/mem.cpp       | 29 ++++++++++++++++++-----------
 2 files changed, 52 insertions(+), 29 deletions(-)
---
diff --git a/gjs/mem-private.h b/gjs/mem-private.h
index 8350bde6..e4bdc750 100644
--- a/gjs/mem-private.h
+++ b/gjs/mem-private.h
@@ -1,16 +1,12 @@
 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
 // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
 // SPDX-FileCopyrightText: 2008 litl, LLC
+// SPDX-FileCopyrightText: 2021 Canonical, Ltd
 
 #ifndef GJS_MEM_PRIVATE_H_
 #define GJS_MEM_PRIVATE_H_
 
-#include <glib.h>
-
-typedef struct {
-    int value;
-    const char* name;
-} GjsMemCounter;
+#include <atomic>
 
 // clang-format off
 #define GJS_FOR_EACH_COUNTER(macro) \
@@ -32,23 +28,43 @@ typedef struct {
     macro(union_prototype)
 // clang-format on
 
-#define GJS_DECLARE_COUNTER(name) extern GjsMemCounter gjs_counter_##name;
+namespace Gjs {
+namespace Memory {
+
+struct Counter {
+    explicit Counter(const char* n) : name(n) {}
+    std::atomic_int64_t value = ATOMIC_VAR_INIT(0);
+    const char* name;
+};
 
+namespace Counters {
+#define GJS_DECLARE_COUNTER(name) extern Counter name;
 GJS_DECLARE_COUNTER(everything)
 GJS_FOR_EACH_COUNTER(GJS_DECLARE_COUNTER)
+#undef GJS_DECLARE_COUNTER
+
+template <Counter* counter>
+constexpr void inc() {
+    everything.value++;
+    counter->value++;
+}
+
+template <Counter* counter>
+constexpr void dec() {
+    counter->value--;
+    everything.value--;
+}
+
+}  // namespace Counters
+}  // namespace Memory
+}  // namespace Gjs
 
-#define GJS_INC_COUNTER(name)                               \
-    do {                                                    \
-        g_atomic_int_add(&gjs_counter_everything.value, 1); \
-        g_atomic_int_add(&gjs_counter_##name.value, 1);     \
-    } while (0)
+#define GJS_INC_COUNTER(name) \
+    (Gjs::Memory::Counters::inc<&Gjs::Memory::Counters::name>());
 
-#define GJS_DEC_COUNTER(name)                                \
-    do {                                                     \
-        g_atomic_int_add(&gjs_counter_everything.value, -1); \
-        g_atomic_int_add(&gjs_counter_##name.value, -1);     \
-    } while (0)
+#define GJS_DEC_COUNTER(name) \
+    (Gjs::Memory::Counters::dec<&Gjs::Memory::Counters::name>());
 
-#define GJS_GET_COUNTER(name) g_atomic_int_get(&gjs_counter_##name.value)
+#define GJS_GET_COUNTER(name) (Gjs::Memory::Counters::name.value.load())
 
 #endif  // GJS_MEM_PRIVATE_H_
diff --git a/gjs/mem.cpp b/gjs/mem.cpp
index c579542c..74794430 100644
--- a/gjs/mem.cpp
+++ b/gjs/mem.cpp
@@ -2,24 +2,31 @@
 // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
 // SPDX-FileCopyrightText: 2008 litl, LLC
 
+#include <stdint.h>
+
+#include <atomic>  // for atomic_int64_t
+
 #include <glib.h>
 
 #include "gjs/mem-private.h"
 #include "gjs/mem.h"
 #include "util/log.h"
 
-#define GJS_DEFINE_COUNTER(name)             \
-    GjsMemCounter gjs_counter_ ## name = { \
-        0, #name                                \
-    };
-
+namespace Gjs {
+namespace Memory {
+namespace Counters {
+#define GJS_DEFINE_COUNTER(name) Counter name(#name);
 
 GJS_DEFINE_COUNTER(everything)
 GJS_FOR_EACH_COUNTER(GJS_DEFINE_COUNTER)
+}  // namespace Counters
+}  // namespace Memory
+}  // namespace Gjs
 
-#define GJS_LIST_COUNTER(name) &gjs_counter_##name,
+#define GJS_LIST_COUNTER(name) &Gjs::Memory::Counters::name,
 
-static GjsMemCounter* counters[] = {GJS_FOR_EACH_COUNTER(GJS_LIST_COUNTER)};
+static Gjs::Memory::Counter* counters[] = {
+    GJS_FOR_EACH_COUNTER(GJS_LIST_COUNTER)};
 
 void
 gjs_memory_report(const char *where,
@@ -27,7 +34,7 @@ gjs_memory_report(const char *where,
 {
     int i;
     int n_counters;
-    int total_objects;
+    int64_t total_objects;
 
     gjs_debug(GJS_DEBUG_MEMORY,
               "Memory report: %s",
@@ -46,13 +53,13 @@ gjs_memory_report(const char *where,
     }
 
     gjs_debug(GJS_DEBUG_MEMORY,
-              "  %d objects currently alive",
+              "  %" G_GINT64_FORMAT " objects currently alive",
               GJS_GET_COUNTER(everything));
 
     if (GJS_GET_COUNTER(everything) != 0) {
         for (i = 0; i < n_counters; ++i) {
-            gjs_debug(GJS_DEBUG_MEMORY, "    %24s = %d", counters[i]->name,
-                      counters[i]->value);
+            gjs_debug(GJS_DEBUG_MEMORY, "    %24s = %" G_GINT64_FORMAT,
+                      counters[i]->name, counters[i]->value.load());
         }
 
         if (die_if_leaks)


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