diff --git a/include/ircd/m/vm/notify.h b/include/ircd/m/vm/notify.h index 26f4b350c..e5d168f49 100644 --- a/include/ircd/m/vm/notify.h +++ b/include/ircd/m/vm/notify.h @@ -13,9 +13,10 @@ namespace ircd::m::vm::notify { - using value_type = std::pair; + using value_type = std::pair *>; using alloc_type = allocator::node; - using map_type = std::multimap, alloc_type::allocator>; + using map_type = std::multimap *, std::less<>, alloc_type::allocator>; + using node_type = std::pair; extern map_type map; diff --git a/matrix/vm_notify.cc b/matrix/vm_notify.cc index aa3d4888c..dc258ff05 100644 --- a/matrix/vm_notify.cc +++ b/matrix/vm_notify.cc @@ -42,12 +42,7 @@ ircd::m::vm::notify::wait(const vector_view &event_id, const milliseconds to) { using iterator_type = unique_iterator; - using node_type = std::pair; - - static const size_t max_ids - { - 64 - }; + static const size_t max_ids {64}; assume(event_id.size() <= max_ids); const auto event_ids @@ -60,14 +55,15 @@ ircd::m::vm::notify::wait(const vector_view &event_id, m::exists(event_id) }; - size_t exists(0); node_type node[max_ids]; iterator_type it[event_ids]; + ctx::future<> future[event_ids]; + ctx::promise<> promise[event_ids]; for(size_t i(0); i < event_ids; ++i) { if(exists_mask & (1UL << i)) { - exists++; + future[i] = ctx::future<>{ctx::already}; continue; } @@ -85,17 +81,32 @@ ircd::m::vm::notify::wait(const vector_view &event_id, it[i] = { - map, map.emplace(event_id[i], ctx::current) + map, map.emplace(event_id[i], promise + i) + }; + + assert(it[i]->second); + future[i] = ctx::future<> + { + *it[i]->second }; } - bool timeout(false); - const auto tp(now() + to); - while(exists < event_ids && !timeout) + auto all { - timeout = ctx::wait_until(tp, std::nothrow); - exists = m::exists_count(event_id); - } + ctx::when_all(future, future + event_ids) + }; + + const bool ok + { + all.wait_until(now() + to, std::nothrow) + }; + + const size_t exists + { + !ok? + m::exists_count(event_id): + event_ids + }; assert(exists <= event_ids); return exists; @@ -112,11 +123,13 @@ ircd::m::vm::notify::hook_handle(const m::event &event, for(; pit.first != pit.second; ++pit.first) { - const auto &[event_id, ctx] {*pit.first}; + const auto &[event_id, promise] {*pit.first}; + assert(promise); + assert(promise->valid()); assert(event_id == event.event_id); - assert(ctx != nullptr); - ctx::notify(*ctx); + if(likely(*promise)) + promise->set_value(); } }