Umm…I haven’t looked at the ThreadPoolJob code but one solution is to change job identifiers from a small integer into a reference counted object pointer. This way a job persists until the last reference is gone. So after a job is finished or gets signaled to exit, it can be put into a state suitable for inspection (i.e. usable in a call to waitForJobToFinish).
I believe that is the solution used by boost::thread and std::thread.
That method no longer has a deleteInactive argument. Each job now knows whether it should be deleted, so there’s no need to tell it what to do. (God knows why I didn’t write it that way in the first place!)