Bitcoin Core 30.99.0
P2P Digital Currency
proxy-io.h
Go to the documentation of this file.
1// Copyright (c) The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#ifndef MP_PROXY_IO_H
6#define MP_PROXY_IO_H
7
8#include <mp/proxy.h>
9#include <mp/util.h>
10
11#include <mp/proxy.capnp.h>
12
13#include <capnp/rpc-twoparty.h>
14
15#include <assert.h>
16#include <condition_variable>
17#include <functional>
18#include <kj/function.h>
19#include <map>
20#include <memory>
21#include <optional>
22#include <sstream>
23#include <string>
24#include <thread>
25
26namespace mp {
27struct ThreadContext;
28
30{
32};
33
35{
39 {
40 }
41};
42
43template <typename ProxyServer, typename CallContext_>
45{
46 using CallContext = CallContext_;
47
50 int req;
51
54 {
55 }
56};
57
58template <typename Interface, typename Params, typename Results>
59using ServerContext = ServerInvokeContext<ProxyServer<Interface>, ::capnp::CallContext<Params, Results>>;
60
61template <>
62struct ProxyClient<Thread> : public ProxyClientBase<Thread, ::capnp::Void>
63{
65 // https://stackoverflow.com/questions/22357887/comparing-two-mapiterators-why-does-it-need-the-copy-constructor-of-stdpair
66 ProxyClient(const ProxyClient&) = delete;
68
78 std::optional<CleanupIt> m_disconnect_cb;
79};
80
81template <>
82struct ProxyServer<Thread> final : public Thread::Server
83{
84public:
85 ProxyServer(ThreadContext& thread_context, std::thread&& thread);
87 kj::Promise<void> getName(GetNameContext context) override;
89 std::thread m_thread;
90};
91
93class LoggingErrorHandler : public kj::TaskSet::ErrorHandler
94{
95public:
97 void taskFailed(kj::Exception&& exception) override;
99};
100
102enum class Log {
103 Trace = 0,
104 Debug,
105 Info,
106 Warning,
107 Error,
108 Raise,
109};
110
111kj::StringPtr KJ_STRINGIFY(Log flags);
112
114
116 std::string message;
117
120};
121
122using LogFn = std::function<void(LogMessage)>;
123
125
128
131 size_t max_chars{200};
132
136};
137
139{
140public:
141 Logger(const LogOptions& options, Log log_level) : m_options(options), m_log_level(log_level) {}
142
143 Logger(Logger&&) = delete;
144 Logger& operator=(Logger&&) = delete;
145 Logger(const Logger&) = delete;
146 Logger& operator=(const Logger&) = delete;
147
148 ~Logger() noexcept(false)
149 {
150 if (enabled()) m_options.log_fn({std::move(m_buffer).str(), m_log_level});
151 }
152
153 template <typename T>
154 friend Logger& operator<<(Logger& logger, T&& value)
156 if (logger.enabled()) logger.m_buffer << std::forward<T>(value);
157 return logger;
158 }
159
160 template <typename T>
161 friend Logger& operator<<(Logger&& logger, T&& value)
162 {
163 return logger << std::forward<T>(value);
164 }
165
166 explicit operator bool() const
167 {
168 return enabled();
169 }
170
171private:
172 bool enabled() const
173 {
175 }
176
179 std::ostringstream m_buffer;
180};
181
182#define MP_LOGPLAIN(loop, ...) if (mp::Logger logger{(loop).m_log_opts, __VA_ARGS__}; logger) logger
183
184#define MP_LOG(loop, ...) MP_LOGPLAIN(loop, __VA_ARGS__) << "{" << LongThreadName((loop).m_exe_name) << "} "
185
186std::string LongThreadName(const char* exe_name);
187
214{
215public:
217 EventLoop(const char* exe_name, LogFn log_fn, void* context = nullptr)
218 : EventLoop(exe_name, LogOptions{std::move(log_fn)}, context){}
219
221 EventLoop(const char* exe_name, LogOptions log_opts, void* context = nullptr);
222
224 EventLoop(const char* exe_name, std::function<void(bool, std::string)> old_callback, void* context = nullptr)
225 : EventLoop(exe_name,
226 LogFn{[old_callback = std::move(old_callback)](LogMessage log_data) {old_callback(log_data.level == Log::Raise, std::move(log_data.message));}},
227 context){}
228
229 ~EventLoop();
230
234 void loop();
235
238 void post(kj::Function<void()> fn);
239
243 template <typename Callable>
244 void sync(Callable&& callable)
245 {
246 post(std::forward<Callable>(callable));
247 }
248
251 void addAsyncCleanup(std::function<void()> fn);
252
264 void startAsyncThread() MP_REQUIRES(m_mutex);
265
267 bool done() const MP_REQUIRES(m_mutex);
268
271 const char* m_exe_name;
272
274 std::thread::id m_thread_id = std::this_thread::get_id();
275
278 std::thread m_async_thread;
279
281 kj::Function<void()>* m_post_fn MP_GUARDED_BY(m_mutex) = nullptr;
282
284 std::optional<CleanupList> m_async_fns MP_GUARDED_BY(m_mutex);
285
287 int m_wait_fd = -1;
288
290 int m_post_fd = -1;
291
294 int m_num_clients MP_GUARDED_BY(m_mutex) = 0;
295
298 Mutex m_mutex;
299 std::condition_variable m_cv;
300
302 kj::AsyncIoContext m_io_context;
303
305 LoggingErrorHandler m_error_handler{*this};
306
308 std::unique_ptr<kj::TaskSet> m_task_set;
309
311 std::list<Connection> m_incoming_connections;
312
315
318};
319
326struct Waiter
327{
328 Waiter() = default;
329
330 template <typename Fn>
331 bool post(Fn&& fn)
332 {
333 const Lock lock(m_mutex);
334 if (m_fn) return false;
335 m_fn = std::forward<Fn>(fn);
336 m_cv.notify_all();
337 return true;
338 }
339
340 template <class Predicate>
341 void wait(Lock& lock, Predicate pred)
342 {
343 m_cv.wait(lock.m_lock, [&]() MP_REQUIRES(m_mutex) {
344 // Important for this to be "while (m_fn)", not "if (m_fn)" to avoid
345 // a lost-wakeup bug. A new m_fn and m_cv notification might be sent
346 // after the fn() call and before the lock.lock() call in this loop
347 // in the case where a capnp response is sent and a brand new
348 // request is immediately received.
349 while (m_fn) {
350 auto fn = std::move(*m_fn);
351 m_fn.reset();
352 Unlock(lock, fn);
353 }
354 const bool done = pred();
355 return done;
356 });
357 }
358
367 std::condition_variable m_cv;
368 std::optional<kj::Function<void()>> m_fn MP_GUARDED_BY(m_mutex);
369};
370
377{
378public:
379 Connection(EventLoop& loop, kj::Own<kj::AsyncIoStream>&& stream_)
380 : m_loop(loop), m_stream(kj::mv(stream_)),
381 m_network(*m_stream, ::capnp::rpc::twoparty::Side::CLIENT, ::capnp::ReaderOptions()),
382 m_rpc_system(::capnp::makeRpcClient(m_network)) {}
384 kj::Own<kj::AsyncIoStream>&& stream_,
385 const std::function<::capnp::Capability::Client(Connection&)>& make_client)
386 : m_loop(loop), m_stream(kj::mv(stream_)),
387 m_network(*m_stream, ::capnp::rpc::twoparty::Side::SERVER, ::capnp::ReaderOptions()),
388 m_rpc_system(::capnp::makeRpcServer(m_network, make_client(*this))) {}
389
395 ~Connection();
396
400 CleanupIt addSyncCleanup(std::function<void()> fn);
401 void removeSyncCleanup(CleanupIt it);
402
404 template <typename F>
405 void onDisconnect(F&& f)
406 {
407 // Add disconnect handler to local TaskSet to ensure it is cancelled and
408 // will never run after connection object is destroyed. But when disconnect
409 // handler fires, do not call the function f right away, instead add it
410 // to the EventLoop TaskSet to avoid "Promise callback destroyed itself"
411 // error in cases where f deletes this Connection object.
412 m_on_disconnect.add(m_network.onDisconnect().then(
413 [f = std::forward<F>(f), this]() mutable { m_loop->m_task_set->add(kj::evalLater(kj::mv(f))); }));
414 }
415
417 kj::Own<kj::AsyncIoStream> m_stream;
418 LoggingErrorHandler m_error_handler{*m_loop};
419 kj::TaskSet m_on_disconnect{m_error_handler};
420 ::capnp::TwoPartyVatNetwork m_network;
421 std::optional<::capnp::RpcSystem<::capnp::rpc::twoparty::VatId>> m_rpc_system;
422
423 // ThreadMap interface client, used to create a remote server thread when an
424 // client IPC call is being made for the first time from a new thread.
425 ThreadMap::Client m_thread_map{nullptr};
426
429 ::capnp::CapabilityServerSet<Thread> m_threads;
430
435};
436
446{
447 ::capnp::word scratch[4]{};
448 ::capnp::MallocMessageBuilder message{scratch};
449 ::capnp::rpc::twoparty::VatId::Builder vat_id{message.getRoot<::capnp::rpc::twoparty::VatId>()};
450 ServerVatId() { vat_id.setSide(::capnp::rpc::twoparty::Side::SERVER); }
451};
452
453template <typename Interface, typename Impl>
455 Connection* connection,
456 bool destroy_connection)
457 : m_client(std::move(client)), m_context(connection)
458
459{
460 // Handler for the connection getting destroyed before this client object.
461 auto disconnect_cb = m_context.connection->addSyncCleanup([this]() {
462 // Release client capability by move-assigning to temporary.
463 {
464 typename Interface::Client(std::move(m_client));
465 }
466 Lock lock{m_context.loop->m_mutex};
467 m_context.connection = nullptr;
468 });
469
470 // Two shutdown sequences are supported:
471 //
472 // - A normal sequence where client proxy objects are deleted by external
473 // code that no longer needs them
474 //
475 // - A garbage collection sequence where the connection or event loop shuts
476 // down while external code is still holding client references.
477 //
478 // The first case is handled here when m_context.connection is not null. The
479 // second case is handled by the disconnect_cb function, which sets
480 // m_context.connection to null so nothing happens here.
481 m_context.cleanup_fns.emplace_front([this, destroy_connection, disconnect_cb]{
482 {
483 // If the capnp interface defines a destroy method, call it to destroy
484 // the remote object, waiting for it to be deleted server side. If the
485 // capnp interface does not define a destroy method, this will just call
486 // an empty stub defined in the ProxyClientBase class and do nothing.
487 Sub::destroy(*this);
488
489 // FIXME: Could just invoke removed addCleanup fn here instead of duplicating code
490 m_context.loop->sync([&]() {
491 // Remove disconnect callback on cleanup so it doesn't run and try
492 // to access this object after it's destroyed. This call needs to
493 // run inside loop->sync() on the event loop thread because
494 // otherwise, if there were an ill-timed disconnect, the
495 // onDisconnect handler could fire and delete the Connection object
496 // before the removeSyncCleanup call.
498
499 // Release client capability by move-assigning to temporary.
500 {
501 typename Interface::Client(std::move(m_client));
502 }
503 if (destroy_connection) {
504 delete m_context.connection;
505 m_context.connection = nullptr;
506 }
507 });
508 }
509 });
510 Sub::construct(*this);
511}
512
513template <typename Interface, typename Impl>
515{
516 CleanupRun(m_context.cleanup_fns);
517}
518
519template <typename Interface, typename Impl>
520ProxyServerBase<Interface, Impl>::ProxyServerBase(std::shared_ptr<Impl> impl, Connection& connection)
521 : m_impl(std::move(impl)), m_context(&connection)
522{
523 assert(m_impl);
524}
525
538template <typename Interface, typename Impl>
540{
541 if (m_impl) {
542 // If impl is non-null at this point, it means no client is waiting for
543 // the m_impl server object to be destroyed synchronously. This can
544 // happen either if the interface did not define a "destroy" method (see
545 // invokeDestroy method below), or if a destroy method was defined, but
546 // the connection was broken before it could be called.
547 //
548 // In either case, be conservative and run the cleanup on an
549 // asynchronous thread, to avoid destructors or cleanup functions
550 // blocking or deadlocking the current EventLoop thread, since they
551 // could be making IPC calls.
552 //
553 // Technically this is a little too conservative since if the interface
554 // defines a "destroy" method, but the destroy method does not accept a
555 // Context parameter specifying a worker thread, the cleanup method
556 // would run on the EventLoop thread normally (when connection is
557 // unbroken), but will not run on the EventLoop thread now (when
558 // connection is broken). Probably some refactoring of the destructor
559 // and invokeDestroy function is possible to make this cleaner and more
560 // consistent.
561 m_context.loop->addAsyncCleanup([impl=std::move(m_impl), fns=std::move(m_context.cleanup_fns)]() mutable {
562 impl.reset();
563 CleanupRun(fns);
564 });
565 }
566 assert(m_context.cleanup_fns.empty());
567}
568
586template <typename Interface, typename Impl>
588{
589 m_impl.reset();
590 CleanupRun(m_context.cleanup_fns);
591}
592
599using ConnThreads = std::map<Connection*, std::optional<ProxyClient<Thread>>>;
600using ConnThread = ConnThreads::iterator;
601
602// Retrieve ProxyClient<Thread> object associated with this connection from a
603// map, or create a new one and insert it into the map. Return map iterator and
604// inserted bool.
605std::tuple<ConnThread, bool> SetThread(GuardedRef<ConnThreads> threads, Connection* connection, const std::function<Thread::Client()>& make_thread);
606
621{
623 std::string thread_name;
624
640 std::unique_ptr<Waiter> waiter = nullptr;
641
659 ConnThreads callback_threads MP_GUARDED_BY(waiter->m_mutex);
660
670 ConnThreads request_threads MP_GUARDED_BY(waiter->m_mutex);
671
675 bool loop_thread = false;
676};
677
681template <typename InitInterface>
682std::unique_ptr<ProxyClient<InitInterface>> ConnectStream(EventLoop& loop, int fd)
683{
684 typename InitInterface::Client init_client(nullptr);
685 std::unique_ptr<Connection> connection;
686 loop.sync([&] {
687 auto stream =
688 loop.m_io_context.lowLevelProvider->wrapSocketFd(fd, kj::LowLevelAsyncIoProvider::TAKE_OWNERSHIP);
689 connection = std::make_unique<Connection>(loop, kj::mv(stream));
690 init_client = connection->m_rpc_system->bootstrap(ServerVatId().vat_id).castAs<InitInterface>();
691 Connection* connection_ptr = connection.get();
692 connection->onDisconnect([&loop, connection_ptr] {
693 MP_LOG(loop, Log::Warning) << "IPC client: unexpected network disconnect.";
694 delete connection_ptr;
695 });
696 });
697 return std::make_unique<ProxyClient<InitInterface>>(
698 kj::mv(init_client), connection.release(), /* destroy_connection= */ true);
699}
700
705template <typename InitInterface, typename InitImpl>
706void _Serve(EventLoop& loop, kj::Own<kj::AsyncIoStream>&& stream, InitImpl& init)
707{
708 loop.m_incoming_connections.emplace_front(loop, kj::mv(stream), [&](Connection& connection) {
709 // Disable deleter so proxy server object doesn't attempt to delete the
710 // init implementation when the proxy client is destroyed or
711 // disconnected.
712 return kj::heap<ProxyServer<InitInterface>>(std::shared_ptr<InitImpl>(&init, [](InitImpl*){}), connection);
713 });
714 auto it = loop.m_incoming_connections.begin();
715 it->onDisconnect([&loop, it] {
716 MP_LOG(loop, Log::Info) << "IPC server: socket disconnected.";
717 loop.m_incoming_connections.erase(it);
718 });
719}
720
724template <typename InitInterface, typename InitImpl>
725void _Listen(EventLoop& loop, kj::Own<kj::ConnectionReceiver>&& listener, InitImpl& init)
726{
727 auto* ptr = listener.get();
728 loop.m_task_set->add(ptr->accept().then(
729 [&loop, &init, listener = kj::mv(listener)](kj::Own<kj::AsyncIoStream>&& stream) mutable {
730 _Serve<InitInterface>(loop, kj::mv(stream), init);
731 _Listen<InitInterface>(loop, kj::mv(listener), init);
732 }));
733}
734
737template <typename InitInterface, typename InitImpl>
738void ServeStream(EventLoop& loop, int fd, InitImpl& init)
739{
740 _Serve<InitInterface>(
741 loop, loop.m_io_context.lowLevelProvider->wrapSocketFd(fd, kj::LowLevelAsyncIoProvider::TAKE_OWNERSHIP), init);
742}
743
746template <typename InitInterface, typename InitImpl>
748{
749 loop.sync([&]() {
750 _Listen<InitInterface>(loop,
751 loop.m_io_context.lowLevelProvider->wrapListenSocketFd(fd, kj::LowLevelAsyncIoProvider::TAKE_OWNERSHIP),
752 init);
753 });
754}
755
756extern thread_local ThreadContext g_thread_context; // NOLINT(bitcoin-nontrivial-threadlocal)
757// Silence nonstandard bitcoin tidy error "Variable with non-trivial destructor
758// cannot be thread_local" which should not be a problem on modern platforms, and
759// could lead to a small memory leak at worst on older ones.
760
761} // namespace mp
762
763#endif // MP_PROXY_IO_H
if(!SetupNetworking())
int flags
Definition: bitcoin-tx.cpp:529
Object holding network & rpc state associated with either an incoming server connection,...
Definition: proxy-io.h:377
CleanupIt addSyncCleanup(std::function< void()> fn)
Register synchronous cleanup function to run on event loop thread (with access to capnp thread local ...
Definition: proxy.cpp:149
EventLoopRef m_loop
Definition: proxy-io.h:416
::capnp::TwoPartyVatNetwork m_network
Definition: proxy-io.h:420
kj::Own< kj::AsyncIoStream > m_stream
Definition: proxy-io.h:417
Connection(EventLoop &loop, kj::Own< kj::AsyncIoStream > &&stream_, const std::function<::capnp::Capability::Client(Connection &)> &make_client)
Definition: proxy-io.h:383
Connection(EventLoop &loop, kj::Own< kj::AsyncIoStream > &&stream_)
Definition: proxy-io.h:379
void onDisconnect(F &&f)
Add disconnect handler.
Definition: proxy-io.h:405
::capnp::CapabilityServerSet< Thread > m_threads
Collection of server-side IPC worker threads (ProxyServer<Thread> objects previously returned by Thre...
Definition: proxy-io.h:429
CleanupList m_sync_cleanup_fns
Cleanup functions to run if connection is broken unexpectedly.
Definition: proxy-io.h:434
std::optional<::capnp::RpcSystem<::capnp::rpc::twoparty::VatId > > m_rpc_system
Definition: proxy-io.h:421
void removeSyncCleanup(CleanupIt it)
Definition: proxy.cpp:163
Event loop implementation.
Definition: proxy-io.h:214
kj::AsyncIoContext m_io_context
Capnp IO context.
Definition: proxy-io.h:302
void sync(Callable &&callable)
Wrapper around EventLoop::post that takes advantage of the fact that callable will not go out of scop...
Definition: proxy-io.h:244
EventLoop(const char *exe_name, LogFn log_fn, void *context=nullptr)
Construct event loop object with default logging options.
Definition: proxy-io.h:217
std::list< Connection > m_incoming_connections
List of connections.
Definition: proxy-io.h:311
Mutex m_mutex
Mutex and condition variable used to post tasks to event loop and async thread.
Definition: proxy-io.h:298
LogOptions m_log_opts
Logging options.
Definition: proxy-io.h:314
std::unique_ptr< kj::TaskSet > m_task_set
Capnp list of pending promises.
Definition: proxy-io.h:308
void * m_context
External context pointer.
Definition: proxy-io.h:317
EventLoop(const char *exe_name, std::function< void(bool, std::string)> old_callback, void *context=nullptr)
Backwards-compatible constructor for previous (deprecated) logging callback signature.
Definition: proxy-io.h:224
Event loop smart pointer automatically managing m_num_clients.
Definition: proxy.h:51
Definition: util.h:170
std::unique_lock< std::mutex > m_lock
Definition: util.h:182
friend Logger & operator<<(Logger &logger, T &&value)
Definition: proxy-io.h:154
Logger(const Logger &)=delete
bool enabled() const
Definition: proxy-io.h:172
~Logger() noexcept(false)
Definition: proxy-io.h:148
Logger & operator=(Logger &&)=delete
Log m_log_level
Definition: proxy-io.h:178
Logger(Logger &&)=delete
Logger(const LogOptions &options, Log log_level)
Definition: proxy-io.h:141
const LogOptions & m_options
Definition: proxy-io.h:177
friend Logger & operator<<(Logger &&logger, T &&value)
Definition: proxy-io.h:161
std::ostringstream m_buffer
Definition: proxy-io.h:179
Logger & operator=(const Logger &)=delete
Handler for kj::TaskSet failed task events.
Definition: proxy-io.h:94
EventLoop & m_loop
Definition: proxy-io.h:98
LoggingErrorHandler(EventLoop &loop)
Definition: proxy-io.h:96
void taskFailed(kj::Exception &&exception) override
Definition: proxy.cpp:43
Base class for generated ProxyClient classes that implement a C++ interface and forward calls to a ca...
Definition: proxy.h:81
Interface::Client m_client
Definition: proxy.h:132
ProxyContext m_context
Definition: proxy.h:133
~ProxyClientBase() noexcept
Definition: proxy-io.h:514
ProxyClientBase(typename Interface::Client client, Connection *connection, bool destroy_connection)
Construct libmultiprocess client object wrapping Cap'n Proto client object with a reference to the as...
Definition: proxy-io.h:454
std::optional< mp::EventLoop > m_loop
EventLoop object which manages I/O events for all connections.
Definition: protocol.cpp:138
Context m_context
Definition: protocol.cpp:135
#define MP_GUARDED_BY(x)
Definition: util.h:159
#define MP_REQUIRES(x)
Definition: util.h:155
Warning
Definition: warning.h:9
Functions to serialize / deserialize common bitcoin types.
Definition: common-types.h:57
void Unlock(Lock &lock, Callback &&callback)
Definition: util.h:206
kj::StringPtr KJ_STRINGIFY(Log flags)
Definition: proxy.cpp:434
std::list< std::function< void()> > CleanupList
Definition: proxy.h:36
void ServeStream(EventLoop &loop, int fd, InitImpl &init)
Given stream file descriptor and an init object, handle requests on the stream by calling methods on ...
Definition: proxy-io.h:738
std::function< void(LogMessage)> LogFn
Definition: proxy-io.h:122
std::tuple< ConnThread, bool > SetThread(GuardedRef< ConnThreads > threads, Connection *connection, const std::function< Thread::Client()> &make_thread)
Definition: proxy.cpp:317
thread_local ThreadContext g_thread_context
Definition: proxy.cpp:41
void _Listen(EventLoop &loop, kj::Own< kj::ConnectionReceiver > &&listener, InitImpl &init)
Given connection receiver and an init object, handle incoming connections by calling _Serve,...
Definition: proxy-io.h:725
std::unique_ptr< ProxyClient< InitInterface > > ConnectStream(EventLoop &loop, int fd)
Given stream file descriptor, make a new ProxyClient object to send requests over the stream.
Definition: proxy-io.h:682
Log
Log flags. Update stringify function if changed!
Definition: proxy-io.h:102
void ListenConnections(EventLoop &loop, int fd, InitImpl &init)
Given listening socket file descriptor and an init object, handle incoming connections and requests b...
Definition: proxy-io.h:747
std::string LongThreadName(const char *exe_name)
Definition: proxy.cpp:429
ConnThreads::iterator ConnThread
Definition: proxy-io.h:600
void _Serve(EventLoop &loop, kj::Own< kj::AsyncIoStream > &&stream, InitImpl &init)
Given stream and init objects, construct a new ProxyServer object that handles requests from the stre...
Definition: proxy-io.h:706
typename CleanupList::iterator CleanupIt
Definition: proxy.h:37
void CleanupRun(CleanupList &fns)
Definition: proxy.h:39
std::map< Connection *, std::optional< ProxyClient< Thread > > > ConnThreads
Map from Connection to local or remote thread handle which will be used over that connection.
Definition: proxy-io.h:599
#define MP_LOG(loop,...)
Definition: proxy-io.h:184
ThreadContext & thread_context
Definition: proxy-io.h:36
ClientInvokeContext(Connection &conn, ThreadContext &thread_context)
Definition: proxy-io.h:37
Connection & connection
Definition: proxy-io.h:31
Log level
The severity level of this message.
Definition: proxy-io.h:119
std::string message
Message to be logged.
Definition: proxy-io.h:116
LogFn log_fn
External logging callback.
Definition: proxy-io.h:127
size_t max_chars
Maximum number of characters to use when representing request and response structs as strings.
Definition: proxy-io.h:131
Log log_level
Messages with a severity level less than log_level will not be reported.
Definition: proxy-io.h:135
ProxyClient(const ProxyClient &)=delete
std::optional< CleanupIt > m_disconnect_cb
Reference to callback function that is run if there is a sudden disconnect and the Connection object ...
Definition: proxy-io.h:78
Mapping from capnp interface type to proxy client implementation (specializations are generated by pr...
Definition: proxy.h:25
EventLoopRef loop
Definition: proxy.h:71
Connection * connection
Definition: proxy.h:70
CleanupList cleanup_fns
Definition: proxy.h:72
std::thread m_thread
Definition: proxy-io.h:89
ThreadContext & m_thread_context
Definition: proxy-io.h:88
Base class for generated ProxyServer classes that implement capnp server methods and forward calls to...
Definition: proxy.h:148
virtual ~ProxyServerBase()
ProxyServer destructor, called from the EventLoop thread by Cap'n Proto garbage collection code after...
Definition: proxy-io.h:539
std::shared_ptr< Impl > m_impl
Implementation pointer that may or may not be owned and deleted when this capnp server goes out of sc...
Definition: proxy.h:170
Mapping from capnp interface type to proxy server implementation (specializations are generated by pr...
Definition: proxy.h:28
CallContext_ CallContext
Definition: proxy-io.h:46
ServerInvokeContext(ProxyServer &proxy_server, CallContext &call_context, int req)
Definition: proxy-io.h:52
CallContext & call_context
Definition: proxy-io.h:49
ProxyServer & proxy_server
Definition: proxy-io.h:48
Vat id for server side of connection.
Definition: proxy-io.h:446
The thread_local ThreadContext g_thread_context struct provides information about individual threads ...
Definition: proxy-io.h:621
ConnThreads callback_threads MP_GUARDED_BY(waiter->m_mutex)
When client is making a request to a server, this is the callbackThread argument it passes in the req...
ConnThreads request_threads MP_GUARDED_BY(waiter->m_mutex)
When client is making a request to a server, this is the thread argument it passes in the request,...
std::string thread_name
Identifying string for debug.
Definition: proxy-io.h:623
Single element task queue used to handle recursive capnp calls.
Definition: proxy-io.h:327
void wait(Lock &lock, Predicate pred)
Definition: proxy-io.h:341
std::condition_variable m_cv
Definition: proxy-io.h:367
Mutex m_mutex
Mutex mainly used internally by waiter class, but also used externally to guard access to related sta...
Definition: proxy-io.h:366
std::optional< kj::Function< void()> > m_fn MP_GUARDED_BY(m_mutex)
bool post(Fn &&fn)
Definition: proxy-io.h:331
Waiter()=default
assert(!tx.IsCoinBase())