So, you can't really have threads join themselves (in any language). It's kind of complicated to sync them and a thread joining itself will almost always fail or lead to strange bugs. The better way is for the main thread to handle this. In C++ you can use atomics (like a bool that is synced between all threads). The atomic can be set in a thread, and you are guaranteed all reads and writes are correct. This could be a boolean, like job_is_done, or it could be an atomic counter, jobs_done, and then you can trigger the completion when all jobs are done. Or you can have the thread complete on it's own (for example if it loops a certain number of times and finishes) then it should automatically sync with the main thread if you join them at some point in the future. If the process does not have a clear end, then you can have the main thread check a variable (ideally an atomic, but you might be able to get around it depending on how many threads you have) and then the main thread will join the child threads. But in your case I don't think your method is the worst. The only issue is if calls to the main thread are not safe, you may not be able to guarantee the order or avoid interlacing. It's hard to say for sure without doing more research.