common taskscheduler: increase thread efficiency.

Revise the logic to avoid potential blocking of the main thread.
Move the clippers job completion to worker-threads to prevent main thread blocks
and enhance maximum parallelization efficiency.
This commit is contained in:
Hermet Park 2023-04-08 12:58:57 +09:00
parent 5112bdb805
commit afea40a947
3 changed files with 31 additions and 23 deletions

View file

@ -150,6 +150,9 @@ struct SwShapeTask : SwTask
//Clip Path //Clip Path
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) { for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
//Guarantee composition targets get ready.
static_cast<SwShapeTask*>(*clip)->done(tid);
auto clipper = &static_cast<SwShapeTask*>(*clip)->shape; auto clipper = &static_cast<SwShapeTask*>(*clip)->shape;
//Clip shape rle //Clip shape rle
if (shape.rle) { if (shape.rle) {
@ -202,6 +205,9 @@ struct SwImageTask : SwTask
if (!imageGenRle(&image, bbox, false)) goto end; if (!imageGenRle(&image, bbox, false)) goto end;
if (image.rle) { if (image.rle) {
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) { for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
//Guarantee composition targets get ready.
static_cast<SwShapeTask*>(*clip)->done(tid);
auto clipper = &static_cast<SwShapeTask*>(*clip)->shape; auto clipper = &static_cast<SwShapeTask*>(*clip)->shape;
if (clipper->fastTrack) rleClipRect(image.rle, &clipper->bbox); if (clipper->fastTrack) rleClipRect(image.rle, &clipper->bbox);
else if (clipper->rle) rleClipPath(image.rle, clipper->rle); else if (clipper->rle) rleClipPath(image.rle, clipper->rle);
@ -590,13 +596,7 @@ void* SwRenderer::prepareCommon(SwTask* task, const RenderTransform* transform,
//Finish previous task if it has duplicated request. //Finish previous task if it has duplicated request.
task->done(); task->done();
if (clips.count > 0) { if (clips.count > 0) task->clips = clips;
//Guarantee composition targets get ready.
for (auto clip = clips.data; clip < (clips.data + clips.count); ++clip) {
static_cast<SwShapeTask*>(*clip)->done();
}
task->clips = clips;
}
if (transform) { if (transform) {
if (!task->transform) task->transform = static_cast<Matrix*>(malloc(sizeof(Matrix))); if (!task->transform) task->transform = static_cast<Matrix*>(malloc(sizeof(Matrix)));

View file

@ -100,13 +100,12 @@ struct TaskQueue {
}; };
class TaskSchedulerImpl struct TaskSchedulerImpl
{ {
public: uint32_t threadCnt;
unsigned threadCnt;
vector<thread> threads; vector<thread> threads;
vector<TaskQueue> taskQueues; vector<TaskQueue> taskQueues;
atomic<unsigned> idx{0}; uint32_t idx = 0;
TaskSchedulerImpl(unsigned threadCnt) : threadCnt(threadCnt), taskQueues(threadCnt) TaskSchedulerImpl(unsigned threadCnt) : threadCnt(threadCnt), taskQueues(threadCnt)
{ {

View file

@ -44,20 +44,25 @@ struct Task
{ {
private: private:
mutex mtx; mutex mtx;
condition_variable cv; bool finished = true;
bool ready{true}; bool running = false;
bool pending{false};
public: public:
virtual ~Task() = default; virtual ~Task() = default;
void done() void done(unsigned tid = 0)
{ {
if (!pending) return; if (finished) return;
unique_lock<mutex> lock(mtx); unique_lock<mutex> lock(mtx);
while (!ready) cv.wait(lock);
pending = false; if (finished) return;
//the job hasn't been launched yet.
running = true;
run(tid);
running = false;
finished = true;
} }
protected: protected:
@ -66,17 +71,21 @@ protected:
private: private:
void operator()(unsigned tid) void operator()(unsigned tid)
{ {
run(tid); if (finished || running) return;
lock_guard<mutex> lock(mtx); lock_guard<mutex> lock(mtx);
ready = true;
cv.notify_one(); if (finished || running) return;
running = true;
run(tid);
running = false;
finished = true;
} }
void prepare() void prepare()
{ {
ready = false; finished = false;
pending = true;
} }
friend class TaskSchedulerImpl; friend class TaskSchedulerImpl;