Create the WorkUnit objects to process and pushes them on the
        work queue. Each work unit is meant to process a slice of
        iterable of size chunksize. If collector is specified, then
        the ApplyResult objects associated with the jobs will notify
        collector when their result becomes ready.

        \return the list of WorkUnit objects (basically: JobSequences)
        pushed onto the work queue

def _create_sequences(self, func, iterable, chunksize, collector=None):
        """
        Create the WorkUnit objects to process and pushes them on the
        work queue. Each work unit is meant to process a slice of
        iterable of size chunksize. If collector is specified, then
        the ApplyResult objects associated with the jobs will notify
        collector when their result becomes ready.

        \return the list of WorkUnit objects (basically: JobSequences)
        pushed onto the work queue
        """
        assert not self._closed  # No lock here. We assume it's atomic...
        sequences = []
        results = []
        it_ = iter(iterable)
        exit_loop = False
        while not exit_loop:
            seq = []
            for _ in range(chunksize or 1):
                try:
                    arg = next(it_)
                except StopIteration:
                    exit_loop = True
                    break
                apply_result = ApplyResult(collector)
                job = Job(func, (arg,), {}, apply_result)
                seq.append(job)
                results.append(apply_result)
            sequences.append(JobSequence(seq))

        for seq in sequences:
            self._workq.put(seq)

        return sequences