{ "format": 1, "id": "saw-remote-loopback", "kind": "class", "name": "remote", "namespace": "saw", "module": "remote", "header": "modules/remote/c++/remote_loopback_base.hpp", "is_special": true, "specializes": "saw-remote", "arguments": ["rmt::Loopback"], "brief_description": "In process backend.", "detailed_description": [ [ "The reference implementation every other backend is measured against. Nothing is serialized and nothing is copied across a boundary, so what remains is the bookkeeping every backend has to do." ], [ "Servers are registered under the address they listen on together with their class id, so a client asking for a schema on an address finds the one server which owns it." ] ], "examples": [ { "title": "Serving an interface and calling it", "description": [ [ "The whole flow on one address: bring up the data servers, bind an interface to them, connect, call. Error handling is left out, but note that every error_or is kept in a named variable, because get_value hands back a reference into it." ], [ "The data servers have to exist before", {"name": "rpc_listen", "id": "saw-remote-loopback-rpc_listen"}, "is called, since that is where the parameter and the answer live." ] ], "language": "cpp", "code": "using TestInterface = schema::Interface<\n\tschema::Member, \"foo\">\n>;\n\nevent_loop loop;\nwait_scope wait{loop};\n\nremote rmt;\n\nauto eo_addr = rmt.parse_address(0u);\nauto& addr = eo_addr.get_value();\n\n/// The transport layer, one server per schema the interface mentions.\nauto eo_u32_srv = rmt.data_listen(*addr);\nauto eo_i64_srv = rmt.data_listen(*addr);\n\nauto iface = interface_factory::create(\n\t[](data input)\n\t\t-> error_or>\n\t{\n\t\tdata rv;\n\t\trv.set(input.get() * 2);\n\t\treturn rv;\n\t});\n\nauto eo_rpc_srv = rmt.rpc_listen(*addr, std::move(iface));\n\n/// The overlay on top of it.\nauto cvr_client = rmt.rpc_connect(*addr);\nauto eo_client = cvr_client.take();\nauto& client = eo_client.get_value();\n\ndata inp{21};\n\nauto cvr_result = client.call<\"foo\">(std::move(inp));\nauto eo_result = cvr_result.take();\nauto& result = eo_result.get_value();\n\n/// The answer never left the server. result only knows the id it picked.\nauto eo_value = result.wait(wait);\n/// eo_value.get_value().get() == 42\n" } ], "attributes": { "saw-remote-loopback-registered_data_servers_": { "id": "saw-remote-loopback-registered_data_servers_", "name": "registered_data_servers_", "type": ["std::map< key_t, ptr<", {"name": "i_data_server", "id": "saw-i_data_server"}, "< rmt::Loopback > > >"], "visibility": "private", "brief_description": "Keyed by address id, schema hash and encoding hash." }, "saw-remote-loopback-registered_rpc_servers_": { "id": "saw-remote-loopback-registered_rpc_servers_", "name": "registered_rpc_servers_", "type": ["std::map< key_t, ptr<", {"name": "i_rpc_server", "id": "saw-i_rpc_server"}, "< rmt::Loopback > > >"], "visibility": "private", "brief_description": "Keyed by address id, interface hash and encoding hash." } }, "functions": { "saw-remote-loopback-parse_address": { "id": "saw-remote-loopback-parse_address", "name": "parse_address", "type": ["error_or< own<", {"name": "remote_address", "id": "saw-remote_address-loopback"}, "< rmt::Loopback > > >"], "brief_description": "Resolves an address for the remote.", "parameters": [ { "name": "id", "type": ["data< schema::UInt64 >"], "brief_description": "Identifier standing in for what a network address would be." } ] }, "saw-remote-loopback-data_listen": { "id": "saw-remote-loopback-data_listen", "name": "data_listen", "type": ["error_or< own<", {"name": "data_server", "id": "saw-data_server-loopback"}, "< Schema, Encode, rmt::Loopback > > >"], "brief_description": "Starts a data server for one schema on an address.", "detailed_description": [ [ "Fails with already_exists if a server for the same schema and encoding is already bound to that address. The returned server registers itself and stays reachable until it is destroyed." ] ], "templates": [ {"name": "Schema", "kind": "type"}, {"name": "Encode", "kind": "type"} ], "parameters": [ {"name": "addr", "type": ["const remote_address< rmt::Loopback > &"]} ] }, "saw-remote-loopback-data_connect": { "id": "saw-remote-loopback-data_connect", "name": "data_connect", "type": ["conveyor<", {"name": "data_client", "id": "saw-data_client-loopback"}, "< Schema, Encode, rmt::Loopback > >"], "brief_description": "Connects to a data server.", "detailed_description": [ ["Fails with not_found if nothing listens for that schema on that address."] ], "templates": [ {"name": "Schema", "kind": "type"}, {"name": "Encode", "kind": "type"} ], "parameters": [ {"name": "addr", "type": ["const remote_address< rmt::Loopback > &"]} ] }, "saw-remote-loopback-rpc_listen": { "id": "saw-remote-loopback-rpc_listen", "name": "rpc_listen", "type": ["error_or< own<", {"name": "rpc_server", "id": "saw-rpc_server-loopback"}, "< Iface, Encode, rmt::Loopback > > >"], "brief_description": "Starts an rpc server for an interface on an address.", "detailed_description": [ [ "Every schema the interface mentions needs a data server on the same address beforehand, since that is where parameters and responses live. A missing one fails the call with not_found." ] ], "templates": [ {"name": "Iface", "kind": "type"}, {"name": "Encode", "kind": "type"} ], "parameters": [ {"name": "addr", "type": ["remote_address< rmt::Loopback > &"]}, { "name": "iface", "type": ["typename rpc_server< Iface, Encode, rmt::Loopback >::InterfaceT"], "brief_description": "The implementations backing the interface." } ] }, "saw-remote-loopback-rpc_connect": { "id": "saw-remote-loopback-rpc_connect", "name": "rpc_connect", "type": ["conveyor<", {"name": "rpc_client", "id": "saw-rpc_client-loopback"}, "< Iface, Encode, rmt::Loopback > >"], "brief_description": "Connects to an rpc server.", "detailed_description": [ ["Defined in remote_loopback.hpp, since the client has to be a complete type at that point."] ], "templates": [ {"name": "Iface", "kind": "type"}, {"name": "Encode", "kind": "type"} ], "parameters": [ {"name": "addr", "type": ["const remote_address< rmt::Loopback > &"]} ] }, "saw-remote-loopback-register_data_server": { "id": "saw-remote-loopback-register_data_server", "name": "register_data_server", "type": ["error_or< void >"], "brief_description": "Internal. Called by a data server on construction.", "parameters": [ {"name": "addr", "type": ["const remote_address< rmt::Loopback > &"]}, {"name": "srv", "type": [{"name": "i_data_server", "id": "saw-i_data_server"}, "< rmt::Loopback > &"]} ] }, "saw-remote-loopback-deregister_data_server": { "id": "saw-remote-loopback-deregister_data_server", "name": "deregister_data_server", "type": ["error_or< void >"], "brief_description": "Internal. Called by a data server on destruction.", "parameters": [ {"name": "addr", "type": ["const remote_address< rmt::Loopback > &"]}, {"name": "srv", "type": [{"name": "i_data_server", "id": "saw-i_data_server"}, "< rmt::Loopback > &"]} ] }, "saw-remote-loopback-register_rpc_server": { "id": "saw-remote-loopback-register_rpc_server", "name": "register_rpc_server", "type": ["error_or< void >"], "brief_description": "Internal. Called by an rpc server on construction.", "parameters": [ {"name": "addr", "type": ["const remote_address< rmt::Loopback > &"]}, {"name": "srv", "type": [{"name": "i_rpc_server", "id": "saw-i_rpc_server"}, "< rmt::Loopback > &"]} ] }, "saw-remote-loopback-deregister_rpc_server": { "id": "saw-remote-loopback-deregister_rpc_server", "name": "deregister_rpc_server", "type": ["error_or< void >"], "brief_description": "Internal. Called by an rpc server on destruction.", "parameters": [ {"name": "addr", "type": ["const remote_address< rmt::Loopback > &"]}, {"name": "srv", "type": [{"name": "i_rpc_server", "id": "saw-i_rpc_server"}, "< rmt::Loopback > &"]} ] } } }