Semaphore.js 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. /*@flow*/
  2. /*::
  3. export type Saferphore_ReturnAfter_t = ((...any)=>void)=>(...any)=>void;
  4. export type Saferphore_t = {
  5. take: ((Saferphore_ReturnAfter_t)=>void)=>void,
  6. };
  7. */
  8. ;(function () {
  9. "use strict";
  10. var create = function (resourceCount /*:number*/) /*:Saferphore_t*/ {
  11. var queue = [];
  12. var check;
  13. var mkRa = function () /*:Saferphore_ReturnAfter_t*/ {
  14. var outerCalled = 0;
  15. return function (func) {
  16. if (outerCalled++) { throw new Error("returnAfter() called multiple times"); }
  17. var called = 0;
  18. return function () {
  19. if (called++) {
  20. throw new Error("returnAfter wrapped callback called multiple times");
  21. }
  22. if (func) { func.apply(null, arguments); }
  23. resourceCount++;
  24. check();
  25. };
  26. };
  27. };
  28. check = function () {
  29. if (resourceCount < 0) { throw new Error("(resourceCount < 0) should never happen"); }
  30. if (resourceCount === 0 || queue.length === 0) { return; }
  31. resourceCount--;
  32. queue.shift()(mkRa());
  33. };
  34. return {
  35. take: function (func) {
  36. queue.push(func);
  37. check();
  38. }
  39. };
  40. };
  41. if (typeof(window) === 'object') {
  42. if (window.define && window.define.amd) {
  43. window.define({ create: create });
  44. } else {
  45. window.Saferphore = { create: create };
  46. }
  47. } else if (typeof(module) === 'object' && module.exports) {
  48. module.exports.create = create;
  49. }
  50. }());