whole_func_string: function Series(asyncFncWrapper) {
      asyncFncWrapper = getAsyncFncWrapper(asyncFncWrapper);
      
      this.add = function() {       
          var fnc, args;
          if(arguments.length===1) {
              fnc=arguments[0];
          }
          else if(arguments.length > 1) {
              fnc=arguments[arguments.length - 1];
              args = [];
              for(var i=0;i<arguments.length-1;i++){
                  args.push(arguments[i]);
              }
          }
          
          if(typeof fnc!=='function')
              throw new Error('Async Series: Last argument have to be function(arg1, arg2, ..., next).');
          
          this._fncQueue = this._fncQueue || [];
          this._fncQueue.push({ args:args, fnc:fnc });
          
          this.execute = function(finalFnc){
              var fncQueue = this._fncQueue;
              fncQueue.current = 0;
              fncQueue.scheduled = 0;
              
              function run(itm) {
                  asyncFncWrapper(function(){
                      fncQueue.scheduled = fncQueue.current;
                      
                      if(itm.args) {
                          itm.args.push(next);
                          itm.fnc.apply(itm, itm.args);
                      }
                      else itm.fnc(next);
                  });
              }
              
              function next(){
                  if(!fncQueue || fncQueue.scheduled !== fncQueue.current)
                      throw new Error('Async Series: cannot execute next() more than once per function');
                  
                  // if(arguments.length > 0) {
                  if(arguments.length > 0 && (arguments[0] !== null && typeof arguments[0] !== 'undefined')) {
                      var args = Array.prototype.slice.call(arguments);
                      fncQueue = null;
                      if(typeof finalFnc==='function')
                          asyncFncWrapper(function(){ finalFnc.apply(this, args); });
                  }
                  else if(fncQueue.current + 1 < fncQueue.length) {
                      fncQueue.current+=1;
                      run(fncQueue[fncQueue.current]);
                  }
                  else {
                      fncQueue = null;
                      if(typeof finalFnc==='function')
                          asyncFncWrapper(finalFnc);
                  }
              }
              
              if(fncQueue && fncQueue.length>0)
                  run(fncQueue[fncQueue.current]);
          };
          return this;
      };
      
      this.execute = function(fnc){ if(typeof fnc==='function') asyncFncWrapper(fnc); };
  }
func_code_string: function Series(asyncFncWrapper) {
      asyncFncWrapper = getAsyncFncWrapper(asyncFncWrapper);
      
      this.add = function() {       
          var fnc, args;
          if(arguments.length===1) {
              fnc=arguments[0];
          }
          else if(arguments.length > 1) {
              fnc=arguments[arguments.length - 1];
              args = [];
              for(var i=0;i<arguments.length-1;i++){
                  args.push(arguments[i]);
              }
          }
          
          if(typeof fnc!=='function')
              throw new Error('Async Series: Last argument have to be function(arg1, arg2, ..., next).');
          
          this._fncQueue = this._fncQueue || [];
          this._fncQueue.push({ args:args, fnc:fnc });
          
          this.execute = function(finalFnc){
              var fncQueue = this._fncQueue;
              fncQueue.current = 0;
              fncQueue.scheduled = 0;
              
              function run(itm) {
                  asyncFncWrapper(function(){
                      fncQueue.scheduled = fncQueue.current;
                      
                      if(itm.args) {
                          itm.args.push(next);
                          itm.fnc.apply(itm, itm.args);
                      }
                      else itm.fnc(next);
                  });
              }
              
              function next(){
                  if(!fncQueue || fncQueue.scheduled !== fncQueue.current)
                      throw new Error('Async Series: cannot execute next() more than once per function');
                  
                  // if(arguments.length > 0) {
                  if(arguments.length > 0 && (arguments[0] !== null && typeof arguments[0] !== 'undefined')) {
                      var args = Array.prototype.slice.call(arguments);
                      fncQueue = null;
                      if(typeof finalFnc==='function')
                          asyncFncWrapper(function(){ finalFnc.apply(this, args); });
                  }
                  else if(fncQueue.current + 1 < fncQueue.length) {
                      fncQueue.current+=1;
                      run(fncQueue[fncQueue.current]);
                  }
                  else {
                      fncQueue = null;
                      if(typeof finalFnc==='function')
                          asyncFncWrapper(finalFnc);
                  }
              }
              
              if(fncQueue && fncQueue.length>0)
                  run(fncQueue[fncQueue.current]);
          };
          return this;
      };
      
      this.execute = function(fnc){ if(typeof fnc==='function') asyncFncWrapper(fnc); };
  }
func_documentation_string: async Series queue constructor
  @param {Object} asyncFncWrapper (optional) by default is setImmediate, but can be setTimeout, or any custom function
  @returns {Object}  series queue