mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-10 14:41:50 +00:00
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:
parent
5112bdb805
commit
afea40a947
3 changed files with 31 additions and 23 deletions
|
@ -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)));
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue