annotate win32-mingw/include/capnp/capability.h @ 149:279b18cc7785

Update Win32 capnp builds to v0.6
author Chris Cannam <cannam@all-day-breakfast.com>
date Tue, 23 May 2017 09:16:54 +0100
parents 38d1c0e7850b
children
rev   line source
cannam@149 1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
cannam@149 2 // Licensed under the MIT License:
cannam@149 3 //
cannam@149 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
cannam@149 5 // of this software and associated documentation files (the "Software"), to deal
cannam@149 6 // in the Software without restriction, including without limitation the rights
cannam@149 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
cannam@149 8 // copies of the Software, and to permit persons to whom the Software is
cannam@149 9 // furnished to do so, subject to the following conditions:
cannam@149 10 //
cannam@149 11 // The above copyright notice and this permission notice shall be included in
cannam@149 12 // all copies or substantial portions of the Software.
cannam@149 13 //
cannam@149 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
cannam@149 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
cannam@149 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
cannam@149 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
cannam@149 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
cannam@149 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
cannam@149 20 // THE SOFTWARE.
cannam@149 21
cannam@149 22 #ifndef CAPNP_CAPABILITY_H_
cannam@149 23 #define CAPNP_CAPABILITY_H_
cannam@149 24
cannam@149 25 #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
cannam@149 26 #pragma GCC system_header
cannam@149 27 #endif
cannam@149 28
cannam@149 29 #if CAPNP_LITE
cannam@149 30 #error "RPC APIs, including this header, are not available in lite mode."
cannam@149 31 #endif
cannam@149 32
cannam@149 33 #include <kj/async.h>
cannam@149 34 #include <kj/vector.h>
cannam@149 35 #include "raw-schema.h"
cannam@149 36 #include "any.h"
cannam@149 37 #include "pointer-helpers.h"
cannam@149 38
cannam@149 39 namespace capnp {
cannam@149 40
cannam@149 41 template <typename Results>
cannam@149 42 class Response;
cannam@149 43
cannam@149 44 template <typename T>
cannam@149 45 class RemotePromise: public kj::Promise<Response<T>>, public T::Pipeline {
cannam@149 46 // A Promise which supports pipelined calls. T is typically a struct type. T must declare
cannam@149 47 // an inner "mix-in" type "Pipeline" which implements pipelining; RemotePromise simply
cannam@149 48 // multiply-inherits that type along with Promise<Response<T>>. T::Pipeline must be movable,
cannam@149 49 // but does not need to be copyable (i.e. just like Promise<T>).
cannam@149 50 //
cannam@149 51 // The promise is for an owned pointer so that the RPC system can allocate the MessageReader
cannam@149 52 // itself.
cannam@149 53
cannam@149 54 public:
cannam@149 55 inline RemotePromise(kj::Promise<Response<T>>&& promise, typename T::Pipeline&& pipeline)
cannam@149 56 : kj::Promise<Response<T>>(kj::mv(promise)),
cannam@149 57 T::Pipeline(kj::mv(pipeline)) {}
cannam@149 58 inline RemotePromise(decltype(nullptr))
cannam@149 59 : kj::Promise<Response<T>>(nullptr),
cannam@149 60 T::Pipeline(nullptr) {}
cannam@149 61 KJ_DISALLOW_COPY(RemotePromise);
cannam@149 62 RemotePromise(RemotePromise&& other) = default;
cannam@149 63 RemotePromise& operator=(RemotePromise&& other) = default;
cannam@149 64 };
cannam@149 65
cannam@149 66 class LocalClient;
cannam@149 67 namespace _ { // private
cannam@149 68 extern const RawSchema NULL_INTERFACE_SCHEMA; // defined in schema.c++
cannam@149 69 class CapabilityServerSetBase;
cannam@149 70 } // namespace _ (private)
cannam@149 71
cannam@149 72 struct Capability {
cannam@149 73 // A capability without type-safe methods. Typed capability clients wrap `Client` and typed
cannam@149 74 // capability servers subclass `Server` to dispatch to the regular, typed methods.
cannam@149 75
cannam@149 76 class Client;
cannam@149 77 class Server;
cannam@149 78
cannam@149 79 struct _capnpPrivate {
cannam@149 80 struct IsInterface;
cannam@149 81 static constexpr uint64_t typeId = 0x3;
cannam@149 82 static constexpr Kind kind = Kind::INTERFACE;
cannam@149 83 static constexpr _::RawSchema const* schema = &_::NULL_INTERFACE_SCHEMA;
cannam@149 84
cannam@149 85 static const _::RawBrandedSchema* brand() {
cannam@149 86 return &_::NULL_INTERFACE_SCHEMA.defaultBrand;
cannam@149 87 }
cannam@149 88 };
cannam@149 89 };
cannam@149 90
cannam@149 91 // =======================================================================================
cannam@149 92 // Capability clients
cannam@149 93
cannam@149 94 class RequestHook;
cannam@149 95 class ResponseHook;
cannam@149 96 class PipelineHook;
cannam@149 97 class ClientHook;
cannam@149 98
cannam@149 99 template <typename Params, typename Results>
cannam@149 100 class Request: public Params::Builder {
cannam@149 101 // A call that hasn't been sent yet. This class extends a Builder for the call's "Params"
cannam@149 102 // structure with a method send() that actually sends it.
cannam@149 103 //
cannam@149 104 // Given a Cap'n Proto method `foo(a :A, b :B): C`, the generated client interface will have
cannam@149 105 // a method `Request<FooParams, C> fooRequest()` (as well as a convenience method
cannam@149 106 // `RemotePromise<C> foo(A::Reader a, B::Reader b)`).
cannam@149 107
cannam@149 108 public:
cannam@149 109 inline Request(typename Params::Builder builder, kj::Own<RequestHook>&& hook)
cannam@149 110 : Params::Builder(builder), hook(kj::mv(hook)) {}
cannam@149 111 inline Request(decltype(nullptr)): Params::Builder(nullptr) {}
cannam@149 112
cannam@149 113 RemotePromise<Results> send() KJ_WARN_UNUSED_RESULT;
cannam@149 114 // Send the call and return a promise for the results.
cannam@149 115
cannam@149 116 private:
cannam@149 117 kj::Own<RequestHook> hook;
cannam@149 118
cannam@149 119 friend class Capability::Client;
cannam@149 120 friend struct DynamicCapability;
cannam@149 121 template <typename, typename>
cannam@149 122 friend class CallContext;
cannam@149 123 friend class RequestHook;
cannam@149 124 };
cannam@149 125
cannam@149 126 template <typename Results>
cannam@149 127 class Response: public Results::Reader {
cannam@149 128 // A completed call. This class extends a Reader for the call's answer structure. The Response
cannam@149 129 // is move-only -- once it goes out-of-scope, the underlying message will be freed.
cannam@149 130
cannam@149 131 public:
cannam@149 132 inline Response(typename Results::Reader reader, kj::Own<ResponseHook>&& hook)
cannam@149 133 : Results::Reader(reader), hook(kj::mv(hook)) {}
cannam@149 134
cannam@149 135 private:
cannam@149 136 kj::Own<ResponseHook> hook;
cannam@149 137
cannam@149 138 template <typename, typename>
cannam@149 139 friend class Request;
cannam@149 140 friend class ResponseHook;
cannam@149 141 };
cannam@149 142
cannam@149 143 class Capability::Client {
cannam@149 144 // Base type for capability clients.
cannam@149 145
cannam@149 146 public:
cannam@149 147 typedef Capability Reads;
cannam@149 148 typedef Capability Calls;
cannam@149 149
cannam@149 150 Client(decltype(nullptr));
cannam@149 151 // If you need to declare a Client before you have anything to assign to it (perhaps because
cannam@149 152 // the assignment is going to occur in an if/else scope), you can start by initializing it to
cannam@149 153 // `nullptr`. The resulting client is not meant to be called and throws exceptions from all
cannam@149 154 // methods.
cannam@149 155
cannam@149 156 template <typename T, typename = kj::EnableIf<kj::canConvert<T*, Capability::Server*>()>>
cannam@149 157 Client(kj::Own<T>&& server);
cannam@149 158 // Make a client capability that wraps the given server capability. The server's methods will
cannam@149 159 // only be executed in the given EventLoop, regardless of what thread calls the client's methods.
cannam@149 160
cannam@149 161 template <typename T, typename = kj::EnableIf<kj::canConvert<T*, Client*>()>>
cannam@149 162 Client(kj::Promise<T>&& promise);
cannam@149 163 // Make a client from a promise for a future client. The resulting client queues calls until the
cannam@149 164 // promise resolves.
cannam@149 165
cannam@149 166 Client(kj::Exception&& exception);
cannam@149 167 // Make a broken client that throws the given exception from all calls.
cannam@149 168
cannam@149 169 Client(Client& other);
cannam@149 170 Client& operator=(Client& other);
cannam@149 171 // Copies by reference counting. Warning: This refcounting is not thread-safe. All copies of
cannam@149 172 // the client must remain in one thread.
cannam@149 173
cannam@149 174 Client(Client&&) = default;
cannam@149 175 Client& operator=(Client&&) = default;
cannam@149 176 // Move constructor avoids reference counting.
cannam@149 177
cannam@149 178 explicit Client(kj::Own<ClientHook>&& hook);
cannam@149 179 // For use by the RPC implementation: Wrap a ClientHook.
cannam@149 180
cannam@149 181 template <typename T>
cannam@149 182 typename T::Client castAs();
cannam@149 183 // Reinterpret the capability as implementing the given interface. Note that no error will occur
cannam@149 184 // here if the capability does not actually implement this interface, but later method calls will
cannam@149 185 // fail. It's up to the application to decide how indicate that additional interfaces are
cannam@149 186 // supported.
cannam@149 187 //
cannam@149 188 // TODO(perf): GCC 4.8 / Clang 3.3: rvalue-qualified version for better performance.
cannam@149 189
cannam@149 190 template <typename T>
cannam@149 191 typename T::Client castAs(InterfaceSchema schema);
cannam@149 192 // Dynamic version. `T` must be `DynamicCapability`, and you must `#include <capnp/dynamic.h>`.
cannam@149 193
cannam@149 194 kj::Promise<void> whenResolved();
cannam@149 195 // If the capability is actually only a promise, the returned promise resolves once the
cannam@149 196 // capability itself has resolved to its final destination (or propagates the exception if
cannam@149 197 // the capability promise is rejected). This is mainly useful for error-checking in the case
cannam@149 198 // where no calls are being made. There is no reason to wait for this before making calls; if
cannam@149 199 // the capability does not resolve, the call results will propagate the error.
cannam@149 200
cannam@149 201 Request<AnyPointer, AnyPointer> typelessRequest(
cannam@149 202 uint64_t interfaceId, uint16_t methodId,
cannam@149 203 kj::Maybe<MessageSize> sizeHint);
cannam@149 204 // Make a request without knowing the types of the params or results. You specify the type ID
cannam@149 205 // and method number manually.
cannam@149 206
cannam@149 207 // TODO(someday): method(s) for Join
cannam@149 208
cannam@149 209 protected:
cannam@149 210 Client() = default;
cannam@149 211
cannam@149 212 template <typename Params, typename Results>
cannam@149 213 Request<Params, Results> newCall(uint64_t interfaceId, uint16_t methodId,
cannam@149 214 kj::Maybe<MessageSize> sizeHint);
cannam@149 215
cannam@149 216 private:
cannam@149 217 kj::Own<ClientHook> hook;
cannam@149 218
cannam@149 219 static kj::Own<ClientHook> makeLocalClient(kj::Own<Capability::Server>&& server);
cannam@149 220
cannam@149 221 template <typename, Kind>
cannam@149 222 friend struct _::PointerHelpers;
cannam@149 223 friend struct DynamicCapability;
cannam@149 224 friend class Orphanage;
cannam@149 225 friend struct DynamicStruct;
cannam@149 226 friend struct DynamicList;
cannam@149 227 template <typename, Kind>
cannam@149 228 friend struct List;
cannam@149 229 friend class _::CapabilityServerSetBase;
cannam@149 230 friend class ClientHook;
cannam@149 231 };
cannam@149 232
cannam@149 233 // =======================================================================================
cannam@149 234 // Capability servers
cannam@149 235
cannam@149 236 class CallContextHook;
cannam@149 237
cannam@149 238 template <typename Params, typename Results>
cannam@149 239 class CallContext: public kj::DisallowConstCopy {
cannam@149 240 // Wrapper around CallContextHook with a specific return type.
cannam@149 241 //
cannam@149 242 // Methods of this class may only be called from within the server's event loop, not from other
cannam@149 243 // threads.
cannam@149 244 //
cannam@149 245 // The CallContext becomes invalid as soon as the call reports completion.
cannam@149 246
cannam@149 247 public:
cannam@149 248 explicit CallContext(CallContextHook& hook);
cannam@149 249
cannam@149 250 typename Params::Reader getParams();
cannam@149 251 // Get the params payload.
cannam@149 252
cannam@149 253 void releaseParams();
cannam@149 254 // Release the params payload. getParams() will throw an exception after this is called.
cannam@149 255 // Releasing the params may allow the RPC system to free up buffer space to handle other
cannam@149 256 // requests. Long-running asynchronous methods should try to call this as early as is
cannam@149 257 // convenient.
cannam@149 258
cannam@149 259 typename Results::Builder getResults(kj::Maybe<MessageSize> sizeHint = nullptr);
cannam@149 260 typename Results::Builder initResults(kj::Maybe<MessageSize> sizeHint = nullptr);
cannam@149 261 void setResults(typename Results::Reader value);
cannam@149 262 void adoptResults(Orphan<Results>&& value);
cannam@149 263 Orphanage getResultsOrphanage(kj::Maybe<MessageSize> sizeHint = nullptr);
cannam@149 264 // Manipulate the results payload. The "Return" message (part of the RPC protocol) will
cannam@149 265 // typically be allocated the first time one of these is called. Some RPC systems may
cannam@149 266 // allocate these messages in a limited space (such as a shared memory segment), therefore the
cannam@149 267 // application should delay calling these as long as is convenient to do so (but don't delay
cannam@149 268 // if doing so would require extra copies later).
cannam@149 269 //
cannam@149 270 // `sizeHint` indicates a guess at the message size. This will usually be used to decide how
cannam@149 271 // much space to allocate for the first message segment (don't worry: only space that is actually
cannam@149 272 // used will be sent on the wire). If omitted, the system decides. The message root pointer
cannam@149 273 // should not be included in the size. So, if you are simply going to copy some existing message
cannam@149 274 // directly into the results, just call `.totalSize()` and pass that in.
cannam@149 275
cannam@149 276 template <typename SubParams>
cannam@149 277 kj::Promise<void> tailCall(Request<SubParams, Results>&& tailRequest);
cannam@149 278 // Resolve the call by making a tail call. `tailRequest` is a request that has been filled in
cannam@149 279 // but not yet sent. The context will send the call, then fill in the results with the result
cannam@149 280 // of the call. If tailCall() is used, {get,init,set,adopt}Results (above) *must not* be called.
cannam@149 281 //
cannam@149 282 // The RPC implementation may be able to optimize a tail call to another machine such that the
cannam@149 283 // results never actually pass through this machine. Even if no such optimization is possible,
cannam@149 284 // `tailCall()` may allow pipelined calls to be forwarded optimistically to the new call site.
cannam@149 285 //
cannam@149 286 // In general, this should be the last thing a method implementation calls, and the promise
cannam@149 287 // returned from `tailCall()` should then be returned by the method implementation.
cannam@149 288
cannam@149 289 void allowCancellation();
cannam@149 290 // Indicate that it is OK for the RPC system to discard its Promise for this call's result if
cannam@149 291 // the caller cancels the call, thereby transitively canceling any asynchronous operations the
cannam@149 292 // call implementation was performing. This is not done by default because it could represent a
cannam@149 293 // security risk: applications must be carefully written to ensure that they do not end up in
cannam@149 294 // a bad state if an operation is canceled at an arbitrary point. However, for long-running
cannam@149 295 // method calls that hold significant resources, prompt cancellation is often useful.
cannam@149 296 //
cannam@149 297 // Keep in mind that asynchronous cancellation cannot occur while the method is synchronously
cannam@149 298 // executing on a local thread. The method must perform an asynchronous operation or call
cannam@149 299 // `EventLoop::current().evalLater()` to yield control.
cannam@149 300 //
cannam@149 301 // Note: You might think that we should offer `onCancel()` and/or `isCanceled()` methods that
cannam@149 302 // provide notification when the caller cancels the request without forcefully killing off the
cannam@149 303 // promise chain. Unfortunately, this composes poorly with promise forking: the canceled
cannam@149 304 // path may be just one branch of a fork of the result promise. The other branches still want
cannam@149 305 // the call to continue. Promise forking is used within the Cap'n Proto implementation -- in
cannam@149 306 // particular each pipelined call forks the result promise. So, if a caller made a pipelined
cannam@149 307 // call and then dropped the original object, the call should not be canceled, but it would be
cannam@149 308 // excessively complicated for the framework to avoid notififying of cancellation as long as
cannam@149 309 // pipelined calls still exist.
cannam@149 310
cannam@149 311 private:
cannam@149 312 CallContextHook* hook;
cannam@149 313
cannam@149 314 friend class Capability::Server;
cannam@149 315 friend struct DynamicCapability;
cannam@149 316 };
cannam@149 317
cannam@149 318 class Capability::Server {
cannam@149 319 // Objects implementing a Cap'n Proto interface must subclass this. Typically, such objects
cannam@149 320 // will instead subclass a typed Server interface which will take care of implementing
cannam@149 321 // dispatchCall().
cannam@149 322
cannam@149 323 public:
cannam@149 324 typedef Capability Serves;
cannam@149 325
cannam@149 326 virtual kj::Promise<void> dispatchCall(uint64_t interfaceId, uint16_t methodId,
cannam@149 327 CallContext<AnyPointer, AnyPointer> context) = 0;
cannam@149 328 // Call the given method. `params` is the input struct, and should be released as soon as it
cannam@149 329 // is no longer needed. `context` may be used to allocate the output struct and deal with
cannam@149 330 // cancellation.
cannam@149 331
cannam@149 332 // TODO(someday): Method which can optionally be overridden to implement Join when the object is
cannam@149 333 // a proxy.
cannam@149 334
cannam@149 335 protected:
cannam@149 336 inline Capability::Client thisCap();
cannam@149 337 // Get a capability pointing to this object, much like the `this` keyword.
cannam@149 338 //
cannam@149 339 // The effect of this method is undefined if:
cannam@149 340 // - No capability client has been created pointing to this object. (This is always the case in
cannam@149 341 // the server's constructor.)
cannam@149 342 // - The capability client pointing at this object has been destroyed. (This is always the case
cannam@149 343 // in the server's destructor.)
cannam@149 344 // - Multiple capability clients have been created around the same server (possible if the server
cannam@149 345 // is refcounted, which is not recommended since the client itself provides refcounting).
cannam@149 346
cannam@149 347 template <typename Params, typename Results>
cannam@149 348 CallContext<Params, Results> internalGetTypedContext(
cannam@149 349 CallContext<AnyPointer, AnyPointer> typeless);
cannam@149 350 kj::Promise<void> internalUnimplemented(const char* actualInterfaceName,
cannam@149 351 uint64_t requestedTypeId);
cannam@149 352 kj::Promise<void> internalUnimplemented(const char* interfaceName,
cannam@149 353 uint64_t typeId, uint16_t methodId);
cannam@149 354 kj::Promise<void> internalUnimplemented(const char* interfaceName, const char* methodName,
cannam@149 355 uint64_t typeId, uint16_t methodId);
cannam@149 356
cannam@149 357 private:
cannam@149 358 ClientHook* thisHook = nullptr;
cannam@149 359 friend class LocalClient;
cannam@149 360 };
cannam@149 361
cannam@149 362 // =======================================================================================
cannam@149 363
cannam@149 364 class ReaderCapabilityTable: private _::CapTableReader {
cannam@149 365 // Class which imbues Readers with the ability to read capabilities.
cannam@149 366 //
cannam@149 367 // In Cap'n Proto format, the encoding of a capability pointer is simply an integer index into
cannam@149 368 // an external table. Since these pointers fundamentally point outside the message, a
cannam@149 369 // MessageReader by default has no idea what they point at, and therefore reading capabilities
cannam@149 370 // from such a reader will throw exceptions.
cannam@149 371 //
cannam@149 372 // In order to be able to read capabilities, you must first attach a capability table, using
cannam@149 373 // this class. By "imbuing" a Reader, you get a new Reader which will interpret capability
cannam@149 374 // pointers by treating them as indexes into the ReaderCapabilityTable.
cannam@149 375 //
cannam@149 376 // Note that when using Cap'n Proto's RPC system, this is handled automatically.
cannam@149 377
cannam@149 378 public:
cannam@149 379 explicit ReaderCapabilityTable(kj::Array<kj::Maybe<kj::Own<ClientHook>>> table);
cannam@149 380 KJ_DISALLOW_COPY(ReaderCapabilityTable);
cannam@149 381
cannam@149 382 template <typename T>
cannam@149 383 T imbue(T reader);
cannam@149 384 // Return a reader equivalent to `reader` except that when reading capability-valued fields,
cannam@149 385 // the capabilities are looked up in this table.
cannam@149 386
cannam@149 387 private:
cannam@149 388 kj::Array<kj::Maybe<kj::Own<ClientHook>>> table;
cannam@149 389
cannam@149 390 kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) override;
cannam@149 391 };
cannam@149 392
cannam@149 393 class BuilderCapabilityTable: private _::CapTableBuilder {
cannam@149 394 // Class which imbues Builders with the ability to read and write capabilities.
cannam@149 395 //
cannam@149 396 // This is much like ReaderCapabilityTable, except for builders. The table starts out empty,
cannam@149 397 // but capabilities can be added to it over time.
cannam@149 398
cannam@149 399 public:
cannam@149 400 BuilderCapabilityTable();
cannam@149 401 KJ_DISALLOW_COPY(BuilderCapabilityTable);
cannam@149 402
cannam@149 403 inline kj::ArrayPtr<kj::Maybe<kj::Own<ClientHook>>> getTable() { return table; }
cannam@149 404
cannam@149 405 template <typename T>
cannam@149 406 T imbue(T builder);
cannam@149 407 // Return a builder equivalent to `builder` except that when reading capability-valued fields,
cannam@149 408 // the capabilities are looked up in this table.
cannam@149 409
cannam@149 410 private:
cannam@149 411 kj::Vector<kj::Maybe<kj::Own<ClientHook>>> table;
cannam@149 412
cannam@149 413 kj::Maybe<kj::Own<ClientHook>> extractCap(uint index) override;
cannam@149 414 uint injectCap(kj::Own<ClientHook>&& cap) override;
cannam@149 415 void dropCap(uint index) override;
cannam@149 416 };
cannam@149 417
cannam@149 418 // =======================================================================================
cannam@149 419
cannam@149 420 namespace _ { // private
cannam@149 421
cannam@149 422 class CapabilityServerSetBase {
cannam@149 423 public:
cannam@149 424 Capability::Client addInternal(kj::Own<Capability::Server>&& server, void* ptr);
cannam@149 425 kj::Promise<void*> getLocalServerInternal(Capability::Client& client);
cannam@149 426 };
cannam@149 427
cannam@149 428 } // namespace _ (private)
cannam@149 429
cannam@149 430 template <typename T>
cannam@149 431 class CapabilityServerSet: private _::CapabilityServerSetBase {
cannam@149 432 // Allows a server to recognize its own capabilities when passed back to it, and obtain the
cannam@149 433 // underlying Server objects associated with them.
cannam@149 434 //
cannam@149 435 // All objects in the set must have the same interface type T. The objects may implement various
cannam@149 436 // interfaces derived from T (and in fact T can be `capnp::Capability` to accept all objects),
cannam@149 437 // but note that if you compile with RTTI disabled then you will not be able to down-cast through
cannam@149 438 // virtual inheritance, and all inheritance between server interfaces is virtual. So, with RTTI
cannam@149 439 // disabled, you will likely need to set T to be the most-derived Cap'n Proto interface type,
cannam@149 440 // and you server class will need to be directly derived from that, so that you can use
cannam@149 441 // static_cast (or kj::downcast) to cast to it after calling getLocalServer(). (If you compile
cannam@149 442 // with RTTI, then you can freely dynamic_cast and ignore this issue!)
cannam@149 443
cannam@149 444 public:
cannam@149 445 CapabilityServerSet() = default;
cannam@149 446 KJ_DISALLOW_COPY(CapabilityServerSet);
cannam@149 447
cannam@149 448 typename T::Client add(kj::Own<typename T::Server>&& server);
cannam@149 449 // Create a new capability Client for the given Server and also add this server to the set.
cannam@149 450
cannam@149 451 kj::Promise<kj::Maybe<typename T::Server&>> getLocalServer(typename T::Client& client);
cannam@149 452 // Given a Client pointing to a server previously passed to add(), return the corresponding
cannam@149 453 // Server. This returns a promise because if the input client is itself a promise, this must
cannam@149 454 // wait for it to resolve. Keep in mind that the server will be deleted when all clients are
cannam@149 455 // gone, so the caller should make sure to keep the client alive (hence why this method only
cannam@149 456 // accepts an lvalue input).
cannam@149 457 };
cannam@149 458
cannam@149 459 // =======================================================================================
cannam@149 460 // Hook interfaces which must be implemented by the RPC system. Applications never call these
cannam@149 461 // directly; the RPC system implements them and the types defined earlier in this file wrap them.
cannam@149 462
cannam@149 463 class RequestHook {
cannam@149 464 // Hook interface implemented by RPC system representing a request being built.
cannam@149 465
cannam@149 466 public:
cannam@149 467 virtual RemotePromise<AnyPointer> send() = 0;
cannam@149 468 // Send the call and return a promise for the result.
cannam@149 469
cannam@149 470 virtual const void* getBrand() = 0;
cannam@149 471 // Returns a void* that identifies who made this request. This can be used by an RPC adapter to
cannam@149 472 // discover when tail call is going to be sent over its own connection and therefore can be
cannam@149 473 // optimized into a remote tail call.
cannam@149 474
cannam@149 475 template <typename T, typename U>
cannam@149 476 inline static kj::Own<RequestHook> from(Request<T, U>&& request) {
cannam@149 477 return kj::mv(request.hook);
cannam@149 478 }
cannam@149 479 };
cannam@149 480
cannam@149 481 class ResponseHook {
cannam@149 482 // Hook interface implemented by RPC system representing a response.
cannam@149 483 //
cannam@149 484 // At present this class has no methods. It exists only for garbage collection -- when the
cannam@149 485 // ResponseHook is destroyed, the results can be freed.
cannam@149 486
cannam@149 487 public:
cannam@149 488 virtual ~ResponseHook() noexcept(false);
cannam@149 489 // Just here to make sure the type is dynamic.
cannam@149 490
cannam@149 491 template <typename T>
cannam@149 492 inline static kj::Own<ResponseHook> from(Response<T>&& response) {
cannam@149 493 return kj::mv(response.hook);
cannam@149 494 }
cannam@149 495 };
cannam@149 496
cannam@149 497 // class PipelineHook is declared in any.h because it is needed there.
cannam@149 498
cannam@149 499 class ClientHook {
cannam@149 500 public:
cannam@149 501 ClientHook();
cannam@149 502
cannam@149 503 virtual Request<AnyPointer, AnyPointer> newCall(
cannam@149 504 uint64_t interfaceId, uint16_t methodId, kj::Maybe<MessageSize> sizeHint) = 0;
cannam@149 505 // Start a new call, allowing the client to allocate request/response objects as it sees fit.
cannam@149 506 // This version is used when calls are made from application code in the local process.
cannam@149 507
cannam@149 508 struct VoidPromiseAndPipeline {
cannam@149 509 kj::Promise<void> promise;
cannam@149 510 kj::Own<PipelineHook> pipeline;
cannam@149 511 };
cannam@149 512
cannam@149 513 virtual VoidPromiseAndPipeline call(uint64_t interfaceId, uint16_t methodId,
cannam@149 514 kj::Own<CallContextHook>&& context) = 0;
cannam@149 515 // Call the object, but the caller controls allocation of the request/response objects. If the
cannam@149 516 // callee insists on allocating these objects itself, it must make a copy. This version is used
cannam@149 517 // when calls come in over the network via an RPC system. Note that even if the returned
cannam@149 518 // `Promise<void>` is discarded, the call may continue executing if any pipelined calls are
cannam@149 519 // waiting for it.
cannam@149 520 //
cannam@149 521 // Since the caller of this method chooses the CallContext implementation, it is the caller's
cannam@149 522 // responsibility to ensure that the returned promise is not canceled unless allowed via
cannam@149 523 // the context's `allowCancellation()`.
cannam@149 524 //
cannam@149 525 // The call must not begin synchronously; the callee must arrange for the call to begin in a
cannam@149 526 // later turn of the event loop. Otherwise, application code may call back and affect the
cannam@149 527 // callee's state in an unexpected way.
cannam@149 528
cannam@149 529 virtual kj::Maybe<ClientHook&> getResolved() = 0;
cannam@149 530 // If this ClientHook is a promise that has already resolved, returns the inner, resolved version
cannam@149 531 // of the capability. The caller may permanently replace this client with the resolved one if
cannam@149 532 // desired. Returns null if the client isn't a promise or hasn't resolved yet -- use
cannam@149 533 // `whenMoreResolved()` to distinguish between them.
cannam@149 534
cannam@149 535 virtual kj::Maybe<kj::Promise<kj::Own<ClientHook>>> whenMoreResolved() = 0;
cannam@149 536 // If this client is a settled reference (not a promise), return nullptr. Otherwise, return a
cannam@149 537 // promise that eventually resolves to a new client that is closer to being the final, settled
cannam@149 538 // client (i.e. the value eventually returned by `getResolved()`). Calling this repeatedly
cannam@149 539 // should eventually produce a settled client.
cannam@149 540
cannam@149 541 kj::Promise<void> whenResolved();
cannam@149 542 // Repeatedly calls whenMoreResolved() until it returns nullptr.
cannam@149 543
cannam@149 544 virtual kj::Own<ClientHook> addRef() = 0;
cannam@149 545 // Return a new reference to the same capability.
cannam@149 546
cannam@149 547 virtual const void* getBrand() = 0;
cannam@149 548 // Returns a void* that identifies who made this client. This can be used by an RPC adapter to
cannam@149 549 // discover when a capability it needs to marshal is one that it created in the first place, and
cannam@149 550 // therefore it can transfer the capability without proxying.
cannam@149 551
cannam@149 552 static const uint NULL_CAPABILITY_BRAND;
cannam@149 553 // Value is irrelevant; used for pointer.
cannam@149 554
cannam@149 555 inline bool isNull() { return getBrand() == &NULL_CAPABILITY_BRAND; }
cannam@149 556 // Returns true if the capability was created as a result of assigning a Client to null or by
cannam@149 557 // reading a null pointer out of a Cap'n Proto message.
cannam@149 558
cannam@149 559 virtual void* getLocalServer(_::CapabilityServerSetBase& capServerSet);
cannam@149 560 // If this is a local capability created through `capServerSet`, return the underlying Server.
cannam@149 561 // Otherwise, return nullptr. Default implementation (which everyone except LocalClient should
cannam@149 562 // use) always returns nullptr.
cannam@149 563
cannam@149 564 static kj::Own<ClientHook> from(Capability::Client client) { return kj::mv(client.hook); }
cannam@149 565 };
cannam@149 566
cannam@149 567 class CallContextHook {
cannam@149 568 // Hook interface implemented by RPC system to manage a call on the server side. See
cannam@149 569 // CallContext<T>.
cannam@149 570
cannam@149 571 public:
cannam@149 572 virtual AnyPointer::Reader getParams() = 0;
cannam@149 573 virtual void releaseParams() = 0;
cannam@149 574 virtual AnyPointer::Builder getResults(kj::Maybe<MessageSize> sizeHint) = 0;
cannam@149 575 virtual kj::Promise<void> tailCall(kj::Own<RequestHook>&& request) = 0;
cannam@149 576 virtual void allowCancellation() = 0;
cannam@149 577
cannam@149 578 virtual kj::Promise<AnyPointer::Pipeline> onTailCall() = 0;
cannam@149 579 // If `tailCall()` is called, resolves to the PipelineHook from the tail call. An
cannam@149 580 // implementation of `ClientHook::call()` is allowed to call this at most once.
cannam@149 581
cannam@149 582 virtual ClientHook::VoidPromiseAndPipeline directTailCall(kj::Own<RequestHook>&& request) = 0;
cannam@149 583 // Call this when you would otherwise call onTailCall() immediately followed by tailCall().
cannam@149 584 // Implementations of tailCall() should typically call directTailCall() and then fulfill the
cannam@149 585 // promise fulfiller for onTailCall() with the returned pipeline.
cannam@149 586
cannam@149 587 virtual kj::Own<CallContextHook> addRef() = 0;
cannam@149 588 };
cannam@149 589
cannam@149 590 kj::Own<ClientHook> newLocalPromiseClient(kj::Promise<kj::Own<ClientHook>>&& promise);
cannam@149 591 // Returns a ClientHook that queues up calls until `promise` resolves, then forwards them to
cannam@149 592 // the new client. This hook's `getResolved()` and `whenMoreResolved()` methods will reflect the
cannam@149 593 // redirection to the eventual replacement client.
cannam@149 594
cannam@149 595 kj::Own<PipelineHook> newLocalPromisePipeline(kj::Promise<kj::Own<PipelineHook>>&& promise);
cannam@149 596 // Returns a PipelineHook that queues up calls until `promise` resolves, then forwards them to
cannam@149 597 // the new pipeline.
cannam@149 598
cannam@149 599 kj::Own<ClientHook> newBrokenCap(kj::StringPtr reason);
cannam@149 600 kj::Own<ClientHook> newBrokenCap(kj::Exception&& reason);
cannam@149 601 // Helper function that creates a capability which simply throws exceptions when called.
cannam@149 602
cannam@149 603 kj::Own<PipelineHook> newBrokenPipeline(kj::Exception&& reason);
cannam@149 604 // Helper function that creates a pipeline which simply throws exceptions when called.
cannam@149 605
cannam@149 606 Request<AnyPointer, AnyPointer> newBrokenRequest(
cannam@149 607 kj::Exception&& reason, kj::Maybe<MessageSize> sizeHint);
cannam@149 608 // Helper function that creates a Request object that simply throws exceptions when sent.
cannam@149 609
cannam@149 610 // =======================================================================================
cannam@149 611 // Extend PointerHelpers for interfaces
cannam@149 612
cannam@149 613 namespace _ { // private
cannam@149 614
cannam@149 615 template <typename T>
cannam@149 616 struct PointerHelpers<T, Kind::INTERFACE> {
cannam@149 617 static inline typename T::Client get(PointerReader reader) {
cannam@149 618 return typename T::Client(reader.getCapability());
cannam@149 619 }
cannam@149 620 static inline typename T::Client get(PointerBuilder builder) {
cannam@149 621 return typename T::Client(builder.getCapability());
cannam@149 622 }
cannam@149 623 static inline void set(PointerBuilder builder, typename T::Client&& value) {
cannam@149 624 builder.setCapability(kj::mv(value.Capability::Client::hook));
cannam@149 625 }
cannam@149 626 static inline void set(PointerBuilder builder, typename T::Client& value) {
cannam@149 627 builder.setCapability(value.Capability::Client::hook->addRef());
cannam@149 628 }
cannam@149 629 static inline void adopt(PointerBuilder builder, Orphan<T>&& value) {
cannam@149 630 builder.adopt(kj::mv(value.builder));
cannam@149 631 }
cannam@149 632 static inline Orphan<T> disown(PointerBuilder builder) {
cannam@149 633 return Orphan<T>(builder.disown());
cannam@149 634 }
cannam@149 635 };
cannam@149 636
cannam@149 637 } // namespace _ (private)
cannam@149 638
cannam@149 639 // =======================================================================================
cannam@149 640 // Extend List for interfaces
cannam@149 641
cannam@149 642 template <typename T>
cannam@149 643 struct List<T, Kind::INTERFACE> {
cannam@149 644 List() = delete;
cannam@149 645
cannam@149 646 class Reader {
cannam@149 647 public:
cannam@149 648 typedef List<T> Reads;
cannam@149 649
cannam@149 650 Reader() = default;
cannam@149 651 inline explicit Reader(_::ListReader reader): reader(reader) {}
cannam@149 652
cannam@149 653 inline uint size() const { return unbound(reader.size() / ELEMENTS); }
cannam@149 654 inline typename T::Client operator[](uint index) const {
cannam@149 655 KJ_IREQUIRE(index < size());
cannam@149 656 return typename T::Client(reader.getPointerElement(
cannam@149 657 bounded(index) * ELEMENTS).getCapability());
cannam@149 658 }
cannam@149 659
cannam@149 660 typedef _::IndexingIterator<const Reader, typename T::Client> Iterator;
cannam@149 661 inline Iterator begin() const { return Iterator(this, 0); }
cannam@149 662 inline Iterator end() const { return Iterator(this, size()); }
cannam@149 663
cannam@149 664 private:
cannam@149 665 _::ListReader reader;
cannam@149 666 template <typename U, Kind K>
cannam@149 667 friend struct _::PointerHelpers;
cannam@149 668 template <typename U, Kind K>
cannam@149 669 friend struct List;
cannam@149 670 friend class Orphanage;
cannam@149 671 template <typename U, Kind K>
cannam@149 672 friend struct ToDynamic_;
cannam@149 673 };
cannam@149 674
cannam@149 675 class Builder {
cannam@149 676 public:
cannam@149 677 typedef List<T> Builds;
cannam@149 678
cannam@149 679 Builder() = delete;
cannam@149 680 inline Builder(decltype(nullptr)) {}
cannam@149 681 inline explicit Builder(_::ListBuilder builder): builder(builder) {}
cannam@149 682
cannam@149 683 inline operator Reader() const { return Reader(builder.asReader()); }
cannam@149 684 inline Reader asReader() const { return Reader(builder.asReader()); }
cannam@149 685
cannam@149 686 inline uint size() const { return unbound(builder.size() / ELEMENTS); }
cannam@149 687 inline typename T::Client operator[](uint index) {
cannam@149 688 KJ_IREQUIRE(index < size());
cannam@149 689 return typename T::Client(builder.getPointerElement(
cannam@149 690 bounded(index) * ELEMENTS).getCapability());
cannam@149 691 }
cannam@149 692 inline void set(uint index, typename T::Client value) {
cannam@149 693 KJ_IREQUIRE(index < size());
cannam@149 694 builder.getPointerElement(bounded(index) * ELEMENTS).setCapability(kj::mv(value.hook));
cannam@149 695 }
cannam@149 696 inline void adopt(uint index, Orphan<T>&& value) {
cannam@149 697 KJ_IREQUIRE(index < size());
cannam@149 698 builder.getPointerElement(bounded(index) * ELEMENTS).adopt(kj::mv(value));
cannam@149 699 }
cannam@149 700 inline Orphan<T> disown(uint index) {
cannam@149 701 KJ_IREQUIRE(index < size());
cannam@149 702 return Orphan<T>(builder.getPointerElement(bounded(index) * ELEMENTS).disown());
cannam@149 703 }
cannam@149 704
cannam@149 705 typedef _::IndexingIterator<Builder, typename T::Client> Iterator;
cannam@149 706 inline Iterator begin() { return Iterator(this, 0); }
cannam@149 707 inline Iterator end() { return Iterator(this, size()); }
cannam@149 708
cannam@149 709 private:
cannam@149 710 _::ListBuilder builder;
cannam@149 711 friend class Orphanage;
cannam@149 712 template <typename U, Kind K>
cannam@149 713 friend struct ToDynamic_;
cannam@149 714 };
cannam@149 715
cannam@149 716 private:
cannam@149 717 inline static _::ListBuilder initPointer(_::PointerBuilder builder, uint size) {
cannam@149 718 return builder.initList(ElementSize::POINTER, bounded(size) * ELEMENTS);
cannam@149 719 }
cannam@149 720 inline static _::ListBuilder getFromPointer(_::PointerBuilder builder, const word* defaultValue) {
cannam@149 721 return builder.getList(ElementSize::POINTER, defaultValue);
cannam@149 722 }
cannam@149 723 inline static _::ListReader getFromPointer(
cannam@149 724 const _::PointerReader& reader, const word* defaultValue) {
cannam@149 725 return reader.getList(ElementSize::POINTER, defaultValue);
cannam@149 726 }
cannam@149 727
cannam@149 728 template <typename U, Kind k>
cannam@149 729 friend struct List;
cannam@149 730 template <typename U, Kind K>
cannam@149 731 friend struct _::PointerHelpers;
cannam@149 732 };
cannam@149 733
cannam@149 734 // =======================================================================================
cannam@149 735 // Inline implementation details
cannam@149 736
cannam@149 737 template <typename Params, typename Results>
cannam@149 738 RemotePromise<Results> Request<Params, Results>::send() {
cannam@149 739 auto typelessPromise = hook->send();
cannam@149 740 hook = nullptr; // prevent reuse
cannam@149 741
cannam@149 742 // Convert the Promise to return the correct response type.
cannam@149 743 // Explicitly upcast to kj::Promise to make clear that calling .then() doesn't invalidate the
cannam@149 744 // Pipeline part of the RemotePromise.
cannam@149 745 auto typedPromise = kj::implicitCast<kj::Promise<Response<AnyPointer>>&>(typelessPromise)
cannam@149 746 .then([](Response<AnyPointer>&& response) -> Response<Results> {
cannam@149 747 return Response<Results>(response.getAs<Results>(), kj::mv(response.hook));
cannam@149 748 });
cannam@149 749
cannam@149 750 // Wrap the typeless pipeline in a typed wrapper.
cannam@149 751 typename Results::Pipeline typedPipeline(
cannam@149 752 kj::mv(kj::implicitCast<AnyPointer::Pipeline&>(typelessPromise)));
cannam@149 753
cannam@149 754 return RemotePromise<Results>(kj::mv(typedPromise), kj::mv(typedPipeline));
cannam@149 755 }
cannam@149 756
cannam@149 757 inline Capability::Client::Client(kj::Own<ClientHook>&& hook): hook(kj::mv(hook)) {}
cannam@149 758 template <typename T, typename>
cannam@149 759 inline Capability::Client::Client(kj::Own<T>&& server)
cannam@149 760 : hook(makeLocalClient(kj::mv(server))) {}
cannam@149 761 template <typename T, typename>
cannam@149 762 inline Capability::Client::Client(kj::Promise<T>&& promise)
cannam@149 763 : hook(newLocalPromiseClient(promise.then([](T&& t) { return kj::mv(t.hook); }))) {}
cannam@149 764 inline Capability::Client::Client(Client& other): hook(other.hook->addRef()) {}
cannam@149 765 inline Capability::Client& Capability::Client::operator=(Client& other) {
cannam@149 766 hook = other.hook->addRef();
cannam@149 767 return *this;
cannam@149 768 }
cannam@149 769 template <typename T>
cannam@149 770 inline typename T::Client Capability::Client::castAs() {
cannam@149 771 return typename T::Client(hook->addRef());
cannam@149 772 }
cannam@149 773 inline kj::Promise<void> Capability::Client::whenResolved() {
cannam@149 774 return hook->whenResolved();
cannam@149 775 }
cannam@149 776 inline Request<AnyPointer, AnyPointer> Capability::Client::typelessRequest(
cannam@149 777 uint64_t interfaceId, uint16_t methodId,
cannam@149 778 kj::Maybe<MessageSize> sizeHint) {
cannam@149 779 return newCall<AnyPointer, AnyPointer>(interfaceId, methodId, sizeHint);
cannam@149 780 }
cannam@149 781 template <typename Params, typename Results>
cannam@149 782 inline Request<Params, Results> Capability::Client::newCall(
cannam@149 783 uint64_t interfaceId, uint16_t methodId, kj::Maybe<MessageSize> sizeHint) {
cannam@149 784 auto typeless = hook->newCall(interfaceId, methodId, sizeHint);
cannam@149 785 return Request<Params, Results>(typeless.template getAs<Params>(), kj::mv(typeless.hook));
cannam@149 786 }
cannam@149 787
cannam@149 788 template <typename Params, typename Results>
cannam@149 789 inline CallContext<Params, Results>::CallContext(CallContextHook& hook): hook(&hook) {}
cannam@149 790 template <typename Params, typename Results>
cannam@149 791 inline typename Params::Reader CallContext<Params, Results>::getParams() {
cannam@149 792 return hook->getParams().template getAs<Params>();
cannam@149 793 }
cannam@149 794 template <typename Params, typename Results>
cannam@149 795 inline void CallContext<Params, Results>::releaseParams() {
cannam@149 796 hook->releaseParams();
cannam@149 797 }
cannam@149 798 template <typename Params, typename Results>
cannam@149 799 inline typename Results::Builder CallContext<Params, Results>::getResults(
cannam@149 800 kj::Maybe<MessageSize> sizeHint) {
cannam@149 801 // `template` keyword needed due to: http://llvm.org/bugs/show_bug.cgi?id=17401
cannam@149 802 return hook->getResults(sizeHint).template getAs<Results>();
cannam@149 803 }
cannam@149 804 template <typename Params, typename Results>
cannam@149 805 inline typename Results::Builder CallContext<Params, Results>::initResults(
cannam@149 806 kj::Maybe<MessageSize> sizeHint) {
cannam@149 807 // `template` keyword needed due to: http://llvm.org/bugs/show_bug.cgi?id=17401
cannam@149 808 return hook->getResults(sizeHint).template initAs<Results>();
cannam@149 809 }
cannam@149 810 template <typename Params, typename Results>
cannam@149 811 inline void CallContext<Params, Results>::setResults(typename Results::Reader value) {
cannam@149 812 hook->getResults(value.totalSize()).template setAs<Results>(value);
cannam@149 813 }
cannam@149 814 template <typename Params, typename Results>
cannam@149 815 inline void CallContext<Params, Results>::adoptResults(Orphan<Results>&& value) {
cannam@149 816 hook->getResults(nullptr).adopt(kj::mv(value));
cannam@149 817 }
cannam@149 818 template <typename Params, typename Results>
cannam@149 819 inline Orphanage CallContext<Params, Results>::getResultsOrphanage(
cannam@149 820 kj::Maybe<MessageSize> sizeHint) {
cannam@149 821 return Orphanage::getForMessageContaining(hook->getResults(sizeHint));
cannam@149 822 }
cannam@149 823 template <typename Params, typename Results>
cannam@149 824 template <typename SubParams>
cannam@149 825 inline kj::Promise<void> CallContext<Params, Results>::tailCall(
cannam@149 826 Request<SubParams, Results>&& tailRequest) {
cannam@149 827 return hook->tailCall(kj::mv(tailRequest.hook));
cannam@149 828 }
cannam@149 829 template <typename Params, typename Results>
cannam@149 830 inline void CallContext<Params, Results>::allowCancellation() {
cannam@149 831 hook->allowCancellation();
cannam@149 832 }
cannam@149 833
cannam@149 834 template <typename Params, typename Results>
cannam@149 835 CallContext<Params, Results> Capability::Server::internalGetTypedContext(
cannam@149 836 CallContext<AnyPointer, AnyPointer> typeless) {
cannam@149 837 return CallContext<Params, Results>(*typeless.hook);
cannam@149 838 }
cannam@149 839
cannam@149 840 Capability::Client Capability::Server::thisCap() {
cannam@149 841 return Client(thisHook->addRef());
cannam@149 842 }
cannam@149 843
cannam@149 844 template <typename T>
cannam@149 845 T ReaderCapabilityTable::imbue(T reader) {
cannam@149 846 return T(_::PointerHelpers<FromReader<T>>::getInternalReader(reader).imbue(this));
cannam@149 847 }
cannam@149 848
cannam@149 849 template <typename T>
cannam@149 850 T BuilderCapabilityTable::imbue(T builder) {
cannam@149 851 return T(_::PointerHelpers<FromBuilder<T>>::getInternalBuilder(kj::mv(builder)).imbue(this));
cannam@149 852 }
cannam@149 853
cannam@149 854 template <typename T>
cannam@149 855 typename T::Client CapabilityServerSet<T>::add(kj::Own<typename T::Server>&& server) {
cannam@149 856 void* ptr = reinterpret_cast<void*>(server.get());
cannam@149 857 // Clang insists that `castAs` is a template-dependent member and therefore we need the
cannam@149 858 // `template` keyword here, but AFAICT this is wrong: addImpl() is not a template.
cannam@149 859 return addInternal(kj::mv(server), ptr).template castAs<T>();
cannam@149 860 }
cannam@149 861
cannam@149 862 template <typename T>
cannam@149 863 kj::Promise<kj::Maybe<typename T::Server&>> CapabilityServerSet<T>::getLocalServer(
cannam@149 864 typename T::Client& client) {
cannam@149 865 return getLocalServerInternal(client)
cannam@149 866 .then([](void* server) -> kj::Maybe<typename T::Server&> {
cannam@149 867 if (server == nullptr) {
cannam@149 868 return nullptr;
cannam@149 869 } else {
cannam@149 870 return *reinterpret_cast<typename T::Server*>(server);
cannam@149 871 }
cannam@149 872 });
cannam@149 873 }
cannam@149 874
cannam@149 875 template <typename T>
cannam@149 876 struct Orphanage::GetInnerReader<T, Kind::INTERFACE> {
cannam@149 877 static inline kj::Own<ClientHook> apply(typename T::Client t) {
cannam@149 878 return ClientHook::from(kj::mv(t));
cannam@149 879 }
cannam@149 880 };
cannam@149 881
cannam@149 882 } // namespace capnp
cannam@149 883
cannam@149 884 #endif // CAPNP_CAPABILITY_H_