instead of waiting until all threads have joined, we are now supplying a callback that will be invoked once all threads have terminated. you can use this callback to free the worker struct