首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Capnproto -在服务器回调中发出客户端请求

Capnproto -在服务器回调中发出客户端请求
EN

Stack Overflow用户
提问于 2018-04-08 04:22:58
回答 1查看 221关注 0票数 0

我需要在服务器回调中执行一些客户端请求,并且不确定将创建的capnp::EzRpcClientCompareNetwork::Client comparer对象存储在哪里。这是因为客户端超出了范围(我认为-我只是得到了SEGFAULT,但这似乎是原因)。它基本上是一个将加载请求转发给它的从站的主站(从站可以通过REG-request注册,并且它们的地址被存储)。

那么-我应该在哪里/如何存储客户端对象?这方面有什么“最佳实践”吗?我认为将它们临时存储在某个类成员变量中有点脏,不是吗?

GroupMaster2.cpp:

代码语言:javascript
复制
kj::Promise<void> GroupMaster2::CompareMasterImpl::load(LoadContext context) {
    auto loadData = context.getParams().getIds();

    slaveListLock.lock();

    auto promList = kj::Vector<kj::Promise<std::pair<std::string, CompareNetwork::Status>>>();

    for(auto& slave : slaveList) {
        try {
            capnp::EzRpcClient client(slave.second->address);
            CompareNetwork::Client comparer = client.getMain<CompareNetwork>();
            auto request = comparer.loadRequest();
            std::string addrCopy(slave.first);
            request.setIds(loadData);
            auto loadPromise = request.send();
            promList.add(loadPromise.then([addrCopy](auto response) {
                return std::make_pair(addrCopy, response.getStatus());
            },
            [&, addrCopy](kj::Exception && exception) {
                slaveListLock.lock();
                slaveList.erase(addrCopy);//something failed, remove this slave!
                slaveListLock.unlock();
                std::cout << "ErrLoad0: " << std::string(exception.getDescription()) << std::endl;
                return std::make_pair(addrCopy, CompareNetwork::Status::ERROR);
            }));
        }
        catch(...) {
            std::cout << "Error sending load to: " << slave.first << std::endl;
        }
    }

    slaveListLock.unlock();

    auto retProm = kj::joinPromises(promList.releaseAsArray()).then([&, KJ_CPCAP(context)](kj::Array<std::pair<std::string, CompareNetwork::Status>> res) mutable {
        bool error = false;

        for(auto& loadRes : res) {
            switch(loadRes.second) {
                case CompareNetwork::Status::OK: {
                        std::cout << "LOAD OK: " << loadRes.first << std::endl;
                        break;
                    }

                case CompareNetwork::Status::ERROR: {
                        std::cout << "LOAD ERROR: " << loadRes.first << std::endl;
                        error = true;
                        break;
                    }
            }
        }
        if(!error)
            context.getResults().setStatus(CompareNetwork::Status::OK);
        else
            context.getResults().setStatus(CompareNetwork::Status::ERROR);
    }, [](kj::Exception && exception) {
        std::cout << __FILE__ << ":" << __LINE__ << std::string(exception.getDescription()) << std::endl;
    }).eagerlyEvaluate([](kj::Exception && exception) {
        std::cout << __FILE__ << ":" << __LINE__ << std::string(exception.getDescription()) << std::endl;
    });
    std::cout << "ReturnedLoad" << std::endl;
    return retProm;
}

GroupNetworkData.capnp:

代码语言:javascript
复制
interface CompareNetwork {
  compare @0 (jobs :JobPartList) -> (res :JobResList);
  load @1 (ids :WIDList) -> (status :Status);

  struct JobPartList {
    jobParts @0 :List(JobPart);

    struct JobPart {
      jobs @0 :List(Job);
      startID @1 :UInt32;

      struct Job {
        wid1 @0 :UInt32;
        wid2 @1 :UInt32;
      }
    }
  }

  struct JobResList {
    jobResults @0 :List(JobRes);
    struct JobRes {
      jobIndex @0 :UInt32;
      result @1 :Float64;
    }
  }

  struct WIDList {
    ids @0 :List(WID);
    struct WID {
      id @0 :UInt32;
    }
  }

  enum Status {
    ok @0;
    error @1;
  }
}

interface CompareMaster extends(CompareNetwork) {
  reg @0 (data :SlaveData) -> (status :CompareNetwork.Status);
  struct SlaveData {
    perfInd @0 :Float64;
    maxMem @1 :UInt32;
    address @2 :Text;
  }
}

提前感谢!dvs23

EN

回答 1

Stack Overflow用户

发布于 2018-04-08 06:48:16

C++14似乎有答案:

How to capture a unique_ptr into a lambda expression?

使用kj::heap分配堆上的两个对象,并将kj::Own移动到回调lambda:

代码语言:javascript
复制
for(auto& slave : slaveList) {
    try {
        auto client = kj::heap<capnp::EzRpcClient>(slave.second->address);
        auto comparer = kj::heap<CompareNetwork::Client>(client->getMain<CompareNetwork>());
        auto request = comparer->loadRequest();
        std::string addrCopy(slave.first);
        request.setIds(loadData);
        auto loadPromise = request.send();
        promList.add(loadPromise.then([addrCopy, client = std::move(client), comparer = std::move(comparer)](auto response) {
            return std::make_pair(addrCopy, response.getStatus());
        },
        [&, addrCopy](kj::Exception && exception) {
            slaveListLock.lock();
            slaveList.erase(addrCopy);//something failed, remove this slave!
            slaveListLock.unlock();
            std::cout << "ErrLoad0: " << std::string(exception.getDescription()) << std::endl;
            return std::make_pair(addrCopy, CompareNetwork::Status::ERROR);
        }));
    }
    catch(...) {
        std::cout << "Error sending load to: " << slave.first << std::endl;
    }
}

更好的想法是受欢迎的,但目前它似乎运行得很好:)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49711638

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档