{"size": 1753, "ext": "js", "max_stars_repo_path": "lib/slots.js", "max_stars_repo_name": "neffets/converjon", "max_stars_repo_stars_event_min_datetime": "2015-01-30T08:06:15.000Z", "max_stars_repo_stars_event_max_datetime": "2020-09-04T02:34:40.000Z", "max_issues_repo_path": "lib/slots.js", "max_issues_repo_name": "neffets/converjon", "max_issues_repo_issues_event_min_datetime": "2015-01-05T13:41:43.000Z", "max_issues_repo_issues_event_max_datetime": "2019-03-25T12:36:04.000Z", "max_forks_repo_path": "lib/slots.js", "max_forks_repo_name": "neffets/converjon", "max_forks_repo_forks_event_min_datetime": "2015-05-06T08:04:36.000Z", "max_forks_repo_forks_event_max_datetime": "2018-06-13T12:53:05.000Z"}
{"max_stars_count": 38, "max_issues_count": 72, "max_forks_count": 10, "avg_line_length": 23.3733333333, "max_line_length": 71, "alphanum_fraction": 0.4945807188}
/* jshint globalstrict: true */
/* global require */
/* global module */
"use strict";

var Promise = require("rsvp").Promise;

/**
 * Returns a function that returns Promises
 * which represent one worker slot from a limited pool of slots.
 *
 * The Promise resolves into a function that MUST be called after
 * using the slot to free it up again.
 *
 * Usage:
 *   var slots = require("./slots)(10); //make a pool of 10 slots
 *
 *   var s1 = slots(); //request a new slot
 *
 *   s1.then(function(free) {
 *      //do your work here
 *
 *      free(); //call "free" to return the slot into the pool
 *   });
 *
 * @param {number} An integer, defining the number of available slots
 * @returns {function} A function that requests one new slot
 */
module.exports = function(limit) {
    limit = +limit || 10;

    var waiting = [];

    var available = limit;

    function free() {
        if (available < limit) {
            available = available + 1;
        }

        tick();
    }

    function tick() {
        if (waiting.length > 0) {
            if (available > 0) {
                available = available - 1;

                waiting.shift()();
            }
        } else {
            // no slots available
        }
    }

    return function() {
        return new Promise(function(resolve, reject) {
            waiting.push(function(){
                /*
                 * ensure that this promise's `free`is only called once
                 */
                var released = false;
                resolve(function() {
                    if (!released) {
                        released = true;
                        free();
                    }
                });
            });

            tick();
        });
    };
};
