How would you implement a thread-safe queue in C++? Walk through the synchronization primitives you would use and why.