ソースを参照

fix: HashSet/Lifo item ownership — nodes never unreffed their contents

HashSetItem and LifoItem are compact classes whose generated free
functions only g_slice_free the node; the stored item pointer was
dropped without unref, so remove()/clear()/destruction leaked one
strong reference per stored object (Dictionary and Catalogue are built
on HashSet, and inversion's injection-context stack on Lifo — every
container operation in the web stack leaked). Mirroring SeriesItem,
the item classes now take (owned T) through a constructor, which makes
valac mark the field owned and emit the destroy call when the field is
cleared before the node is deleted.

Companion to the inversion Scope.release work: without this, clearing
a released scope's caches still leaked every scoped instance (and with
a scoped sqlite Connection, its db+wal fd pair per request).
clanker 1 ヶ月 前
親
コミット
8e2d4fb4b0
2 ファイル変更、18 行追加、12 行削除
  1. 12 6
      src/lib/DataStructures/HashSet.vala
  2. 6 6
      src/lib/DataStructures/Lifo.vala

+ 12 - 6
src/lib/DataStructures/HashSet.vala

@@ -7,6 +7,11 @@ namespace Invercargill.DataStructures {
         private class HashSetItem<T> {
             public uint hash;
             public T item;
+
+            public HashSetItem(owned T item, uint hash) {
+                this.item = (owned)item;
+                this.hash = hash;
+            }
         }
 
         private HashSetItem<T>* tombstone;
@@ -28,7 +33,7 @@ namespace Invercargill.DataStructures {
         }
 
         private void setup(HashDelegate<T>? value_hash_func = null, EqualityDelegate<T>? value_equal_func = null) {
-            tombstone = new HashSetItem<T>();
+            tombstone = new HashSetItem<T>(null, 0);
             hash_func = value_hash_func ?? Operators.hash<T>();
             equal_func = value_equal_func ?? Operators.equality<T>();
             safe_read = get_safe_read_function_for<T>();
@@ -120,9 +125,7 @@ namespace Invercargill.DataStructures {
                 bucket = buckets[bucket_index];
             }
             
-            HashSetItem<T>* new_bucket = new HashSetItem<T>();
-            new_bucket->hash = bucket_hash;
-            new_bucket->item = (owned)item;
+            HashSetItem<T>* new_bucket = new HashSetItem<T>((owned) item, bucket_hash);
             buckets[bucket_index] = new_bucket;
             n_items++;
             return true;
@@ -174,6 +177,7 @@ namespace Invercargill.DataStructures {
                 if(buckets[bucket_index] != tombstone) {
                     var ours = buckets[bucket_index]->item;
                     if(equal_func(ours, item)) {
+                        buckets[bucket_index]->item = null;
                         delete buckets[bucket_index];
                         buckets[bucket_index] = tombstone;
                         n_items--;
@@ -195,8 +199,10 @@ namespace Invercargill.DataStructures {
 
         private void delete_items() {
             for(uint i = 0; i < buckets.length; i++) {
-                if(buckets[i] != null && buckets[i] != tombstone)
-                delete buckets[i];
+                if(buckets[i] != null && buckets[i] != tombstone) {
+                    buckets[i]->item = null;
+                    delete buckets[i];
+                }
             }
         }
 

+ 6 - 6
src/lib/DataStructures/Lifo.vala

@@ -27,9 +27,7 @@ namespace Invercargill.DataStructures {
 
         public void push(owned T item) {
             mutex.lock();
-            LifoItem<T>* lifo_item = new LifoItem<T>() {
-                item = item,
-            };
+            LifoItem<T>* lifo_item = new LifoItem<T>((owned) item);
 
             if(top_item == null) {
                 top_item = lifo_item;
@@ -47,9 +45,7 @@ namespace Invercargill.DataStructures {
              mutex.lock();
 
              foreach (var item in items) {
-                LifoItem<T>* lifo_item = new LifoItem<T>() {
-                    item = item,
-                };
+                LifoItem<T>* lifo_item = new LifoItem<T>(item);
     
                 if(top_item == null) {
                     top_item = lifo_item;
@@ -143,6 +139,10 @@ namespace Invercargill.DataStructures {
         private class LifoItem<T> {
             public T item;
             public LifoItem<T>* next_item;
+
+            public LifoItem(owned T item) {
+                this.item = (owned)item;
+            }
         }
 
     }