| 54 | } |
| 55 | |
| 56 | Future<T> get() |
| 57 | { |
| 58 | Future<T> future; |
| 59 | |
| 60 | synchronized (data->lock) { |
| 61 | if (data->elements.empty()) { |
| 62 | data->promises.emplace_back(new Promise<T>()); |
| 63 | future = data->promises.back()->future(); |
| 64 | } else { |
| 65 | T t = std::move(data->elements.front()); |
| 66 | data->elements.pop(); |
| 67 | return Future<T>(std::move(t)); |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | // If there were no items available, we set up a discard |
| 72 | // handler. This is done here to minimize the amount of |
| 73 | // work done within the critical section above. |
| 74 | auto weak_data = std::weak_ptr<Data>(data); |
| 75 | |
| 76 | future.onDiscard([weak_data, future]() { |
| 77 | auto data = weak_data.lock(); |
| 78 | if (!data) { |
| 79 | return; |
| 80 | } |
| 81 | |
| 82 | synchronized (data->lock) { |
| 83 | for (auto it = data->promises.begin(); |
| 84 | it != data->promises.end(); |
| 85 | ++it) { |
| 86 | if ((*it)->future() == future) { |
| 87 | (*it)->discard(); |
| 88 | data->promises.erase(it); |
| 89 | break; |
| 90 | } |
| 91 | } |
| 92 | } |
| 93 | }); |
| 94 | |
| 95 | return future; |
| 96 | } |
| 97 | |
| 98 | size_t size() const |
| 99 | { |