queue, stack을 concurrecy환경에서 안전하게 읽고/쓰고를 해보자.
Stack 구현
#pragma once
#include <mutex>
template<typename T>
class LockStack
{
public:
	LockStack() { }
	LockStack(const LockStack&) = delete;
	LockStack& operator=(const LockStack&) = delete;
	void Push(T value)
	{
		lock_guard<mutex> lock(_mutex);
		_stack.push(std::move(value));
		// (참고) std::move == static_cast<T&&>() 임을 기억하자
		_condVar.notify_one();
	}
	bool TryPop(T& value)
	{
		lock_guard<mutex> lock(_mutex);
		if (_stack.empty())
			return false;
		// empty -> top -> pop
		value = std::move(_stack.top());
		_stack.pop();
		return true;
	}
	void WaitPop(T& value)
	{
		unique_lock<mutex> lock(_mutex);
        // empty 상태를 확인, condition_variable이용
        // Trypop은 무한으로 대기하는 버전이고,
        // WaitPop은 Push되면 동작하는 버전
		_condVar.wait(lock, [this] { return _stack.empty() == false; });
		value = std::move(_stack.top());
		_stack.pop();
	}
private:
	stack<T> _stack;
	mutex _mutex;
	condition_variable _condVar;
};
queue 구현
#pragma once
#include <mutex>
template<typename T>
class LockQueue
{
public:
	LockQueue() { }
	LockQueue(const LockQueue&) = delete;
	LockQueue& operator=(const LockQueue&) = delete;
	void Push(T value)
	{
		lock_guard<mutex> lock(_mutex);
		_queue.push(std::move(value));
		_condVar.notify_one();
	}
	bool TryPop(T& value)
	{
		lock_guard<mutex> lock(_mutex);
		if (_queue.empty())
			return false;
		value = std::move(_queue.front());
		_queue.pop();
		return true;
	}
	void WaitPop(T& value)
	{
		unique_lock<mutex> lock(_mutex);
		_condVar.wait(lock, [this] { return _queue.empty() == false; });
		value = std::move(_queue.front());
		_queue.pop();
	}
private:
	queue<T> _queue;
	mutex _mutex;
	condition_variable _condVar;
};