mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +00:00
renderer/scheduler: --binary size by 2.2kb
replace the stl with own lightweight data structures.
This commit is contained in:
parent
6f19c581e8
commit
79facf3656
2 changed files with 32 additions and 28 deletions
|
@ -20,11 +20,11 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <deque>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include "tvgArray.h"
|
||||
#include "tvgInlist.h"
|
||||
#include "tvgTaskScheduler.h"
|
||||
|
||||
/************************************************************************/
|
||||
|
@ -34,7 +34,7 @@
|
|||
namespace tvg {
|
||||
|
||||
struct TaskQueue {
|
||||
deque<Task*> taskDeque;
|
||||
Inlist<Task> taskDeque;
|
||||
mutex mtx;
|
||||
condition_variable ready;
|
||||
bool done = false;
|
||||
|
@ -44,8 +44,6 @@ struct TaskQueue {
|
|||
unique_lock<mutex> lock{mtx, try_to_lock};
|
||||
if (!lock || taskDeque.empty()) return false;
|
||||
*task = taskDeque.front();
|
||||
taskDeque.pop_front();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -54,11 +52,9 @@ struct TaskQueue {
|
|||
{
|
||||
unique_lock<mutex> lock{mtx, try_to_lock};
|
||||
if (!lock) return false;
|
||||
taskDeque.push_back(task);
|
||||
taskDeque.back(task);
|
||||
}
|
||||
|
||||
ready.notify_one();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -82,8 +78,6 @@ struct TaskQueue {
|
|||
if (taskDeque.empty()) return false;
|
||||
|
||||
*task = taskDeque.front();
|
||||
taskDeque.pop_front();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -91,12 +85,10 @@ struct TaskQueue {
|
|||
{
|
||||
{
|
||||
unique_lock<mutex> lock{mtx};
|
||||
taskDeque.push_back(task);
|
||||
taskDeque.back(task);
|
||||
}
|
||||
|
||||
ready.notify_one();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -105,24 +97,33 @@ static thread_local bool _async = true; //toggle async tasking for each thread
|
|||
|
||||
struct TaskSchedulerImpl
|
||||
{
|
||||
uint32_t threadCnt;
|
||||
vector<thread> threads;
|
||||
vector<TaskQueue> taskQueues;
|
||||
Array<thread*> threads;
|
||||
Array<TaskQueue*> taskQueues;
|
||||
atomic<uint32_t> idx{0};
|
||||
|
||||
TaskSchedulerImpl(unsigned threadCnt) : threadCnt(threadCnt), taskQueues(threadCnt)
|
||||
TaskSchedulerImpl(unsigned threadCnt)
|
||||
{
|
||||
threads.reserve(threadCnt);
|
||||
taskQueues.reserve(threadCnt);
|
||||
|
||||
for (unsigned i = 0; i < threadCnt; ++i) {
|
||||
threads.emplace_back([&, i] { run(i); });
|
||||
taskQueues.push(new TaskQueue);
|
||||
threads.push(new thread([&, i] { run(i); }));
|
||||
}
|
||||
}
|
||||
|
||||
~TaskSchedulerImpl()
|
||||
{
|
||||
for (auto& queue : taskQueues) queue.complete();
|
||||
for (auto& thread : threads) thread.join();
|
||||
for (auto tq = taskQueues.data; tq < taskQueues.end(); ++tq) {
|
||||
(*tq)->complete();
|
||||
}
|
||||
for (auto thread = threads.data; thread < threads.end(); ++thread) {
|
||||
(*thread)->join();
|
||||
delete(*thread);
|
||||
}
|
||||
for (auto tq = taskQueues.data; tq < taskQueues.end(); ++tq) {
|
||||
delete(*tq);
|
||||
}
|
||||
}
|
||||
|
||||
void run(unsigned i)
|
||||
|
@ -132,14 +133,14 @@ struct TaskSchedulerImpl
|
|||
//Thread Loop
|
||||
while (true) {
|
||||
auto success = false;
|
||||
for (unsigned x = 0; x < threadCnt * 2; ++x) {
|
||||
if (taskQueues[(i + x) % threadCnt].tryPop(&task)) {
|
||||
for (unsigned x = 0; x < threads.count * 2; ++x) {
|
||||
if (taskQueues[(i + x) % threads.count]->tryPop(&task)) {
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success && !taskQueues[i].pop(&task)) break;
|
||||
if (!success && !taskQueues[i]->pop(&task)) break;
|
||||
(*task)(i + 1);
|
||||
}
|
||||
}
|
||||
|
@ -147,13 +148,13 @@ struct TaskSchedulerImpl
|
|||
void request(Task* task)
|
||||
{
|
||||
//Async
|
||||
if (threadCnt > 0 && _async) {
|
||||
if (threads.count > 0 && _async) {
|
||||
task->prepare();
|
||||
auto i = idx++;
|
||||
for (unsigned n = 0; n < threadCnt; ++n) {
|
||||
if (taskQueues[(i + n) % threadCnt].tryPush(task)) return;
|
||||
for (unsigned n = 0; n < threads.count; ++n) {
|
||||
if (taskQueues[(i + n) % threads.count]->tryPush(task)) return;
|
||||
}
|
||||
taskQueues[i % threadCnt].push(task);
|
||||
taskQueues[i % threads.count]->push(task);
|
||||
//Sync
|
||||
} else {
|
||||
task->run(0);
|
||||
|
@ -192,7 +193,7 @@ void TaskScheduler::request(Task* task)
|
|||
|
||||
unsigned TaskScheduler::threads()
|
||||
{
|
||||
if (inst) return inst->threadCnt;
|
||||
if (inst) return inst->threads.count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include "tvgCommon.h"
|
||||
#include "tvgInlist.h"
|
||||
|
||||
namespace tvg
|
||||
{
|
||||
|
@ -50,6 +51,8 @@ private:
|
|||
bool pending = false;
|
||||
|
||||
public:
|
||||
INLIST_ITEM(Task);
|
||||
|
||||
virtual ~Task() = default;
|
||||
|
||||
void done()
|
||||
|
|
Loading…
Add table
Reference in a new issue