ProgressBar: Fix updating

'updateCV.notify_one()' does nothing if the update thread is not
waiting for updateCV (in particular this happens when it is sleeping
on quitCV). So also set a variable to ensure that the update isn't
lost.
This commit is contained in:
Eelco Dolstra 2019-06-25 21:57:18 +02:00
parent 88571219d9
commit 324a5dc92f
No known key found for this signature in database
GPG key ID: 8170B4726D7198DE

View file

@ -62,6 +62,7 @@ private:
uint64_t corruptedPaths = 0, untrustedPaths = 0; uint64_t corruptedPaths = 0, untrustedPaths = 0;
bool active = true; bool active = true;
bool haveUpdate = true;
}; };
Sync<State> state_; Sync<State> state_;
@ -83,6 +84,7 @@ public:
updateThread = std::thread([&]() { updateThread = std::thread([&]() {
auto state(state_.lock()); auto state(state_.lock());
while (state->active) { while (state->active) {
if (!state->haveUpdate)
state.wait(updateCV); state.wait(updateCV);
draw(*state); draw(*state);
state.wait_for(quitCV, std::chrono::milliseconds(50)); state.wait_for(quitCV, std::chrono::milliseconds(50));
@ -178,7 +180,7 @@ public:
|| (type == actCopyPath && hasAncestor(*state, actSubstitute, parent))) || (type == actCopyPath && hasAncestor(*state, actSubstitute, parent)))
i->visible = false; i->visible = false;
update(); update(*state);
} }
/* Check whether an activity has an ancestore with the specified /* Check whether an activity has an ancestore with the specified
@ -213,7 +215,7 @@ public:
state->its.erase(i); state->its.erase(i);
} }
update(); update(*state);
} }
void result(ActivityId act, ResultType type, const std::vector<Field> & fields) override void result(ActivityId act, ResultType type, const std::vector<Field> & fields) override
@ -223,7 +225,7 @@ public:
if (type == resFileLinked) { if (type == resFileLinked) {
state->filesLinked++; state->filesLinked++;
state->bytesLinked += getI(fields, 0); state->bytesLinked += getI(fields, 0);
update(); update(*state);
} }
else if (type == resBuildLogLine) { else if (type == resBuildLogLine) {
@ -239,26 +241,26 @@ public:
info.lastLine = lastLine; info.lastLine = lastLine;
state->activities.emplace_back(info); state->activities.emplace_back(info);
i->second = std::prev(state->activities.end()); i->second = std::prev(state->activities.end());
update(); update(*state);
} }
} }
} }
else if (type == resUntrustedPath) { else if (type == resUntrustedPath) {
state->untrustedPaths++; state->untrustedPaths++;
update(); update(*state);
} }
else if (type == resCorruptedPath) { else if (type == resCorruptedPath) {
state->corruptedPaths++; state->corruptedPaths++;
update(); update(*state);
} }
else if (type == resSetPhase) { else if (type == resSetPhase) {
auto i = state->its.find(act); auto i = state->its.find(act);
assert(i != state->its.end()); assert(i != state->its.end());
i->second->phase = getS(fields, 0); i->second->phase = getS(fields, 0);
update(); update(*state);
} }
else if (type == resProgress) { else if (type == resProgress) {
@ -269,7 +271,7 @@ public:
actInfo.expected = getI(fields, 1); actInfo.expected = getI(fields, 1);
actInfo.running = getI(fields, 2); actInfo.running = getI(fields, 2);
actInfo.failed = getI(fields, 3); actInfo.failed = getI(fields, 3);
update(); update(*state);
} }
else if (type == resSetExpected) { else if (type == resSetExpected) {
@ -281,17 +283,19 @@ public:
state->activitiesByType[type].expected -= j; state->activitiesByType[type].expected -= j;
j = getI(fields, 1); j = getI(fields, 1);
state->activitiesByType[type].expected += j; state->activitiesByType[type].expected += j;
update(); update(*state);
} }
} }
void update() void update(State & state)
{ {
state.haveUpdate = true;
updateCV.notify_one(); updateCV.notify_one();
} }
void draw(State & state) void draw(State & state)
{ {
state.haveUpdate = false;
if (!state.active) return; if (!state.active) return;
std::string line; std::string line;