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 })