Make status updates on tasks safe - add intermediate progress bar for TaskWindow

This commit is contained in:
Simon Robertshaw 2012-06-21 13:22:52 +01:00
parent 09758b9152
commit 12ba6834eb
4 changed files with 64 additions and 19 deletions

View File

@ -17,8 +17,13 @@ void Task::SetTaskListener(TaskListener * listener)
void Task::Start()
{
thDone = false;
done = false;
progress = 0;
status = "";
taskMutex = PTHREAD_MUTEX_INITIALIZER;
before();
pthread_mutex_init (&taskMutex, NULL);
pthread_cond_init(&taskCond, NULL);
pthread_create(&doWorkThread, 0, &Task::doWork_helper, this);
}
@ -40,13 +45,12 @@ bool Task::GetDone()
void Task::Poll()
{
int newProgress;
bool newDone;
bool newDone = false;
std::string newStatus;
pthread_mutex_lock(&taskMutex);
newProgress = thProgress;
newDone = thDone;
newStatus = std::string(thStatus);
pthread_cond_signal(&taskCond);
pthread_mutex_unlock(&taskMutex);
if(newProgress!=progress) {
@ -55,21 +59,23 @@ void Task::Poll()
listener->NotifyProgress(this);
}
if(newStatus!=status) {
status = newStatus;
status = std::string(newStatus);
if(listener)
listener->NotifyStatus(this);
}
if(newDone!=done)
{
done = newDone;
if(listener)
listener->NotifyDone(this);
}
if(done)
{
pthread_join(doWorkThread, NULL);
pthread_mutex_destroy(&taskMutex);
after();
}
if(newDone!=done)
{
done = newDone;
if(listener)
listener->NotifyDone(this);
}
}
@ -78,6 +84,11 @@ Task::~Task()
}
void Task::before()
{
}
void Task::doWork()
{
notifyStatus("Fake progress");
@ -88,6 +99,11 @@ void Task::doWork()
}
}
void Task::after()
{
}
void * Task::doWork_helper(void * ref)
{
((Task*)ref)->doWork();
@ -98,7 +114,6 @@ void * Task::doWork_helper(void * ref)
void Task::notifyProgress(int progress)
{
pthread_mutex_lock(&taskMutex);
pthread_cond_wait(&taskCond, &taskMutex);
thProgress = progress;
pthread_mutex_unlock(&taskMutex);
}
@ -106,15 +121,13 @@ void Task::notifyProgress(int progress)
void Task::notifyStatus(std::string status)
{
pthread_mutex_lock(&taskMutex);
pthread_cond_wait(&taskCond, &taskMutex);
thStatus = status;
thStatus = std::string(status);
pthread_mutex_unlock(&taskMutex);
}
void Task::notifyDone()
{
pthread_mutex_lock(&taskMutex);
pthread_cond_wait(&taskCond, &taskMutex);
thDone = true;
pthread_mutex_unlock(&taskMutex);
}

View File

@ -37,6 +37,9 @@ protected:
pthread_mutex_t taskMutex;
pthread_cond_t taskCond;
virtual void before();
virtual void after();
virtual void doWork();
static void * doWork_helper(void * ref);

View File

@ -9,12 +9,13 @@
#include "TaskWindow.h"
#include "Task.h"
TaskWindow::TaskWindow(std::string title_, Task * task_):
TaskWindow::TaskWindow(std::string title_, Task * task_, bool closeOnDone):
task(task_),
title(title_),
ui::Window(ui::Point(-1, -1), ui::Point(300, 200)),
progress(0),
done(false)
done(false),
closeOnDone(closeOnDone)
{
ui::Label * tempLabel = new ui::Label(ui::Point(3, 3), ui::Point(Size.X-6, 16), title);
@ -35,6 +36,12 @@ void TaskWindow::NotifyStatus(Task * task)
}
void TaskWindow::NotifyDone(Task * task)
{
if(closeOnDone)
Exit();
}
void TaskWindow::Exit()
{
if(ui::Engine::Ref().GetWindow()==this)
{
@ -50,6 +57,9 @@ void TaskWindow::NotifyProgress(Task * task)
void TaskWindow::OnTick(float dt)
{
intermediatePos += 1.0f*dt;
if(intermediatePos>100.0f)
intermediatePos = 0.0f;
task->Poll();
}
@ -61,8 +71,24 @@ void TaskWindow::OnDraw()
g->drawrect(Position.X + 20, Position.Y + 36, Size.X-40, 24, 255, 255, 255, 255);
float size = float(Size.X-40)*(float(progress)/100.0f); // TIL...
g->fillrect(Position.X + 20, Position.Y + 36, size, 24, 255, 255, 255, 255);
if(progress!=-1)
{
float size = float(Size.X-40)*(float(progress)/100.0f); // TIL...
g->fillrect(Position.X + 20, Position.Y + 36, size, 24, 255, 255, 255, 255);
} else {
int size = 40, rsize = 0;
float position = float(Size.X-40)*(intermediatePos/100.0f);
if(position + size > Size.X-40)
{
size = (Size.X-40)-position;
rsize = 40-size;
}
g->fillrect(Position.X + 20 + position, Position.Y + 36, size, 24, 255, 255, 255, 255);
if(rsize)
{
g->fillrect(Position.X + 20, Position.Y + 36, rsize, 24, 255, 255, 255, 255);
}
}
}
TaskWindow::~TaskWindow() {

View File

@ -18,15 +18,18 @@ class TaskWindow: public ui::Window, public TaskListener {
Task * task;
std::string title;
int progress;
float intermediatePos;
bool done;
bool closeOnDone;
ui::Label * statusLabel;
public:
TaskWindow(std::string title_, Task * task_);
TaskWindow(std::string title_, Task * task_, bool closeOnDone = true);
virtual void NotifyStatus(Task * task);
virtual void NotifyDone(Task * task);
virtual void NotifyProgress(Task * task);
virtual void OnTick(float dt);
virtual void OnDraw();
virtual void Exit();
virtual ~TaskWindow();
};