/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.

For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once

#include <utility>

namespace base {

template <typename T>
class thread_safe_wrap {
public:
	template <typename ...Args>
	thread_safe_wrap(Args &&...args) : _value(std::forward<Args>(args)...) {
	}

	template <typename Callback>
	auto with(Callback &&callback) {
		QMutexLocker lock(&_mutex);
		return callback(_value);
	}

	template <typename Callback>
	auto with(Callback &&callback) const {
		QMutexLocker lock(&_mutex);
		return callback(_value);
	}

private:
	T _value;
	QMutex _mutex;

};

template <typename T, template<typename...> typename Container = std::deque>
class thread_safe_queue {
public:
	template <typename ...Args>
	void emplace(Args &&...args) {
		_wrap.with([&](Container<T> &value) {
			value.emplace_back(std::forward<Args>(args)...);
		});
	}

	Container<T> take() {
		return _wrap.with([&](Container<T> &value) {
			return std::exchange(value, Container<T>());
		});
	}

private:
	thread_safe_wrap<Container<T>> _wrap;

};

} // namespace base