I would like to use callbacks with boost::progress_display. Firstly I have a class Foo that I need to broadcast events from:
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;
}
Then, in some other code, I have a callback that is used to handle events coming from Foo. I then create a Foo in otherFunction and attach callback to it:
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();
}
When the above is run, the callback will be called from Foo::doWork.
Is this the correct way to use callbacks in combination with boost::progress_display?
It can become annoying where I need to create and attach multiple handlers each with their own boost::progress_display. Doing this would mean that each individual progress_display percentage bar is printed out one after the other.
Thanks, Ben.
UPDATE In response to the comment, here's a simple implementation of
progress_group
andgroup_progress_display
classes that together make it easy to display a single progress bar for several different progress items (progress_group::item
instances).See it Live On Coliru.
Let's look at
progress_group
:Note that I (arbitrarily) opted to use weak pointers so the progress items may disappear and the scale will just be adjusted.
The actual progress is dynamically scaled to the resolution of the underlying display widget (
boost::progress_display
). The main limitation this leaves is that the progress needs to be strictly increasing over time (as the output might not be to a tty):This sample runs 100 background jobs of varying loads in threads, and displays a single, cumulative progress widget:
(Note how the lambda (or
boost::bind
expression for c++03) itself keeps the shared pointer alive.)The
worker
doesn't know a single thing about the progress implementation:Old Answer
This would appear to work Live On Coliru.
A potential issue would be that, at this moment, the progress indicator somehow has to have accurate information about the process steps. You might want to hide that information (inside Data, or wrap it in a class that also adds the progress information), then using some simple arithmetics you could translate to a fixed scale (say, 100).
This would allow even your
Foo::doWork
to adjust the scale on-the-fly, which is pretty much proof that the decoupling is working.