[libgee] Fix case of releasing lock-free resources during the global cleanup



commit eed6c917cfc42a2cf880a08100420ab71d365046
Author: Maciej Piechotka <uzytkownik2 gmail com>
Date:   Sat Mar 1 21:58:41 2014 +0100

    Fix case of releasing lock-free resources during the global cleanup

 gee/hazardpointer.vala |   31 ++++++++++++++++++++++++-------
 1 files changed, 24 insertions(+), 7 deletions(-)
---
diff --git a/gee/hazardpointer.vala b/gee/hazardpointer.vala
index 7513751..937e08a 100644
--- a/gee/hazardpointer.vala
+++ b/gee/hazardpointer.vala
@@ -452,15 +452,22 @@ public class Gee.HazardPointer<G> { // FIXME: Make it a struct
                        switch (self) {
                        case HELPER_THREAD:
                                new Thread<bool> ("<<libgee hazard pointer>>", () => {
+                                       Context ctx = new Context (Policy.TRY_FREE);
                                        while (true) {
                                                Thread.yield ();
-                                               attempt_free ();
+                                               pull_from_queue (ctx._to_free, ctx._to_free.is_empty);
+                                               ctx.try_free ();
                                        }
                                });
                                break;
                        case MAIN_LOOP:
+                               _global_to_free = new ArrayList<FreeNode *> ();
                                Idle.add (() => {
-                                       attempt_free ();
+                                       Context ctx = new Context (Policy.TRY_FREE);
+                                       swap (ref _global_to_free, ref ctx._to_free);
+                                       pull_from_queue (ctx._to_free, false);
+                                       ctx.try_free ();
+                                       swap (ref _global_to_free, ref ctx._to_free);
                                        return true;
                                }, Priority.LOW);
                                break;
@@ -469,6 +476,12 @@ public class Gee.HazardPointer<G> { // FIXME: Make it a struct
                        }
                }
 
+               private static void swap<T>(ref T a, ref T b) {
+                       T tmp = (owned)a;
+                       a = (owned)b;
+                       b = (owned)tmp;
+               }
+
                /**
                 * Ensures that helper methods are started.
                 */
@@ -482,21 +495,25 @@ public class Gee.HazardPointer<G> { // FIXME: Make it a struct
                                        _queue = new LinkedList<ArrayList<FreeNode *>> ();
                                        // Hack to not lie about successfull setting policy
                                        policy = AtomicInt.add (ref release_policy, (int)(1 << (sizeof(int) * 
8 - 1)));
-                                       _global_to_free = new ArrayList<FreeNode *> ();
                                        start ((ReleasePolicy) policy);
                                }
                                _queue_mutex.unlock ();
                        }
                }
 
-               private static inline void attempt_free () {
-                       if (_queue_mutex.trylock ()) {
+               private static inline void pull_from_queue (Collection<FreeNode *> to_free, bool do_lock) {
+                       bool locked = do_lock;
+                       if (do_lock) {
+                               _queue_mutex.lock ();
+                       } else {
+                               locked = _queue_mutex.trylock ();
+                       }
+                       if (locked) {
                                Collection<ArrayList<FreeNode *>> temp = new ArrayList<ArrayList<FreeNode *>> 
();
                                _queue.drain (temp);
                                _queue_mutex.unlock ();
-                               temp.foreach ((x) => {_global_to_free.add_all (x); return true;});
+                               temp.foreach ((x) => {to_free.add_all (x); return true;});
                        }
-                       try_free (_global_to_free);
                }
        }
 


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