Adds a **task** to evaluate. A **task** is jointly a function or 
        callable an iterable with optional arguments and keyworded arguments.
        The iterable can be the result iterator of a previously added **task**
        (to the same or to a different ``NuMap`` instance).

        Arguments:
        
          - func (callable) this will be called on each element of the 
            "iterable" and supplied with arguments "args" and keyworded 
            arguments "kwargs"
          - iterable (iterable) this must be a sequence of *picklable* objects 
            which will be the first arguments passed to the "func"
          - args (``tuple``) [default: ``None``] A ``tuple`` of optional 
            constant arguments passed to the callable "func" after the first
            argument from the "iterable"
          - kwargs (``dict``) [default: ``None``] A dictionary of keyworded 
            arguments passed to "func" after the variable argument from the 
            "iterable" and the arguments from "args"
          - timeout (``bool``) see: ``_NuMapTask``
          - block (``bool``) see: ``_NuMapTask``
          - track (``bool``) [default: ``False``] If ``True`` the results 
            (or exceptions) of a **task** are saved within:
            ``self._tasks_tracked[%task_id%]`` as a ``{index:result}`` 
            dictionary. This is only useful if the callable "func" creates 
            persistant data. The dictionary can be used to restore the correct 
            order of the data

def add_task(self, func, iterable, args=None, kwargs=None, timeout=None, \
                block=True, track=False):
        """ 
        Adds a **task** to evaluate. A **task** is jointly a function or 
        callable an iterable with optional arguments and keyworded arguments.
        The iterable can be the result iterator of a previously added **task**
        (to the same or to a different ``NuMap`` instance).

        Arguments:
        
          - func (callable) this will be called on each element of the 
            "iterable" and supplied with arguments "args" and keyworded 
            arguments "kwargs"
          - iterable (iterable) this must be a sequence of *picklable* objects 
            which will be the first arguments passed to the "func"
          - args (``tuple``) [default: ``None``] A ``tuple`` of optional 
            constant arguments passed to the callable "func" after the first
            argument from the "iterable"
          - kwargs (``dict``) [default: ``None``] A dictionary of keyworded 
            arguments passed to "func" after the variable argument from the 
            "iterable" and the arguments from "args"
          - timeout (``bool``) see: ``_NuMapTask``
          - block (``bool``) see: ``_NuMapTask``
          - track (``bool``) [default: ``False``] If ``True`` the results 
            (or exceptions) of a **task** are saved within:
            ``self._tasks_tracked[%task_id%]`` as a ``{index:result}`` 
            dictionary. This is only useful if the callable "func" creates 
            persistant data. The dictionary can be used to restore the correct 
            order of the data
            
        """
        if not self._started.isSet():
            task = izip(repeat(len(self._tasks)), repeat(func), \
                        repeat((args or ())), repeat((kwargs or {})), \
                        enumerate(iterable))
            task_id = len(self._tasks)
            self._tasks.append(task)
            if track:
                self._tasks_tracked[task_id] = {} # result:index
            self._next_available[task_id] = Queue()
            self._next_skipped[task_id] = 0
            self._task_finished[task_id] = Event()
            self._task_next_lock[task_id] = tLock()
            # this locks threads not processes
            self._task_results[task_id] = _PriorityQueue() if self.ordered \
                                                          else Queue()
            return self.get_task(task=task_id, timeout=timeout, block=block)
        else:
            log.error('%s cannot add tasks (is started).' % self)
            raise RuntimeError('%s cannot add tasks (is started).' % self)