1

I want to follow a thread progress. I have already implemented progress bar graphically, but I am wondering how to efficiently measure progress of the thread in a real time.

Progress bar

template<typename T>
inline T Saturate(T value, T min = static_cast<T>(0.0f), T max = static_cast<T>(1.0f))
{
    return value < static_cast<T>(min) ? static_cast<T>(min) : value > static_cast<T>(max) ? static_cast<T>(max) : value;
}

void ProgressBar(float progress, const Vector2& size)
{
    Panel* window = getPanel();

    Vector2 position = //some position                                                                                                                              
    progress = Saturate(progress);

    window->renderer->FillRect({ position, size }, 0xff00a5ff);
    window->renderer->FillRect(Rect(position.x, position.y, Lerp(0.0f, size.w, progress), size.h), 0xff0000ff);

    //progress will be shown as a %
    std::string progressText;       
    //ToString(value, how many decimal places)                                                                                                                        
    progressText = ToString(progress * 100.0f, 2) + "%";                                                

    const float textWidth = font->getWidth(progressText) * context.fontScale,
                textX = Clamp(Lerp(position.x, position.x + size.w, progress), position.x, position.x + size.w - textWidth);
    window->renderer->DrawString(progressText, Vector2(textX, position.y + font->getAscender(progressText) * context.fontScale * 0.5f), 0xffffffff, context.fontScale, *font.get());
}

and somewhere in a game loop, example usage

static float prog = 0.0f;
float progSpeed = 0.01f;
static float progDir = 1.0f;
prog += progSpeed * (1.0f / 60.0f) * progDir;

ProgressBar(prog, { 100.0f, 30.0f });

I know how to measure execution time:

uint t1 = getTime();
//... do sth
uint t2 = getTime();
uint executionTime = t2 - t1;

but of course progress bar will be updated after execution, so it won't be shown in a real time.

Should I use a new thread? Are there any other methods to do this?

  • 1
    May depend on the kind of _progress bar_ you are using. Does it have an interface to convey to the maximum in form of an estimated time property? What time resolution should be used (realtime isn't really a thing, every kind of _realtime_ is based on a certain resolution, the operating system is able to guarantee)? – πάντα ῥεῖ Feb 27 '19 at 19:44
  • It is programmed to be from 0.0f to 1.0f. I think that time might be in a milliseconds and I'd convert it to 0.0f -> 1.0f –  Feb 27 '19 at 19:53
  • I am afraid you have to be more specific about your GUI framework, what specific _`ProgressBar`_ you are using, how you configure it, and how you're planning to update it. I think that should be the minimum code to be included in your question as showing an attempt. – πάντα ῥεῖ Feb 27 '19 at 19:53
  • Change `do sth` to periodically report progress.. – rustyx Feb 27 '19 at 19:54
  • Ok, I thought progress bar is a progress bar, but if it is a case. I have already updated the question. –  Feb 27 '19 at 20:02
  • @rustyx how to do this? Could you write something more, please? –  Feb 27 '19 at 20:03

1 Answers1

1

All you can do for a progress bar is show an estimate or how long you have progressed based on the work you have already done (with an estimate (or maybe exact knowledge) of the total work to do.

All you know is what work has been done and the time that took. The time it takes to do everything is always going to be an estimate. You can usually do pretty good by basing the estimate on the already completed work, but not always.

Making an exact progress bar is (in most cases) Impossible. Best you can do is a guesstimate.

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
  • So, I should periodically report progress as if rustyx suggested. How to do this, though. –  Feb 27 '19 at 20:05
  • @JarekBisnesu If you are writing everything yourself, you need to add the capability for callbacks so that the thread can send messages to the progress bar to keep the bar up to date. If you are using a framework, odds are good this plumbing is built in (.Net `BackgroundWorker` for example). – user4581301 Feb 27 '19 at 20:10
  • I am more into writing everything myself, because I want to learn something and know how it works than just use it. I will try to think (and google) out how to add the capability for callbacks, I'll let you know later. –  Feb 27 '19 at 20:14
  • 1
    What GUI library or framework are you using? Any answer would depend on that. – drescherjm Feb 27 '19 at 20:14
  • Maybe you want boost::signals2 for this: https://theboostcpplibraries.com/boost.signals2-multithreading – drescherjm Feb 27 '19 at 20:19
  • @drescherjm I'd rather want to write own one. –  Feb 27 '19 at 21:03
  • @user4581301 should I create a class like ProgressCallback with for example float progress inside and for every, for instance, millisecond, stop the thread, return the callback, update progress bar and then run a thread again but now start writing to data from the point that I stopped writing to it? –  Feb 27 '19 at 21:03
  • @JarekBisnesu You don't necessarily have to go as far as a class. A simple function is more than enough most of the time. How much do you know about thread synchronization? That's going to be the hard part. It is really easy for the background thread to provide an update in the middle of a progress bar draw operation and result in bad behaviour. – user4581301 Feb 27 '19 at 21:12
  • @user4581301 I know mutex, guard lock, unique lock, condition variables and maybe more which I do not remember right now, but might be remined while writing. Should I know something more? –  Feb 27 '19 at 21:18
  • @JarekBisnesu That's enough to get you started, but also look into [message loops](https://stackoverflow.com/a/2223270/4581301). – user4581301 Feb 27 '19 at 21:22