19 typename std::enable_if<std::is_same<
decltype(output.get()), Context::Builder>::value>::type* enable =
nullptr)
30 GuardedRef{thread_context.waiter->m_mutex, thread_context.callback_threads}, &connection,
31 [&] {
return connection.m_threads.add(kj::heap<
ProxyServer<Thread>>(connection, thread_context, std::thread{})); })};
36 auto make_request_thread{[&]{
43 auto request = connection.m_thread_map.makeThreadRequest();
44 request.setName(thread_context.thread_name);
45 return request.send().getResult();
48 GuardedRef{thread_context.waiter->m_mutex, thread_context.request_threads},
49 &connection, make_request_thread)};
51 auto context = output.init();
52 context.setThread(request_thread->second->m_client);
53 context.setCallbackThread(callback_thread->second->m_client);
60 typename std::enable_if<
61 std::is_same<
decltype(Accessor::get(server_context.call_context.getParams())), Context::Reader>::value,
62 kj::Promise<typename ServerContext::CallContext>>::type
64 auto& server = server_context.proxy_server;
66 int req = server_context.req;
73 auto self = server.thisCap();
74 auto invoke = [self = kj::mv(self), call_context = kj::mv(server_context.call_context), &server, &loop,
req, fn,
args...](
CancelMonitor& cancel_monitor)
mutable {
97 auto& request_threads = thread_context.request_threads;
101 Lock cancel_lock{cancel_mutex};
105 if (cancel_monitor.m_canceled) {
110 assert(!cancel_monitor.m_on_cancel);
111 cancel_monitor.m_on_cancel = [&loop, &server_context, &cancel_mutex,
req]() {
112 MP_LOG(loop,
Log::Info) <<
"IPC server request #" <<
req <<
" canceled while executing.";
124 Lock cancel_lock{cancel_mutex};
125 server_context.request_canceled =
true;
131 std::tie(request_thread, inserted) =
SetThread(
132 GuardedRef{thread_context.waiter->m_mutex, request_threads}, server.m_context.connection,
133 [&] {
return Accessor::get(call_context.getParams()).getCallbackThread(); });
141 const bool erase_thread{inserted};
150 cancel_lock.
m_lock.unlock();
165 cancel_monitor.m_on_cancel = nullptr;
166 auto self_dispose{kj::mv(self)};
174 ConnThreads::node_type removed;
176 Lock lock(thread_context.waiter->m_mutex);
177 removed = request_threads.extract(server.m_context.connection);
182 if (server_context.request_canceled) {
183 MP_LOG(loop,
Log::Info) <<
"IPC server request #" <<
req <<
" canceled before it could be executed";
184 }
else KJ_IF_MAYBE(exception, kj::runCatchingExceptions([&]{
186 fn.invoke(server_context,
args...);
191 MP_LOG(loop,
Log::Error) <<
"IPC server request #" <<
req <<
" uncaught exception (" << kj::str(*exception).cStr() <<
")";
192 kj::throwRecoverableException(kj::mv(*exception));
201 const auto& params = server_context.call_context.getParams();
202 Context::Reader context_arg = Accessor::get(params);
203 if (!context_arg.hasThread()) {
206 auto* connection = server.m_context.connection;
207 auto& pool = connection->m_thread_pool;
210 <<
"IPC server error request #" <<
req <<
", no thread specified and no pool configured";
211 throw std::runtime_error(
"no thread specified and no pool configured");
213 auto* slot = &pool[0];
214 for (
size_t i = 1; i < pool.size(); ++i) {
215 if (pool[i].depth < slot->depth) slot = &pool[i];
218 auto result = connection->m_threads.getLocalServer(slot->client)
219 .then([&loop, invoke = kj::mv(invoke),
req](
const kj::Maybe<Thread::Server&>& perhaps)
mutable -> kj::Promise<typename ServerContext::CallContext> {
220 KJ_IF_MAYBE (thread_server, perhaps) {
223 <<
"IPC server post request #" <<
req <<
" {" << thread.m_thread_context.thread_name <<
"}";
224 return thread.template post<typename ServerContext::CallContext>(std::move(invoke));
227 <<
"IPC server error request #" <<
req <<
", pool thread not found";
228 throw std::runtime_error(
"pool thread not found");
231 .attach(kj::defer([slot] { --slot->depth; }));
232 return connection->m_canceler.wrap(kj::mv(result));
234 auto thread_client = context_arg.getThread();
235 auto result = server.m_context.connection->m_threads.getLocalServer(thread_client)
236 .then([&loop, invoke = kj::mv(invoke),
req](
const kj::Maybe<Thread::Server&>& perhaps)
mutable {
240 KJ_IF_MAYBE (thread_server, perhaps) {
243 <<
"IPC server post request #" <<
req <<
" {" << thread.m_thread_context.thread_name <<
"}";
244 return thread.template post<typename ServerContext::CallContext>(std::move(invoke));
247 <<
"IPC server error request #" <<
req <<
", missing thread to execute request";
248 throw std::runtime_error(
"invalid thread handle");
250 }, [&loop,
req](::kj::Exception&& e) -> kj::Promise<typename ServerContext::CallContext> {
282 <<
"IPC server error request #" <<
req <<
" CapabilityServerSet<Thread>::getLocalServer call failed, did you forget to provide a ThreadMap to the client prior to this IPC call?";
290 return server.m_context.connection->m_canceler.wrap(kj::mv(result));
auto PassField(Priority< 1 >, TypeList< LocalType & >, ServerContext &server_context, Fn &&fn, Args &&... args) -> Require< typename decltype(Accessor::get(server_context.call_context.getParams()))::Calls >
PassField override for callable interface reference arguments.
ThreadContext & thread_context