Hi, Thanks for taking the time to respond. I was doing all of those things, simple communication works fine but it breaks when trying to pass a client capability to the server for it to use in the "publish" phase. I eventually figured out if I add in a
kj::NEVER_DONE.wait( client.getWaitScope() ); at the end everything works, but locks at the end of the test fixture (as you would expect). I think I fundamentally misunderstood where the event loop processing is done. I thought this was performed on a separate thread, so a simple "this_thread::sleap_for(...)" would allow all the handlers in the queue to finish (not the most optimal I know but I wanted to make sure everything worked first). I now know (think?) there must be a "wait()" _somewhere_ to enter the event loop again on the current thread and clear the queue. Since I'm using this in test fixtures, NEVER_DONE is not an option because I want to return control and carry on with other tests. - Is there a way with the ez-rpc interfaces to process everything currently in the queue and then return control? I see EventLoop has a "run()" method but I don't see a way to get the EventLoop from the EzRpcServer/Client. - If not, is there something like "kj::DO_UNTIL.wait( seconds(1), client.getWaitScope() )"; or a std::condition_variable style notification to stop? - With both client and server on the same event loop, there's no difference between "client.getWaitScope()" and "server.getWaitScope()" right? It does seem to be a great library by the way, the bits I've managed to get working. Thanks, Mark. On 25 August 2016 at 18:38, Kenton Varda <[email protected]> wrote: > Hi Mark, > > Terminology note: Think of "capability" as meaning the same thing as > "pointer", except it's a pointer that cannot be forged and without which > you cannot otherwise access the target object. An "interface" describes the > methods implemented by an object to which a capability points. > > What you describe should work, but there are a number of ways you might be > getting it wrong. It's hard to say which without seeing your code, but here > are some things to check: > > - Are you tearing down the RPC client too early? Once the network > connection closes, all capabilities delivered through it become > disconnected. Make sure you construct the RPC client (e.g. EzRpcClient) > once, not every time you want to make a call. > > - Are you discarding promises before they complete? When you have a > kj::Promise<T> representing an asynchronous task which hasn't completed > yet, and you allow that promise to go out-of-scope (without calling .then() > or anything else on it), the asynchronous task will be canceled. To prevent > this, create a kj::TaskSet and add promises to the set -- the TaskSet > ensures that the task runs to completion (unless you destroy the TaskSet, > of course). For example: > > void doThings(kj::TaskSet& tasks) { > kj::Promise<void> task1 = doSomething().then(...).then(...); > kj::Promise<void> task2 = doSomething().then(...).then(...); > > tasks.add(kj::mv(task1)); > } > > In the code above, only task1's .then()s will ever execute -- task2 will > be canceled when the function returns. > > - Another reason why a .then() continuation might not execute is if an > exception was thrown. You can catch exceptions by providing a second > callback to .then() which takes kj::Exception as the parameter. Note that > when creating a kj::TaskSet, you will be forced to provide an error > callback which will be used whenever a task throws an exception -- I > usually do KJ_LOG(ERROR, exception) inside that callback. > > -Kenton > > On Thu, Aug 25, 2016 at 3:14 AM, <[email protected]> wrote: > >> Hi, >> I'm trying to develop an application that replicates remote objects >> locally and keeps them updated. This effectively boils down to a >> publication-subscription model where the local proxy object sends an >> interface (capability in capnp speak?) to the server that can be used to >> send it notifications. The server stores this interface pointer and >> responds with an "okay", then later uses the interface to send the local >> object notifications if the server-side object changes. >> It doesn't work however. If I use the interface pointer after the >> original "subscription" call has resolved, the message is never received on >> the client. If I use the interface _during_ the subscription request the >> message is received by the client, but the "then(...)" block on the server >> is not executed. I've looked through the calculator example, but that uses >> the client-side interface immediately. >> >> - Can the interface pointers (capabilities right?) given in one call be >> stored for later use? I assume this must be the case but I can't be doing >> it correctly. >> - I'm using the ez-rpc interfaces. Is this one of the use cases not >> supported by them? >> - As this is my most basic test case, both the client and server are in >> the same compilation unit. I don't do any thread manipulation myself so I >> assume they're on the same event loop. Is this an issue? If so, I want >> the single process use case for testing, so is starting one or the other on >> a different thread sufficient? >> >> I can reduce the code to a simple example, but before going to the effort >> I wanted to make sure I'm not misunderstanding something. >> >> Thanks, >> >> Mark. >> >> Cap'n Proto version 0.5.3 >> >> -- >> You received this message because you are subscribed to the Google Groups >> "Cap'n Proto" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected]. >> Visit this group at https://groups.google.com/group/capnproto. >> > > -- You received this message because you are subscribed to the Google Groups "Cap'n Proto" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. Visit this group at https://groups.google.com/group/capnproto.
