123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- let isLooping = false;
- function getMapKeys(map) {
- return Array.from(map).map((it) => it[0]);
- }
- function workLoop() {
- isLooping = true;
- const prioritys = getMapKeys(Thread.threadMap).sort((a, b) => b - a);
- const curPriority = prioritys[0];
- const curPriorityArray = Thread.threadMap.get(curPriority);
- curPriorityArray.forEach((thread) => {
- thread.samePriorityLength = curPriorityArray.length;
- let taskUnit = thread.taskUnit;
- thread.start();
- while (taskUnit && !thread.shouldYield && !thread.isEmpty) {
- taskUnit = thread.taskUnit = thread.exec();
- }
- if (taskUnit === undefined) {
- thread.destroy();
- }
- else {
- thread.pause();
- }
- thread.pause();
- });
- if (Thread.isAllEmpty()) {
- isLooping = false;
- }
- else {
- nextTick(workLoop);
- }
- }
- let channel;
- function nextTick(callback) {
- if (window.MessageChannel) {
- if (!channel) {
- channel = new MessageChannel();
- channel.port1.onmessage = callback;
- }
- channel.port2.postMessage("notify");
- }
- else {
- setTimeout(callback, 0);
- }
- }
- class Thread {
- static create(runner, taskUnit = undefined, options) {
- const thread = new Thread(runner, taskUnit, options);
- Thread.threads.push(thread);
- const newThreadPriority = thread.options.priority;
- const curPriorityArray = Thread.threadMap.get(newThreadPriority);
- if (curPriorityArray) {
- curPriorityArray.push(thread);
- }
- else {
- Thread.threadMap.set(newThreadPriority, [thread]);
- }
- return thread;
- }
- static isAllEmpty() {
- return !Thread.threads.find((thread) => !thread.isEmpty);
- }
- constructor(runner, taskUnit, options) {
- this.runner = undefined;
- this.taskUnit = undefined;
- this.options = {
- priority: 0,
- };
- this.status = "normal";
- this.samePriorityLength = 0;
- this.startTime = 0;
- this.runner = runner;
- this.taskUnit = taskUnit;
- this.options = Object.assign(this.options, options);
- }
- start() {
- this.startTime = Date.now();
- if (!isLooping) {
- workLoop();
- }
- }
- pause() {
- this.startTime = 0;
- }
- exec() {
- return this.runner(this.taskUnit);
- }
- destroy() {
- Thread.threads.splice(Thread.threads.findIndex((it) => it === this), 1);
- const curPriorityArray = Thread.threadMap.get(this.options.priority);
- curPriorityArray.splice(curPriorityArray.findIndex((it) => it === this), 1);
- if (curPriorityArray.length === 0) {
- Thread.threadMap.delete(this.options.priority);
- }
- this.runner = undefined;
- this.options = undefined;
- this.taskUnit = undefined;
- }
- get shouldYield() {
- return Date.now() > this.startTime + this.yieldInterval;
- }
- get isEmpty() {
- return this.taskUnit === undefined;
- }
- get yieldInterval() {
- return Thread.yieldInterval / this.samePriorityLength;
- }
- }
- Thread.threads = [];
- Thread.threadMap = new Map();
- Thread.yieldInterval = 5;
- export { Thread };
|