| 850 | |
| 851 | template <typename T> |
| 852 | bool Promise<T>::associate(const Future<T>& future) |
| 853 | { |
| 854 | bool associated = false; |
| 855 | |
| 856 | synchronized (f.data->lock) { |
| 857 | // Don't associate if this promise has completed. Note that this |
| 858 | // does not include if Future::discard was called on this future |
| 859 | // since in that case that would still leave the future PENDING |
| 860 | // (note that we cover that case below). |
| 861 | if (f.data->state == Future<T>::PENDING && !f.data->associated) { |
| 862 | associated = f.data->associated = true; |
| 863 | |
| 864 | // After this point we don't allow 'f' to be completed via the |
| 865 | // promise since we've set 'associated' but Future::discard on |
| 866 | // 'f' might get called which will get propagated via the |
| 867 | // 'f.onDiscard' below. Note that we currently don't propagate a |
| 868 | // discard from 'future.onDiscard' but these semantics might |
| 869 | // change if/when we make 'f' and 'future' true aliases of one |
| 870 | // another. |
| 871 | } |
| 872 | } |
| 873 | |
| 874 | // Note that we do the actual associating after releasing the lock |
| 875 | // above to avoid deadlocking by attempting to require the lock |
| 876 | // within from invoking 'f.onDiscard' and/or 'f.set/fail' via the |
| 877 | // bind statements from doing 'future.onReady/onFailed'. |
| 878 | if (associated) { |
| 879 | // TODO(jieyu): Make 'f' a true alias of 'future'. Currently, only |
| 880 | // 'discard' is associated in both directions. In other words, if |
| 881 | // a future gets discarded, the other future will also get |
| 882 | // discarded. For 'set' and 'fail', they are associated only in |
| 883 | // one direction. In other words, calling 'set' or 'fail' on this |
| 884 | // promise will not affect the result of the future that we |
| 885 | // associated. |
| 886 | f.onDiscard(lambda::bind(&internal::discard<T>, WeakFuture<T>(future))); |
| 887 | |
| 888 | // Need to disambiguate for the compiler. |
| 889 | bool (Future<T>::*set)(const T&) = &Future<T>::set; |
| 890 | |
| 891 | future |
| 892 | .onReady(lambda::bind(set, f, lambda::_1)) |
| 893 | .onFailed(lambda::bind(&Future<T>::fail, f, lambda::_1)) |
| 894 | .onDiscarded(lambda::bind(&internal::discarded<T>, f)) |
| 895 | .onAbandoned(lambda::bind(&Future<T>::abandon, f, true)); |
| 896 | } |
| 897 | |
| 898 | return associated; |
| 899 | } |
| 900 | |
| 901 | |
| 902 | template <typename T> |