我需要在服务器回调中执行一些客户端请求,并且不确定在何处存储创建的capnp::EzRpcClient
和CompareNetwork::Client comparer
对象。这是因为客户超出了范围(我认为 - 我只是得到了一个SEGFAULT,但这似乎是原因)。它基本上是一个主人,它将加载请求转发给它的奴隶(奴隶可以通过REG请求注册并存储他们的地址)。
那么 - 我应该在哪里/如何存储客户端对象?这有什么“最佳实践”吗?我认为暂时将它们存储在某个类成员变量中有点脏,不是吗?
GroupMaster2.cpp:
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:
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
答案 0 :(得分:0)
C ++ 14似乎有答案:
How to capture a unique_ptr into a lambda expression?
使用kj :: heap在堆上分配两个对象,并将kj :: Own移动到回调lambda:
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;
}
}
欢迎更好的想法,但目前似乎运作良好:)