1

我想尝试使用 Cap'n Proto C++ RPC 进行承诺流水线,但我不知道该怎么做。

这是我的架构:

interface Test {
  getInt @0 () -> (intResult :Int32);
  increment @1 (intParam :Int32) -> (intResult :Int32);
}

这是我想做的(伪代码):

increment(getInt());

我试图做这样的事情:

auto request1 = test.getIntRequest();
auto promise = request1.send();

auto request2 = test.incrementRequest();
request2.setIntParam(promise.getIntResult()) // HERE IS THE PROBLEM
auto promise2 = request2.send();

但这不是使用承诺的好方法。我希望你明白我想做什么。

谢谢你。

编辑:另一个问题:如何在服务器上实现这些方法?

我写了这段代码:

#include <kj/debug.h>
#include <capnp/ez-rpc.h>
#include <capnp/message.h>
#include <iostream>
#include "test.capnp.h"

using namespace std;


class TestI : virtual public Test::Server
{
public:
      TestI() {}
      ::kj::Promise<void> getInt(GetIntContext context) 
      {
            // ????
      }
      ::kj::Promise<void> increment(IncrementContext context) 
      {
            // ????
      }
};

class Int32BoxI : virtual public Int32Box::Server
{
private:
      int val = 12;
public:
      Int32BoxI(int value): val(value) {}
      ::kj::Promise<void> get(GetContext context)
      {
            context.getResults().setValue(this->val);
            return kj::READY_NOW;
      }
}

但我不知道如何实现 getInt() 和 increment()。

4

1 回答 1

2

这里的问题是您正在尝试在 int 上进行流水线化,但流水线化仅适用于对象引用。您可以通过将 int 包装在一个对象中来解决此问题,如下所示:

interface Int32Box {
  get @0 () -> (value :Int32);
}

interface Test {
  getInt @0 () -> (intResult :Int32Box);
  increment @1 (intParam :Int32Box) -> (intResult :Int32Box);
}

现在您的代码将按原样工作。

当然,现在您必须另外调用.get()finalInt32Box才能读取该值。不过幸运的是,您可以通过管道处理此调用,因此它不需要任何额外的网络往返。

auto request1 = test.getIntRequest();
auto promise = request1.send();

auto request2 = test.incrementRequest();
request2.setIntParam(promise.getIntResult());
auto promise2 = request2.send();

auto request3 = promise2.getIntResult().getRequest();
auto promise3 = request3.send();

// This is the only wait!
int finalResult = promise3.wait().getValue();

上述序列只执行一次网络往返。

于 2017-01-18T18:11:23.827 回答