Fix case of releasing lock-free resources during the local cleanup
authorMaciej Piechotka <uzytkownik2@gmail.com>
Sat, 1 Mar 2014 21:09:07 +0000 (22:09 +0100)
committerMaciej Piechotka <uzytkownik2@gmail.com>
Sat, 1 Mar 2014 21:09:07 +0000 (22:09 +0100)
gee/hazardpointer.vala

index 937e08a..22aca16 100644 (file)
@@ -402,33 +402,34 @@ public class Gee.HazardPointer<G> { // FIXME: Make it a struct
                 * @param to_free List containing elements to free.
                 * @return Non-empty list of not freed elements or ``null`` if all elements have been disposed.
                 */
-               internal ArrayList<FreeNode *>? perform (owned ArrayList<FreeNode *> to_free) {
+               internal bool perform (ref ArrayList<FreeNode *> to_free) {
                        switch (this.to_concrete ()) {
                        case TRY_FREE:
-                               return try_free (to_free) ? (owned) to_free : null;
+                               return try_free (to_free);
                        case FREE:
                                while (try_free (to_free)) {
                                        Thread.yield ();
                                }
-                               return null;
+                               break;
                        case TRY_RELEASE:
                                ReleasePolicy.ensure_start ();
                                if (_queue_mutex.trylock ()) {
                                        _queue.offer ((owned) to_free);
                                        _queue_mutex.unlock ();
-                                       return null;
+                                       return true;
                                } else {
-                                       return (owned) to_free;
+                                       return false;
                                }
                        case RELEASE:
                                ReleasePolicy.ensure_start ();
                                _queue_mutex.lock ();
                                _queue.offer ((owned) to_free);
                                _queue_mutex.unlock ();
-                               return null;
+                               return true;
                        default:
                                assert_not_reached ();
                        }
+                       return false;
                }
        }
 
@@ -561,15 +562,12 @@ public class Gee.HazardPointer<G> { // FIXME: Make it a struct
                        int size = _to_free.size;
                        bool clean_parent = false;
                        if (size > 0) {
-                               ArrayList<FreeNode *>? remaining;
-                               if (_parent == null || size >= THRESHOLD)
-                                       remaining = _policy.perform ((owned) _to_free);
-                               else
-                                       remaining = (owned) _to_free;
-                               if (remaining != null) {
-                                       assert (_parent != null);
-                                       _parent->_to_free.add_all (remaining);
-                                       clean_parent = true;
+                               if (_parent == null || size >= THRESHOLD) {
+                                       if (!_policy.perform (ref _to_free)) {
+                                               assert (_parent != null && _to_free != null);
+                                               _parent->_to_free.add_all (_to_free);
+                                               clean_parent = true;
+                                       }
                                }
                        }
 #if DEBUG