'Distribute test cases across workers.
Return an identifier of each test case with its result in order to use
imap_unordered to show results as soon as they\'re available.
To minimize pickling errors when getting results from workers:
- pass back numeric indexes in self.subsuites instead of tests
- make tracebacks picklable with tblib, if available
Even with tblib, errors may still occur for dynamically created
exception classes such Model.DoesNotExist which cannot be unpickled.'

def run(self, result):

    counter = multiprocessing.Value(ctypes.c_int, 0)
    pool = multiprocessing.Pool(processes=self.processes, initializer=self.init_worker.__func__, initargs=[counter])
    args = [(self.runner_class, index, subsuite, self.failfast) for (index, subsuite) in enumerate(self.subsuites)]
    test_results = pool.imap_unordered(self.run_subsuite.__func__, args)
    while True:
        if result.shouldStop:
            pool.terminate()
            break
        try:
            (subsuite_index, events) = test_results.next(timeout=0.1)
        except multiprocessing.TimeoutError:
            continue
        except StopIteration:
            pool.close()
            break
        tests = list(self.subsuites[subsuite_index])
        for event in events:
            event_name = event[0]
            handler = getattr(result, event_name, None)
            if (handler is None):
                continue
            test = tests[event[1]]
            args = event[2:]
            handler(test, *args)
    pool.join()
    return result
