annotate win32-mingw/include/capnp/capability.h @ 141:1b5b6dfd0d0e

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