diff --git a/src/lib/tvgTaskScheduler.cpp b/src/lib/tvgTaskScheduler.cpp index fcbcf207..01946808 100644 --- a/src/lib/tvgTaskScheduler.cpp +++ b/src/lib/tvgTaskScheduler.cpp @@ -105,7 +105,7 @@ struct TaskSchedulerImpl uint32_t threadCnt; vector threads; vector taskQueues; - uint32_t idx = 0; + atomic idx{0}; TaskSchedulerImpl(unsigned threadCnt) : threadCnt(threadCnt), taskQueues(threadCnt) { diff --git a/src/lib/tvgTaskScheduler.h b/src/lib/tvgTaskScheduler.h index 36c494c9..cad88751 100644 --- a/src/lib/tvgTaskScheduler.h +++ b/src/lib/tvgTaskScheduler.h @@ -43,56 +43,83 @@ struct TaskScheduler struct Task { private: - mutex mtx; - bool finished = true; - bool running = false; + mutex finishedMtx; + mutex preparedMtx; + condition_variable cv; + bool finished = true; //if run() finished + bool prepared = false; //the task is requested public: - virtual ~Task() = default; + virtual ~Task() + { + if (!prepared) return; + + //Guarantee the task is finished by TaskScheduler. + unique_lock lock(preparedMtx); + + while (prepared) { + cv.wait(lock); + } + } void done(unsigned tid = 0) { if (finished) return; - unique_lock lock(mtx); + lock_guard lock(finishedMtx); if (finished) return; //the job hasn't been launched yet. - running = true; - run(tid); - running = false; + + //set finished so that operator() quickly returns. finished = true; + + run(tid); } protected: virtual void run(unsigned tid) = 0; private: + void finish() + { + lock_guard lock(preparedMtx); + prepared = false; + cv.notify_one(); + } + void operator()(unsigned tid) { - if (finished || running) return; + if (finished) { + finish(); + return; + } - lock_guard lock(mtx); + lock_guard lock(finishedMtx); - if (finished || running) return; + if (finished) { + finish(); + return; + } - running = true; run(tid); - running = false; + finished = true; + + finish(); } void prepare() { finished = false; + prepared = true; } friend struct TaskSchedulerImpl; }; - - } #endif //_TVG_TASK_SCHEDULER_H_ + \ No newline at end of file