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

View File

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

View File

@@ -9,12 +9,13 @@
#include "TaskWindow.h" #include "TaskWindow.h"
#include "Task.h" #include "Task.h"
TaskWindow::TaskWindow(std::string title_, Task * task_): TaskWindow::TaskWindow(std::string title_, Task * task_, bool closeOnDone):
task(task_), task(task_),
title(title_), title(title_),
ui::Window(ui::Point(-1, -1), ui::Point(300, 200)), ui::Window(ui::Point(-1, -1), ui::Point(300, 200)),
progress(0), 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); 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) void TaskWindow::NotifyDone(Task * task)
{
if(closeOnDone)
Exit();
}
void TaskWindow::Exit()
{ {
if(ui::Engine::Ref().GetWindow()==this) if(ui::Engine::Ref().GetWindow()==this)
{ {
@@ -50,6 +57,9 @@ void TaskWindow::NotifyProgress(Task * task)
void TaskWindow::OnTick(float dt) void TaskWindow::OnTick(float dt)
{ {
intermediatePos += 1.0f*dt;
if(intermediatePos>100.0f)
intermediatePos = 0.0f;
task->Poll(); 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); 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... if(progress!=-1)
g->fillrect(Position.X + 20, Position.Y + 36, size, 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);
} 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() { TaskWindow::~TaskWindow() {

View File

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