提问人:Paul 提问时间:8/17/2023 更新时间:8/17/2023 访问量:52
C++ boost 回调返回数据
C++ boost callback returning data
问:
我正在努力从回调中获取数据(而不是向回调发送参数)。我可以在没有数据的情况下触发回调,但希望能得到一些关于我所缺少内容的指导。如上所述,它可以在不返回数据的情况下工作,将相邻的注释掉的行换成我的尝试作为返回数据(所以错误很可能在那里)。
#include <iostream>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <map>
#include <string>
typedef boost::function<void()> callback;
//typedef boost::function<void(std::string)> callback; // With return argument
class B
{
public:
//typedef boost::shared_ptr<const printer> SharedConst;
B(boost::asio::io_service& io, std::string name_, int target_, callback call_)
: timer_(io, boost::posix_time::seconds(1)),
count(1), target(target_), name(name_), call(call_)
{
timer_.async_wait(boost::bind(&B::print, this));
}
~B()
{
std::cout << "Final count is " << count << "\n";
}
void print()
{
if (count < target)
{
std::cout << name << " : " << count << "\n";
++count;
timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));
timer_.async_wait(boost::bind(&B::print, this));
}
else {
call();
//call(name);
}
}
private:
callback call;
boost::asio::deadline_timer timer_;
int count;
int target;
std::string name;
};
class A {
private:
std::map<std::string, B*> jobs;
boost::asio::io_service io;
public:
void acceptResult()
//void acceptResult(std::string jobID_)
{
std::cout << "acceptResult" << std::endl;
//std::cout << "acceptResult from job : " << jobID_<< std::endl;
//free(jobs.at(jobID_));
//auto it = jobs.find(jobID_);
//jobs.erase(it);
}
void newJob(std::string jobID_, unsigned int target)
{
B *b = new B(io, jobID_, target, boost::bind(&A::acceptResult, this));
jobs.insert({jobID_, b});
}
void run()
{
io.run();
}
};
int main()
{
A a;
a.newJob("j1", 5);
a.newJob("j2", 3);
a.run();
return 0;
}
输出(不返回值):
j1 : 1
j2 : 1
j1 : 2
j2 : 2
j1 : 3
acceptResult
j1 : 4
acceptResult
提前致谢,保罗。
答:
2赞
sehe
8/17/2023
#1
首先,我们来清理一些问题:
- 初始化顺序 ( 之后
callback
name
) - 内存泄漏(应管理作业生存期):
jobs
- 销毁顺序(应该在 AFTER
io
jobs
)
我可能修复了更多,但我忘记了: Live On Coliru:
j1 : 1
j2 : 1
j1 : 2
j2 : 2
j1 : 3
acceptResult
j1 : 4
acceptResult
Final count is 3
Final count is 5
问题
取消注释“问题”行,我注意到您忘记了参数的占位符:bind
name
boost::bind(&A::acceptResult, this, boost::placeholders::_1)
就这样!由于我的选择,不需要复杂(而且不是例外安全)的舞蹈。哦,更不用说 / 是不正确的!unique_ptr
free
new
delete
void acceptResult(std::string jobID_) {
std::cout << "acceptResult from job : " << jobID_<< std::endl;
jobs.erase(jobID_);
}
#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <iostream>
#include <map>
#include <string>
using callback = std::function<void(std::string)>; // With return argument
class B {
public:
B(boost::asio::io_service& io, std::string name_, int target_, callback call_)
: timer_(io, boost::posix_time::seconds(1))
, count(1)
, target(target_)
, name(name_)
, call(call_) {
timer_.async_wait(boost::bind(&B::print, this));
}
~B() { std::cout << "Final count is " << count << "\n"; }
void print() {
if (count < target) {
std::cout << name << " : " << count << "\n";
++count;
timer_.expires_at(timer_.expires_at() + boost::posix_time::seconds(1));
timer_.async_wait(boost::bind(&B::print, this));
} else {
call(name);
}
}
private:
boost::asio::deadline_timer timer_;
int count;
int target;
std::string name;
callback call;
};
class A {
private:
boost::asio::io_service io; // ORDER! destruct last
std::map<std::string, std::unique_ptr<B>> jobs;
public:
void acceptResult(std::string jobID_) {
std::cout << "acceptResult from job : " << jobID_<< std::endl;
jobs.erase(jobID_);
}
void newJob(std::string jobID_, unsigned int target) {
jobs.emplace(jobID_,
std::make_unique<B>(io, jobID_, target,
boost::bind(&A::acceptResult, this, boost::placeholders::_1)));
}
void run() { io.run(); }
};
int main() {
A a;
a.newJob("j1", 5);
a.newJob("j2", 3);
a.run();
}
指纹
j1 : 1
j2 : 1
j1 : 2
j2 : 2
j1 : 3
acceptResult from job : j2
Final count is 3
j1 : 4
acceptResult from job : j1
Final count is 5
评论
0赞
Paul
8/17/2023
谢谢 sehe,无论是以“原始”非 lambda 方式修复它,因为这仍然困扰着我为什么它是错误的,并修复了我的其他错误。
1赞
Ted Lyngmo
8/17/2023
@Paul这就是我提到的“隐式占位符 (_1
) 的弃用功能”。我应该添加它来显示它的去向,但选择了(恕我直言)更简单的 lambda。我也使用 s 作为测试,但得到了一个竞争条件。奇怪。我现在刚刚将它添加到我的代码中,当然它就像一个魅力:-)unique_ptr
0赞
sehe
8/18/2023
@TedLyngmo 您能指出这种“隐式占位符”的文档/示例吗?据我所知,Boost Bind 中从未存在过这样的功能。Boost Lambda/Phoenix 占位符可能存在混淆,甚至与全局命名空间占位符的默认声明混淆,这些占位符最近确实被弃用了(但从来都不是隐式的,只是污染了全局命名空间)。
1赞
Ted Lyngmo
8/18/2023
@sehe我不是从文档中得到的,而是在编译时得到的,但我没有正确记住确切的消息。它是:“声明 Bind 占位符 (_1, _2, ...) 的做法在全局命名空间中已弃用。请使用<boost/bind/bind.hpp>......“ - 所以,不是一回事,不是......
1赞
sehe
8/18/2023
@TedLyngmo不不不,完全诚实。我亲身体会到,在这个网站上做出贡献可能很耗时,而且相对来说吃力不讨好。我知道我从你那里看到了一些深刻的见解,所以我很高兴能够向你提问,并看到你在这个网站上帮助人们。(英语也不是我的第一语言,但老实说,我认为这更多的是关于人们从不表达感谢,或者当它发生时,人们担心的程度还不够!
评论
async_wait
boost::bind(&A::acceptResult, this)
_1
<boost/bind/bind.hpp>
bind