rewrite parallel run-tests

- use libdispatch instead of NSOperationQueues
- restructure the code such that everything runs in 1 queue
- use a semaphore to limit the number of concurrent processes