Farm.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', {
  3. value: true
  4. });
  5. exports.default = void 0;
  6. var _types = require('./types');
  7. function _defineProperty(obj, key, value) {
  8. if (key in obj) {
  9. Object.defineProperty(obj, key, {
  10. value: value,
  11. enumerable: true,
  12. configurable: true,
  13. writable: true
  14. });
  15. } else {
  16. obj[key] = value;
  17. }
  18. return obj;
  19. }
  20. class Farm {
  21. constructor(numOfWorkers, callback, computeWorkerKey) {
  22. _defineProperty(this, '_computeWorkerKey', void 0);
  23. _defineProperty(this, '_cacheKeys', void 0);
  24. _defineProperty(this, '_callback', void 0);
  25. _defineProperty(this, '_last', void 0);
  26. _defineProperty(this, '_locks', void 0);
  27. _defineProperty(this, '_numOfWorkers', void 0);
  28. _defineProperty(this, '_offset', void 0);
  29. _defineProperty(this, '_queue', void 0);
  30. this._cacheKeys = Object.create(null);
  31. this._callback = callback;
  32. this._last = [];
  33. this._locks = [];
  34. this._numOfWorkers = numOfWorkers;
  35. this._offset = 0;
  36. this._queue = [];
  37. if (computeWorkerKey) {
  38. this._computeWorkerKey = computeWorkerKey;
  39. }
  40. }
  41. doWork(method, ...args) {
  42. return new Promise((resolve, reject) => {
  43. const computeWorkerKey = this._computeWorkerKey;
  44. const request = [_types.CHILD_MESSAGE_CALL, false, method, args];
  45. let worker = null;
  46. let hash = null;
  47. if (computeWorkerKey) {
  48. hash = computeWorkerKey.call(this, method, ...args);
  49. worker = hash == null ? null : this._cacheKeys[hash];
  50. }
  51. const onStart = worker => {
  52. if (hash != null) {
  53. this._cacheKeys[hash] = worker;
  54. }
  55. };
  56. const onEnd = (error, result) => {
  57. if (error) {
  58. reject(error);
  59. } else {
  60. resolve(result);
  61. }
  62. };
  63. const task = {
  64. onEnd,
  65. onStart,
  66. request
  67. };
  68. if (worker) {
  69. this._enqueue(task, worker.getWorkerId());
  70. } else {
  71. this._push(task);
  72. }
  73. });
  74. }
  75. _getNextTask(workerId) {
  76. let queueHead = this._queue[workerId];
  77. while (queueHead && queueHead.task.request[1]) {
  78. queueHead = queueHead.next || null;
  79. }
  80. this._queue[workerId] = queueHead;
  81. return queueHead && queueHead.task;
  82. }
  83. _process(workerId) {
  84. if (this._isLocked(workerId)) {
  85. return this;
  86. }
  87. const task = this._getNextTask(workerId);
  88. if (!task) {
  89. return this;
  90. }
  91. const onEnd = (error, result) => {
  92. task.onEnd(error, result);
  93. this._unlock(workerId);
  94. this._process(workerId);
  95. };
  96. task.request[1] = true;
  97. this._lock(workerId);
  98. this._callback(workerId, task.request, task.onStart, onEnd);
  99. return this;
  100. }
  101. _enqueue(task, workerId) {
  102. const item = {
  103. next: null,
  104. task
  105. };
  106. if (task.request[1]) {
  107. return this;
  108. }
  109. if (this._queue[workerId]) {
  110. this._last[workerId].next = item;
  111. } else {
  112. this._queue[workerId] = item;
  113. }
  114. this._last[workerId] = item;
  115. this._process(workerId);
  116. return this;
  117. }
  118. _push(task) {
  119. for (let i = 0; i < this._numOfWorkers; i++) {
  120. this._enqueue(task, (this._offset + i) % this._numOfWorkers);
  121. }
  122. this._offset++;
  123. return this;
  124. }
  125. _lock(workerId) {
  126. this._locks[workerId] = true;
  127. }
  128. _unlock(workerId) {
  129. this._locks[workerId] = false;
  130. }
  131. _isLocked(workerId) {
  132. return this._locks[workerId];
  133. }
  134. }
  135. exports.default = Farm;