0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2025-02-18 09:40:12 +01:00

ircd:Ⓜ️:vm: Add vm::notify interface w/ yielding wait for event_id.

This commit is contained in:
Jason Volk 2023-02-05 13:42:46 -08:00
parent dc873d8c8f
commit 9ecf389007
4 changed files with 167 additions and 0 deletions

View file

@ -0,0 +1,43 @@
// The Construct
//
// Copyright (C) The Construct Developers, Authors & Contributors
// Copyright (C) 2016-2023 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
#pragma once
#define HAVE_IRCD_M_VM_NOTIFY_H
namespace ircd::m::vm::notify
{
using value_type = std::pair<const event::id, ctx::ctx *>;
using alloc_type = allocator::node<value_type>;
using map_type = std::multimap<event::id, ctx::ctx *, std::less<>, alloc_type::allocator>;
extern map_type map;
size_t wait(const vector_view<const event::id> &, const milliseconds);
bool wait(const event::id &, const milliseconds);
}
/// Yields ctx until event was successfully evaluated. Returns false if
/// timeout occurred.
inline bool
ircd::m::vm::notify::wait(const event::id &event_id,
const milliseconds to)
{
const vector_view<const event::id> vector
(
&event_id, 1
);
const auto count
{
wait(vector, to)
};
return count;
}

View file

@ -28,6 +28,7 @@ namespace ircd::m::vm
#include "opts.h"
#include "eval.h"
#include "seq.h"
#include "notify.h"
namespace ircd::m::vm
{

View file

@ -185,6 +185,7 @@ libircd_matrix_la_SOURCES += vm_inject.cc
libircd_matrix_la_SOURCES += vm_execute.cc
libircd_matrix_la_SOURCES += vm_fetch.cc
libircd_matrix_la_SOURCES += vm_conforms.cc
libircd_matrix_la_SOURCES += vm_notify.cc
libircd_matrix_la_SOURCES += init_backfill.cc
libircd_matrix_la_SOURCES += homeserver.cc
libircd_matrix_la_SOURCES += homeserver_bootstrap.cc

122
matrix/vm_notify.cc Normal file
View file

@ -0,0 +1,122 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2023 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
namespace ircd::m::vm::notify
{
static void hook_handle(const m::event &, vm::eval &);
extern hookfn<vm::eval &> hook;
extern alloc_type alloc;
extern map_type map;
}
decltype(ircd::m::vm::notify::alloc)
ircd::m::vm::notify::alloc;
decltype(ircd::m::vm::notify::map)
ircd::m::vm::notify::map
{
alloc
};
decltype(ircd::m::vm::notify::hook)
ircd::m::vm::notify::hook
{
hook_handle,
{
{ "_site", "vm.notify" }
}
};
/// Yields ctx until all events were successfully evaluated or timeout.
/// Returns the count of events which were successfully evaluated.
size_t
ircd::m::vm::notify::wait(const vector_view<const event::id> &event_id,
const milliseconds to)
{
using iterator_type = unique_iterator<map_type>;
using node_type = std::pair<map_type::node_type, value_type>;
static const size_t max_ids
{
64
};
assume(event_id.size() <= max_ids);
const auto event_ids
{
std::min(event_id.size(), max_ids)
};
const uint64_t exists_mask
{
m::exists(event_id)
};
size_t exists(0);
node_type node[max_ids];
iterator_type it[event_ids];
for(size_t i(0); i < event_ids; ++i)
{
if(exists_mask & (1UL << i))
{
exists++;
continue;
}
const auto &s
{
map.get_allocator().s
};
assert(s);
assert(!s->next);
const scope_restore next
{
s->next, reinterpret_cast<value_type *>(node + i)
};
it[i] =
{
map, map.emplace(event_id[i], ctx::current)
};
}
bool timeout(false);
const auto tp(now<system_point>() + to);
while(exists < event_ids && !timeout)
{
timeout = ctx::wait_until(tp, std::nothrow);
exists = m::exists_count(event_id);
}
assert(exists <= event_ids);
return exists;
}
void
ircd::m::vm::notify::hook_handle(const m::event &event,
vm::eval &)
{
auto pit
{
map.equal_range(event.event_id)
};
for(; pit.first != pit.second; ++pit.first)
{
const auto &[event_id, ctx] {*pit.first};
assert(event_id == event.event_id);
assert(ctx != nullptr);
ctx::notify(*ctx);
}
}