| 1258 | |
| 1259 | template <typename T> |
| 1260 | bool Future<T>::await(const Duration& duration) const |
| 1261 | { |
| 1262 | // NOTE: We need to preemptively allocate the Latch on the stack |
| 1263 | // instead of lazily create it in the critical section below because |
| 1264 | // instantiating a Latch requires creating a new process (at the |
| 1265 | // time of writing this comment) which might need to do some |
| 1266 | // synchronization in libprocess which might deadlock if some other |
| 1267 | // code in libprocess is already holding a lock and then attempts to |
| 1268 | // do Promise::set (or something similar) that attempts to acquire |
| 1269 | // the lock that we acquire here. This is an artifact of using |
| 1270 | // Future/Promise within the implementation of libprocess. |
| 1271 | // |
| 1272 | // We mostly only call 'await' in tests so this should not be a |
| 1273 | // performance concern. |
| 1274 | Owned<Latch> latch(new Latch()); |
| 1275 | |
| 1276 | bool pending = false; |
| 1277 | |
| 1278 | synchronized (data->lock) { |
| 1279 | if (data->state == PENDING) { |
| 1280 | pending = true; |
| 1281 | data->onAnyCallbacks.push_back(lambda::bind(&internal::awaited, latch)); |
| 1282 | } |
| 1283 | } |
| 1284 | |
| 1285 | if (pending) { |
| 1286 | return latch->await(duration); |
| 1287 | } |
| 1288 | |
| 1289 | return true; |
| 1290 | } |
| 1291 | |
| 1292 | |
| 1293 | template <typename T> |