      1 var define = require("../define").define,
      2         Collection = require("./Collection"),
      3         Queue = require("./Queue"),
      4         base = require("../base");
      5
      6 /**
      7  * @class Base class for a pool.
      8  *
      9  * @name Pool
     10  * @memberOf comb.collections
     11  *
     12  * @property {Number} count the total number of objects in the pool, including free and in use objects.
     13  * @property {Number} freeCount the number of free objects in this pool.
     14  * @property {Number} inUseCount the number of objects in use in this pool.
     15  * @property {Number} [minObjects=0] the minimum number of objects this pool should contain.
     16  * @property {Number} [maxObjects=1] the maximum number of objects this pool should contain
     17
     18  */
     19 exports = module.exports = define(null, {
     20     instance : {
     21         /**@lends comb.collections.Pool.prototype*/
     22
     23         __minObjects : 0,
     24
     25         __maxObjects : 1,
     26
     27         constructor : function(options) {
     28             options = options || {};
     29             this.__freeObjects = new Queue();
     30             this.__inUseObjects = [];
     31             this.__minObjects = options.minObjects || 0;
     32             this.__maxObjects = options.maxObjects || 1;
     33             this.minObjects = this.__minObjects;
     34             this.maxObjects = this.__maxObjects;
     35         },
     36
     37         /**
     38          * Retrieves an object from this pool.
     39          * `
     40          * @return {*} an object to contained in this pool
     41          */
     42         getObject : function() {
     43             var ret = undefined;
     44             if (this.freeCount > 0) {
     45                 ret = this.__freeObjects.dequeue();
     46                 this.__inUseObjects.push(ret);
     47             } else if (this.__maxObjects > this.count) {
     48                 ret = this.createObject();
     49                 this.__inUseObjects.push(ret);
     50             }
     51             return ret;
     52         },
     53
     54         /**
     55          * Returns an object to this pool. The object is validated before it is returned to the pool,
     56          * if the validation fails then it is removed from the pool;
     57          * @param {*} obj the object to return to the pool
     58          */
     59         returnObject : function(obj) {
     60             if (this.validate(obj) && this.count <= this.__maxObjects) {
     61                 this.__freeObjects.enqueue(obj);
     62                 var index;
     63                 if ((index = this.__inUseObjects.indexOf(obj)) > -1)
     64                     this.__inUseObjects.splice(index, 1);
     65             } else {
     66                 this.removeObject(obj);
     67             }
     68         },
     69
     70         /**
     71          * Removes an object from the pool, this can be overriden to provide any
     72          * teardown of objects that needs to take place.
     73          *
     74          * @param {*} obj the object that needs to be removed.
     75          *
     76          * @return {*} the object removed.
     77          */
     78         removeObject : function(obj) {
     79             var index;
     80             if (this.__freeObjects.contains(obj)) {
     81                 this.__freeObjects.remove(obj);
     82             } else if ((index = this.__inUseObjects.indexOf(obj)) > -1) {
     83                 this.__inUseObjects.splice(index, 1);
     84             }
     85             //otherwise its not contained in this pool;
     86             return obj;
     87         },
     88
     89         /**
     90          * Validates an object in this pool.
     91          * </br>
     92          * <b>THIS SHOULD BE OVERRIDDEN TO VALIDATE</b>
     93          *
     94          * @param {*} obj the object to validate.
     95          */
     96         validate : function(obj) {
     97             return true;
     98         },
     99
    100         /**
    101          * Creates a new object for this pool.
    102          * * </br>
    103          * <b>THIS SHOULD BE OVERRIDDEN TO ADD THE CORRECT TYPE OF OBJECT</b>
    104          *
    105          * @return {Object} be default just creates an object.
    106          */
    107         createObject : function() {
    108             return {};
    109         },
    110
    111         setters : {
    112             minObjects : function(l) {
    113
    114                 if (l <= this.__maxObjects) {
    115                     this.__minObjects = l;
    116                     var i;
    117                     if ((i = this.count) < l) {
    118                         while (i++ < l) {
    119                             this.__freeObjects.enqueue(this.createObject());
    120                         }
    121                     }
    122                 } else {
    123                     throw "comb.collections.Pool : minObjects cannot be greater than maxObjects.";
    124                 }
    125             },
    126             maxObjects : function(l) {
    127                 if (l >= this.__minObjects) {
    128                     this.__maxObjects = l;
    129                     var i = this.count, j = this.freeCount, fo = this.__freeObjects;
    130                     while (i > l && j >= 0) {
    131                         this.removeObject(fo.dequeue());
    132                         j--;
    133                         i--;
    134                     }
    135                 } else {
    136                     throw "comb.collections.Pool : maxObjects cannot be less than maxObjects.";
    137                 }
    138
    139             }
    140         },
    141
    142         getters : {
    143             freeCount : function() {
    144                 return this.__freeObjects.count;
    145             },
    146             inUseCount : function() {
    147                 return this.__inUseObjects.length;
    148             },
    149             count : function() {
    150                 return  this.__freeObjects.count + this.__inUseObjects.length;
    151
    152             },
    153
    154             minObjects : function() {
    155                 return this.__minObjects;
    156             },
    157             maxObjects : function() {
    158                 return this.__maxObjects;
    159             }
    160         }
    161     }
    162 })