Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions doc/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ The `*.capnp` data definition files are consumed by the _libmultiprocess_ code g

The `ProxyServer` objects help translate IPC requests from a socket to method calls on a local object. The `ProxyServer` objects are just used internally by the `mp::ServeStream(loop, socket, wrapped_object)` and `mp::ListenConnections(loop, socket, wrapped_object[, max_connections])` functions, and aren't exposed externally. The `ProxyClient` classes are exposed, and returned from the `mp::ConnectStream(loop, socket)` function and meant to be used directly. The classes implement methods described in `.capnp` definitions, and whenever any method is called, a request with the method arguments is sent over the associated IPC connection, and the corresponding `wrapped_object` method on the other end of the connection is called, with the `ProxyClient` method blocking until it returns and forwarding back any return value to the `ProxyClient` method caller.

## Event loop

Making connections and IPC calls requires an `mp::EventLoop` instance running in its own dedicated thread. The event loop is reference-counted, and `EventLoop::loop()` returns when the last `mp::EventLoopRef` is released. Therefore, any code that needs to use the loop across multiple calls should maintain its own `EventLoopRef`. Connection objects and proxy objects automatically hold a reference for as long as they exist.

For a typical setup, see [example.cpp](../example/example.cpp).

## Example

A simple interface description can be found at [test/mp/test/foo.capnp](../test/mp/test/foo.capnp), implementation in [test/mp/test/foo.h](../test/mp/test/foo.h), and usage in [test/mp/test/test.cpp](../test/mp/test/test.cpp).
Expand Down
15 changes: 9 additions & 6 deletions example/example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <kj/async.h>
#include <kj/common.h>
#include <memory>
#include <mp/proxy.h>
#include <mp/proxy-io.h>
#include <mp/util.h>
#include <stdexcept>
Expand All @@ -24,14 +25,15 @@

namespace fs = std::filesystem;

static auto Spawn(mp::EventLoop& loop, const std::string& process_argv0, const std::string& new_exe_name)
static auto Spawn(const mp::EventLoopRef& loop_ref, const std::string& process_argv0, const std::string& new_exe_name)
{
const auto [pid, socket] = mp::SpawnProcess([&](mp::SpawnConnectInfo info) -> std::vector<std::string> {
fs::path path = process_argv0;
path.remove_filename();
path.append(new_exe_name);
return {path.string(), std::move(info)};
});
mp::EventLoop& loop = *loop_ref;
return std::make_tuple(mp::ConnectStream<InitInterface>(loop, mp::MakeStream(loop, socket)), pid);
}

Expand All @@ -48,16 +50,16 @@ int main(int argc, char** argv)
return 1;
}

std::promise<mp::EventLoop*> promise;
std::promise<mp::EventLoopRef> promise;
std::thread loop_thread([&] {
mp::EventLoop loop("mpexample", LogPrint);
promise.set_value(&loop);
promise.set_value(mp::EventLoopRef(loop));
loop.loop();
});
mp::EventLoop* loop = promise.get_future().get();
mp::EventLoopRef loop_ref = promise.get_future().get();

auto [printer_init, printer_pid] = Spawn(*loop, argv[0], "mpprinter");
auto [calc_init, calc_pid] = Spawn(*loop, argv[0], "mpcalculator");
auto [printer_init, printer_pid] = Spawn(loop_ref, argv[0], "mpprinter");
auto [calc_init, calc_pid] = Spawn(loop_ref, argv[0], "mpcalculator");
auto calc = calc_init->makeCalculator(printer_init->makePrinter());
while (true) {
std::string eqn;
Expand All @@ -71,6 +73,7 @@ int main(int argc, char** argv)
mp::WaitProcess(calc_pid);
printer_init.reset();
mp::WaitProcess(printer_pid);
loop_ref.reset();
loop_thread.join();
std::cout << "Bye!" << std::endl;
return 0;
Expand Down
4 changes: 3 additions & 1 deletion include/mp/proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ inline void CleanupRun(CleanupList& fns) {
}
}

//! Event loop smart pointer automatically managing m_num_refs.
//! Event loop smart pointer automatically managing m_num_refs. Hold one
//! reference to keep the loop running, once the last reference is released
//! EventLoop::loop() will exit.
//! If a lock pointer argument is passed, the specified lock will be used,
//! otherwise EventLoop::m_mutex will be locked when needed.
class EventLoopRef
Expand Down
Loading