[RFC PATCH] Attempt to reactive Ruby gc

Subject: [RFC PATCH] Attempt to reactive Ruby gc

Date: Tue, 27 Apr 2021 03:53:43 -0500

To: notmuch@notmuchmail.org

Cc: Ali Polatel

From: Felipe Contreras


Commit c7893408 (ruby: Kill garbage collection related cruft.,
2010-05-26) removed garbage collection because the order of objects
freed couldn't be ensured in Ruby.

However, we can use talloc for reference counting and thus preventing
Ruby from destroying the objects.

First we create a wrapper object with no talloc parent, which will be
owned by the Ruby object (e.g. Notmuch::Thread). The notmuch object
(notmuch_thread_t) will have two parents then (notmuch_threads_t and
Notmuch::Thread).

If Ruby destroys the other parent first (notmuch_threads_t), that still
doesn't destroy the object, since we still own a reference (from
Notmuch::Thread).

It's only when both are destroyed that the object is actually freed.

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---
 bindings/ruby/defs.h     | 24 +++++++++++++++++++++++-
 bindings/ruby/extconf.rb |  1 +
 bindings/ruby/thread.c   |  6 +++---
 bindings/ruby/threads.c  |  2 +-
 4 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/bindings/ruby/defs.h b/bindings/ruby/defs.h
index 48544ca2..56a70a4f 100644
--- a/bindings/ruby/defs.h
+++ b/bindings/ruby/defs.h
@@ -23,6 +23,7 @@
 
 #include <notmuch.h>
 #include <ruby.h>
+#include <talloc.h>
 
 extern VALUE notmuch_rb_cDatabase;
 extern VALUE notmuch_rb_cDirectory;
@@ -50,6 +51,25 @@ extern ID ID_call;
 extern ID ID_db_create;
 extern ID ID_db_mode;
 
+typedef struct {
+    void *pointer;
+} notmuch_rb_object_t;
+
+static inline void
+notmuch_rb_object_free (void *object)
+{
+    talloc_free (object);
+}
+
+static inline VALUE
+notmuch_rb_object_wrap (VALUE klass, void *ptr)
+{
+    notmuch_rb_object_t *object = talloc (NULL, typeof (*object));
+    object->pointer = ptr;
+    talloc_reference (object, ptr);
+    return Data_Wrap_Struct (klass, NULL, &notmuch_rb_object_free, object);
+}
+
 /* RSTRING_PTR() is new in ruby-1.9 */
 #if !defined(RSTRING_PTR)
 # define RSTRING_PTR(v) (RSTRING((v))->ptr)
@@ -105,10 +125,12 @@ extern ID ID_db_mode;
 
 #define Data_Get_Notmuch_Thread(obj, ptr)			\
     do {							\
+	notmuch_rb_object_t *object;				\
 	Check_Type ((obj), T_DATA);				\
 	if (DATA_PTR ((obj)) == NULL)				\
 	rb_raise (rb_eRuntimeError, "thread destroyed");	\
-	Data_Get_Struct ((obj), notmuch_thread_t, (ptr));	\
+	Data_Get_Struct ((obj), typeof (*object), object);	\
+	(ptr) = object->pointer;					\
     } while (0)
 
 #define Data_Get_Notmuch_Message(obj, ptr)			\
diff --git a/bindings/ruby/extconf.rb b/bindings/ruby/extconf.rb
index 161de5a2..d914537c 100644
--- a/bindings/ruby/extconf.rb
+++ b/bindings/ruby/extconf.rb
@@ -19,6 +19,7 @@ if not ENV['LIBNOTMUCH']
 end
 
 $LOCAL_LIBS += ENV['LIBNOTMUCH']
+$LIBS += " -ltalloc"
 
 # Create Makefile
 dir_config('notmuch')
diff --git a/bindings/ruby/thread.c b/bindings/ruby/thread.c
index 9b295981..5705b556 100644
--- a/bindings/ruby/thread.c
+++ b/bindings/ruby/thread.c
@@ -28,11 +28,11 @@
 VALUE
 notmuch_rb_thread_destroy (VALUE self)
 {
-    notmuch_thread_t *thread;
+    notmuch_rb_object_t *object;
 
-    Data_Get_Notmuch_Thread (self, thread);
+    Data_Get_Struct (self, typeof (*object), object);
 
-    notmuch_thread_destroy (thread);
+    notmuch_rb_object_free (object);
     DATA_PTR (self) = NULL;
 
     return Qnil;
diff --git a/bindings/ruby/threads.c b/bindings/ruby/threads.c
index ed403a8f..302ffd91 100644
--- a/bindings/ruby/threads.c
+++ b/bindings/ruby/threads.c
@@ -53,7 +53,7 @@ notmuch_rb_threads_each (VALUE self)
 
     for (; notmuch_threads_valid (threads); notmuch_threads_move_to_next (threads)) {
 	thread = notmuch_threads_get (threads);
-	rb_yield (Data_Wrap_Struct (notmuch_rb_cThread, NULL, NULL, thread));
+	rb_yield (notmuch_rb_object_wrap (notmuch_rb_cThread, thread));
     }
 
     return self;
-- 
2.31.0
_______________________________________________
notmuch mailing list -- notmuch@notmuchmail.org
To unsubscribe send an email to notmuch-leave@notmuchmail.org

Thread: