work with PIThreadPoolWorker
This commit is contained in:
@@ -42,23 +42,19 @@ PIThreadPoolWorker::PIThreadPoolWorker(int threads_count) {
|
||||
|
||||
|
||||
PIThreadPoolWorker::~PIThreadPoolWorker() {
|
||||
stop();
|
||||
for (auto * w: workers) {
|
||||
if (!w->thread.waitForFinish(1_s)) w->thread.terminate();
|
||||
}
|
||||
piDeleteAllAndClear(workers);
|
||||
}
|
||||
|
||||
|
||||
void PIThreadPoolWorker::start() {
|
||||
for (auto w: workers)
|
||||
for (auto w: workers) {
|
||||
w->thread.start();
|
||||
m_running = true;
|
||||
w->notifier.notify();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PIThreadPoolWorker::stop() {
|
||||
m_running = false;
|
||||
for (auto w: workers) {
|
||||
w->thread.stop();
|
||||
w->notifier.notify();
|
||||
@@ -102,13 +98,87 @@ bool PIThreadPoolWorker::waitForFinish(PISystemTime timeout) {
|
||||
}
|
||||
|
||||
|
||||
bool PIThreadPoolWorker::isRunning() const {
|
||||
return workers.every([](Worker * w) { return w->thread.isRunning(); });
|
||||
}
|
||||
|
||||
|
||||
bool PIThreadPoolWorker::waitForTasks(PISystemTime timeout) {
|
||||
if (!isRunning()) return tasks_queue.getRef()->isEmpty();
|
||||
auto checkWorking = [this] {
|
||||
if (tasks_queue.getRef()->isNotEmpty()) return true;
|
||||
for (auto * w: workers)
|
||||
if (w->in_work > 0) return true;
|
||||
return false;
|
||||
};
|
||||
if (timeout.isNull()) {
|
||||
for (;;) {
|
||||
if (!checkWorking()) break;
|
||||
piMinSleep();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
PITimeMeasurer tm;
|
||||
while (tm.elapsed() < timeout) {
|
||||
if (!checkWorking()) return true;
|
||||
piMinSleep();
|
||||
}
|
||||
return tm.elapsed() < timeout;
|
||||
}
|
||||
|
||||
|
||||
bool PIThreadPoolWorker::waitForTask(int64_t id, PISystemTime timeout) {
|
||||
if (!isRunning()) return tasks_queue.getRef()->every([id](const Task & t) { return t.id != id; });
|
||||
auto checkWorking = [this, id] {
|
||||
if (tasks_queue.getRef()->any([id](const Task & t) { return t.id == id; })) return true;
|
||||
for (auto * w: workers)
|
||||
if (w->in_work == id) return true;
|
||||
return false;
|
||||
};
|
||||
if (timeout.isNull()) {
|
||||
for (;;) {
|
||||
if (!checkWorking()) break;
|
||||
piMinSleep();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
PITimeMeasurer tm;
|
||||
while (tm.elapsed() < timeout) {
|
||||
if (!checkWorking()) return true;
|
||||
piMinSleep();
|
||||
}
|
||||
return tm.elapsed() < timeout;
|
||||
}
|
||||
|
||||
|
||||
void PIThreadPoolWorker::exec() {
|
||||
start();
|
||||
waitForStart();
|
||||
waitForTasks();
|
||||
stopAndWait();
|
||||
}
|
||||
|
||||
|
||||
int64_t PIThreadPoolWorker::enqueueTask(std::function<void(int64_t)> func, PIObject * context) {
|
||||
if (context) {
|
||||
if (!contexts[context]) {
|
||||
contexts << context;
|
||||
CONNECTL(context, deleted, ([this, context](PIObject *) {
|
||||
contexts.remove(context);
|
||||
auto qref = tasks_queue.getRef();
|
||||
// auto prev_size = qref->size();
|
||||
// piCout << "deleted" << (void *)context << qref->map<void *>([](const Task & t) { return t.context; });
|
||||
qref->removeWhere([context](const Task & t) { return t.context == context; });
|
||||
// piCout << prev_size << qref->size() << qref->map<void *>([](const Task & t) { return t.context; });
|
||||
}));
|
||||
}
|
||||
}
|
||||
int64_t id = ++next_task_id;
|
||||
Task task;
|
||||
task.id = id;
|
||||
task.func = std::move(func);
|
||||
task.context = context;
|
||||
tasks_queue.getRef()->append(std::move(task));
|
||||
tasks_queue.getRef()->enqueue(std::move(task));
|
||||
for (auto * w: workers)
|
||||
w->notifier.notify();
|
||||
return id;
|
||||
@@ -142,7 +212,6 @@ PIThreadPoolWorker::TaskStatus PIThreadPoolWorker::taskStatus(int64_t id) const
|
||||
void PIThreadPoolWorker::threadFunc(Worker * w) {
|
||||
w->notifier.wait();
|
||||
if (w->thread.isStopping()) return;
|
||||
if (!m_running) return;
|
||||
Task task;
|
||||
{
|
||||
auto ref = tasks_queue.getRef();
|
||||
@@ -151,7 +220,9 @@ void PIThreadPoolWorker::threadFunc(Worker * w) {
|
||||
}
|
||||
if (!task.isValid()) return;
|
||||
w->in_work = task.id;
|
||||
taskStarted(task.id);
|
||||
task.func(task.id);
|
||||
w->in_work = -1;
|
||||
taskFinished(task.id);
|
||||
w->notifier.notify();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user