Always evaluate in when_done
authorMaciej Piechotka <uzytkownik2@gmail.com>
Mon, 8 Jul 2013 00:32:34 +0000 (02:32 +0200)
committerMaciej Piechotka <uzytkownik2@gmail.com>
Tue, 9 Jul 2013 17:21:44 +0000 (19:21 +0200)
gee/flatmapfuture.vala
gee/future.vala
gee/mapfuture.vala

index 5df8149..20020ec 100644 (file)
@@ -24,10 +24,10 @@ internal class Gee.FlatMapFuture<A, G> : Object, Future<A> {
        public FlatMapFuture (Future<G> base_future, Future.FlatMapFunc<A, G> func) {
                _base = base_future;
                _func = func;
-               _base.when_done (() => {
+               _base.when_done ((val) => {
                        _mutex.lock ();
                        if (_progress == Progress.INIT) {
-                               go_map ();
+                               go_map (val);
                        } else {
                                _mutex.unlock ();
                        }
@@ -43,52 +43,75 @@ internal class Gee.FlatMapFuture<A, G> : Object, Future<A> {
                }
        }
 
-       public unowned G wait () {
-               unowned Future<A> ret_future;
+       public unowned A wait () {
                _mutex.lock ();
-               switch (_progress) {
-               case Progress.INIT:
-                       ret_future = go_map ();
-                       break;
-               case Progress.PROGRESS:
-                       _cond.wait (_mutex);
+               Progress progress = _progress;
+               if (progress == Progress.INIT) {
+                       Future<G> base_future = _base;
                        _mutex.unlock ();
-                       ret_future = _mapped;
-                       break;
-               case Progress.READY:
+                       base_future.wait ();
+                       _mutex.lock ();
+                       progress = Progress.PROGRESS;
+               }
+               if (progress == Progress.PROGRESS) {
+                       _cond.wait (_mutex);
+                       progress = Progress.READY;
+               }
+               if (progress == Progress.READY) {
                        _mutex.unlock ();
-                       ret_future = _mapped;
-                       break;
-               default:
-                       assert_not_reached ();
+                       return _mapped.wait ();
                }
-               return ret_future.wait ();
+               assert_not_reached ();
        }
 
        public unowned bool wait_until (int64 end_time, out unowned G? value = null) {
-               bool ret_value;
                _mutex.lock ();
-               switch (_progress) {
-               case Progress.INIT:
-                       ret_value = go_map ().wait_until (end_time, out value);
-                       break;
-               case Progress.PROGRESS:
-                       if (ret_value = _cond.wait_until (_mutex, end_time)) {
-                               _mutex.unlock ();
-                               ret_value = _mapped.wait_until (end_time, out value);
-                       } else {
+               Progress progress = _progress;
+               if (progress == Progress.INIT) {
+                       Future<G> base_future = _base;
+                       _mutex.unlock ();
+                       if (!base_future.wait_until (end_time)) {
+                               return false;
+                       }
+                       _mutex.lock ();
+                       progress = Progress.PROGRESS;
+               }
+               if (progress == Progress.PROGRESS) {
+                       if (!_cond.wait_until (_mutex, end_time)) {
                                _mutex.unlock ();
-                               value = null;
+                               return false;
                        }
-                       break;
-               case Progress.READY:
+                       progress = Progress.READY;
+               }
+               if (progress == Progress.READY) {
+                       _mutex.unlock ();
+                       return _mapped.wait_until (end_time, out value);
+               }
+               assert_not_reached ();
+       }
+
+       public async unowned A wait_async () {
+               _mutex.lock ();
+               Progress progress = _progress;
+               if (progress == Progress.INIT) {
+                       Future<G> base_future = _base;
+                       _mutex.unlock ();
+                       yield base_future.wait_async ();
+                       _mutex.lock ();
+                       progress = Progress.PROGRESS;
+               }
+               if (progress == Progress.PROGRESS) {
+                       unowned A result = null;
+                       _when_done += Future.WhenDoneArrayElement<G>((res) => {
+                               wait_async.callback ();
+                       });
+                       progress = Progress.READY;
+               }
+               if (progress == Progress.READY) {
                        _mutex.unlock ();
-                       ret_value = _mapped.wait_until (end_time, out value);
-                       break;
-               default:
-                       assert_not_reached ();
+                       return yield _mapped.wait_async ();
                }
-               return ret_value;
+               assert_not_reached ();
        }
 
        public void when_done (Future.WhenDoneFunc<A> func) {
@@ -102,7 +125,7 @@ internal class Gee.FlatMapFuture<A, G> : Object, Future<A> {
                }
        }
 
-       private unowned Future<A> go_map () {
+       private unowned Future<A> go_map (G val) {
                _progress = Progress.PROGRESS;
                _mutex.unlock ();
 
index 5cb2130..1747795 100644 (file)
@@ -124,6 +124,8 @@ public interface Gee.Future<G> : Object {
         */
        public abstract void when_done (WhenDoneFunc<G> func);
 
+       public delegate A MapFunc<A, G> (G value);
+
        /**
         * Maps a future value to another value by a function and returns the
         * another value in future.
index 1bc13a4..3d3bb8d 100644 (file)
  */
 
 internal class Gee.MapFuture<A, G> : Object, Future<A> {
-       public MapFuture (Future<G> future_base, MapFunc<A, G> func) {
+       public MapFuture (Future<G> future_base, Future.MapFunc<A, G> func) {
                _base = future_base;
                _func = func;
-               _base.when_done (() => {
+               _base.when_done ((val) => {
                        _mutex.lock ();
                        if (_progress == Progress.INIT) {
-                               go_map ();
+                               go_map (val);
                        } else {
                                _mutex.unlock ();
                        }
@@ -37,87 +37,84 @@ internal class Gee.MapFuture<A, G> : Object, Future<A> {
        public bool ready {
                get {
                        _mutex.lock ();
-                       bool locked = _progress == Progress.READY;
+                       bool result = _progress == Progress.READY;
                        _mutex.unlock ();
-                       return locked;
+                       return result;
                }
        }
 
        public unowned A wait () {
-               unowned A ret_value;
                _mutex.lock ();
-               switch (_progress) {
-               case Progress.INIT:
-                       ret_value = go_map ();
-                       break;
-               case Progress.PROGRESS:
-                       _cond.wait (_mutex);
+               Progress progress = _progress;
+               if (progress == Progress.INIT) {
+                       Future<G> base_future = _base;
                        _mutex.unlock ();
-                       ret_value = _value;
-                       break;
-               case Progress.READY:
+                       base_future.wait ();
+                       _mutex.lock ();
+                       progress = Progress.PROGRESS;
+               }
+               if (progress == Progress.PROGRESS) {
+                       _cond.wait (_mutex);
+                       progress = Progress.READY;
+               }
+               if (progress == Progress.READY) {
                        _mutex.unlock ();
-                       ret_value = _value;
-                       break;
-               default:
-                       assert_not_reached ();
+                       return _value;
                }
-               return ret_value;
+               assert_not_reached ();
        }
 
-       public unowned bool wait_until (int64 end_time, out unowned G? value = null) {
-               bool ret_value;
+       public unowned bool wait_until (int64 end_time, out unowned A? value = null) {
                _mutex.lock ();
-               switch (_progress) {
-               case Progress.INIT:
-                       if (!_base.wait_until (end_time)) {
-                               _mutex.unlock ();
+               Progress progress = _progress;
+               if (progress == Progress.INIT) {
+                       Future<G> base_future = _base;
+                       _mutex.unlock ();
+                       if (!base_future.wait_until (end_time)) {
                                return false;
                        }
-                       value = go_map ();
-                       ret_value = true;
-                       break;
-               case Progress.PROGRESS:
-                       if (ret_value = _cond.wait_until (_mutex, end_time)) {
-                               _mutex.unlock ();
-                               value = _value;
-                       } else {
+                       _mutex.lock ();
+                       progress = Progress.PROGRESS;
+               }
+               if (progress == Progress.PROGRESS) {
+                       if (!_cond.wait_until (_mutex, end_time)) {
                                _mutex.unlock ();
+                               return false;
                        }
-                       break;
-               case Progress.READY:
+                       progress = Progress.READY;
+               }
+               if (progress == Progress.READY) {
                        _mutex.unlock ();
                        value = _value;
-                       ret_value = true;
-                       break;
-               default:
-                       assert_not_reached ();
+                       return true;
                }
-               return ret_value;
+               assert_not_reached ();
        }
 
        public async unowned A wait_async () {
-               unowned G g = yield _base.wait_async ();
                _mutex.lock ();
-               switch (_progress) {
-               case Progress.INIT:
-                       go_map ();
-                       return _value;
-               case Progress.PROGRESS:
+               Progress progress = _progress;
+               if (progress == Progress.INIT) {
+                       Future<G> base_future = _base;
+                       _mutex.unlock ();
+                       yield base_future.wait_async ();
+                       _mutex.lock ();
+                       progress = Progress.PROGRESS;
+               }
+               if (progress == Progress.PROGRESS) {
                        unowned A result = null;
                        _when_done += Future.WhenDoneArrayElement<G>((res) => {
-                               result = res;
                                wait_async.callback ();
                        });
                        _mutex.unlock ();
                        yield;
                        return _value;
-               case Progress.READY:
+               }
+               if (progress == Progress.READY) {
                        _mutex.unlock ();
                        return _value;
-               default:
-                       assert_not_reached ();
                }
+               assert_not_reached ();
        }
 
        public void when_done (Future.WhenDoneFunc<A> func) {
@@ -131,11 +128,11 @@ internal class Gee.MapFuture<A, G> : Object, Future<A> {
                }
        }
 
-       private inline unowned A go_map () {
+       private inline unowned A go_map (G val) {
                _progress = Progress.PROGRESS;
                _mutex.unlock ();
 
-               A tmp_value = _func (_base.value);
+               A tmp_value = _func (val);
                unowned A value = tmp_value;
 
                _mutex.lock ();
@@ -162,7 +159,7 @@ internal class Gee.MapFuture<A, G> : Object, Future<A> {
        private Mutex _mutex = Mutex ();
        private Cond _cond = Cond ();
        private Future<G> _base;
-       private MapFunc<A, G> _func;
+       private Future.MapFunc<A, G> _func;
        private A _value;
        private Progress _progress = Progress.INIT;
        private Future.WhenDoneArrayElement<G>[]? _when_done = new Future.WhenDoneArrayElement<G>[0];