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:
parent
dc873d8c8f
commit
9ecf389007
4 changed files with 167 additions and 0 deletions
43
include/ircd/m/vm/notify.h
Normal file
43
include/ircd/m/vm/notify.h
Normal 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;
|
||||
}
|
|
@ -28,6 +28,7 @@ namespace ircd::m::vm
|
|||
#include "opts.h"
|
||||
#include "eval.h"
|
||||
#include "seq.h"
|
||||
#include "notify.h"
|
||||
|
||||
namespace ircd::m::vm
|
||||
{
|
||||
|
|
|
@ -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
122
matrix/vm_notify.cc
Normal 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);
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue