gpt4 book ai didi

c++ - 我怎样才能有效地使用 boost::progress_display 的回调?

转载 作者:太空宇宙 更新时间:2023-11-04 11:32:19 24 4
gpt4 key购买 nike

我想对 boost::progress_display 使用回调。首先,我有一个 Foo 类,我需要从以下位置广播事件:

class Foo
{
public:
template <typename L>
void attachListener(L const &listener)
{
m_callback.connect(listener);
}

void doWork()
{
for(...stuff...) {
m_callback(m_someData);
}
}
private:
Data m_someData;
boost::signals2::signal<void(Data const&)> m_callback;

}

然后,在其他一些代码中,我有一个回调用于处理来自 Foo 的事件。然后,我在 otherFunction 中创建一个 Foo 并为其附加回调:

void callback(Data const &someData, boost::progress_display &pd)
{
// other stuff
++pd;
}

void otherFunction()
{
boost::progress_display pd(100);
boost::function<void(Data const&)> f(boost::bind(&callback, _1, boost::ref(pd)));
Foo foo;
foo.attachListener(f);
foo.doWork();
}

当上面的代码运行时,回调将从 Foo::doWork 调用。

这是将回调与 boost::progress_display 结合使用的正确方法吗?

如果我需要创建并附加多个处理程序,每个处理程序都有自己的 boost::progress_display,这会变得很烦人。这样做意味着每个单独的 progress_display 百分比条都会一个接一个地打印出来。

谢谢,本。

最佳答案

更新 作为对评论的回应,这里有一个 progress_group 的简单实现。和 group_progress_display一起使用的类可以轻松地为多个不同的进度项(progress_group::item 实例)显示单个进度条。

查看 Live On Coliru

让我们看看progress_group :

struct progress_group {
struct item {
size_t current, total;

item(size_t total=100, size_t current=0)
: current(current), total(total) { }

void tick() {
if (current < total) current++;
}
};

std::list<boost::weak_ptr<progress_group::item> > members;

void add(boost::shared_ptr<item> const& pi) {
assert(pi);
members.push_back(pi);
}

item get_cumulative() {
item cumul(0, 0);

for(auto& wpi : members) {
auto pi = wpi.lock();

if (pi) {
cumul.current += pi->current;
cumul.total += pi->total;
}
}

return cumul;
}
};

请注意,我(任意地)选择使用弱指针,这样进度项可能会消失,并且只会调整比例。


实际进度动态缩放到底层显示小部件的分辨率 (boost::progress_display)。这留下的主要限制是进度需要随着时间的推移严格增加(因为输出可能不是 tty):

struct group_progress_display {

group_progress_display() : _display(1000), _reentrancy(0) {
}

void add(boost::shared_ptr<progress_group::item> pi) {
_group.add(pi);
}

void update() {
if (1 == ++_reentrancy) // cheap synch
{
auto cumul = _group.get_cumulative();

if (cumul.total > 0)
{
size_t target = (1.0 * cumul.current)/cumul.total * _display.expected_count();

if (target >= _display.count())
_display += target - _display.count();
}
}
--_reentrancy;
}
private:
boost::progress_display _display;
progress_group _group;
boost::atomic_int _reentrancy;
};

此示例在线程中运行 100 个不同负载的后台作业,并显示一个累积进度小部件:

int main()
{
boost::thread_group workers;
group_progress_display display;

for (int i = 0; i < 100; ++i)
{
auto load = (rand()%5) * 1500;
auto progress_item = boost::make_shared<progress_group::item>(load);
display.add(progress_item);

worker this_worker(progress_item->total);
this_worker.attachListener([=,&display]{
progress_item->tick();
display.update();
});

workers.create_thread(this_worker);
}

workers.join_all();
}

(请注意 lambda(或 c++03 的 boost::bind 表达式)本身如何使共享指针保持事件状态。)

worker对进度实现一无所知:

struct worker {
explicit worker(size_t count) : count(count) {}

template <typename L>
void attachListener(L&& listener) {
m_callback = std::forward<L>(listener);
}

void operator()()
{
for (size_t i = 0; i < count; ++i) {
boost::this_thread::sleep_for(boost::chrono::microseconds(500));
m_callback();
}
}

private:
boost::function<void()> m_callback;
size_t count;
};

旧答案

这似乎有效 Live On Coliru .

一个潜在的问题是,此时,进度指示器必须以某种方式包含有关流程步骤的准确信息。您可能希望隐藏该信息(在 Data 中,或将其包装在一个也添加进度信息的类中),然后使用一些简单的算术可以转换为固定比例(例如,100)。

这甚至允许您的 Foo::doWork即时调整比例,这在很大程度上证明了解耦正在发挥作用。

关于c++ - 我怎样才能有效地使用 boost::progress_display 的回调?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24264608/

24 4 0
文章推荐: c - 程序启动前valgrind奇怪的条件跳转信息
文章推荐: java - Wicket 7 - 向导完成按钮生成多个 onClick 事件
文章推荐: linux - 玩弄 LD_LIBRARY_PATH
文章推荐: html -
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com