<aside> 📗 목차


</aside>

mutex::lock()을 이용한 Stack

<aside> 💡 보라색 부분을 제외하고 Queue와 거의 동일하다

</aside>

#pragma once

#include <mutex>

//! lock 기반의 스택
template<typename T>
class LockStack
{
public:
	LockStack() {};
	~LockStack() {};

	LockStack(const LockStack&) = delete; //! 복사 생성자는 삭제해버린다
	LockStack& operator=(const LockStack&) = delete; //! 대입 연산자도 삭제해버린다 (복사하려고해도, 응 돌아가~)

	//! Push할때 공유 데이터에 접근하니 lock을 걸어준다
	void Push(T value)
	{
		lock_guard<mutex> lock(_mutex);
		_stack.push(move(value));				//~ move를 사용해서 불필요한 복사를 방지한다
		_condVar.notify_one();						//~데이터가 들어왔으니, 대기중인 스레드를 깨워준다
	}

	//! Pop값은 되었는지 안되었는지 확인하기 위해 bool을 반환한다
	//! 100% 확률로 Pop이 안되니까, TryPop이라고 이름을 붙인다
	bool TryPop(T& value)
	{
		lock_guard<mutex> lock(_mutex);
		if (_stack.empty()) return false;

		value = move(_stack.top()); //! 스택 상단에 값을 가져오고
		_stack.pop();						//! 스택에서 상단값을 제거한다	
		return true;
	}

	bool WaitPop(T& value)
	{
		unique_lock<mutex> lock(_mutex); //~ notify_one을 인지하기 위해 unique_lock을 사용함
		_condVar.wait(lock, [this] { return _stack.empty() == false; }); //~ 람다식을 사용해서 스택에 데이터 없으면 있을때까지 대기함 (근데 여기 this 굳이 안적어도 될듯)
		value = move(_stack.top());
		_stack.pop();
		return true;
	}

private:
	stack<T> _stack;
	mutex _mutex;
	condition_variable _condVar;
};

mutex::lock()을 이용한 Queue

<aside> 💡 보라색 부분을 제외하고 Stack과 거의 동일하다

</aside>

#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(move(value));			//~ 불필요한 복사 막기 위해 move로 값 넣어주고
		_condVar.notify_one();					//~ 대기중인 스레드 하나 꺠우기!
	}

	//! Pop값은 되었는지 안되었는지 확인하기 위해 bool을 반환한다
	//! 100% 확률로 Pop이 안되니까, TryPop이라고 이름을 붙인다
	bool TryPop(T& value)
	{
		lock_guard<mutex> lock(_mutex);
		if (_queue.empty()) return false;

		value = move(_queue.front());
		_queue.pop();						
		return true;
	}

	bool WaitPop(T& value)
	{
		unique_lock<mutex> lock(_mutex); //~ notify_one을 인지하기 위해 unique_lock을 사용함
		_condVar.wait(lock, [this] { return _queue.empty() == false; }); //~ 람다식을 사용해서 스택에 데이터 없으면 있을때까지 대기함 (근데 여기 this 굳이 안적어도 될듯)
		value = move(_queue.front());
		_queue.pop();
		return true;
	}

private:
	queue<T> _queue;
	mutex _mutex;
	condition_variable _condVar;
};

class ConcurrentQueue
{
};