// D import file generated from 'src/core/sync/rwmutex.d'
module core.sync.rwmutex;
public import core.sync.exception;
import core.sync.condition;
import core.sync.mutex;
import core.memory;
version (Posix)
{
	import core.sys.posix.pthread;
}
class ReadWriteMutex
{
	enum Policy
	{
		PREFER_READERS,
		PREFER_WRITERS,
	}
	nothrow @safe this(Policy policy = Policy.PREFER_WRITERS)
	{
		m_commonMutex = new Mutex;
		if (!m_commonMutex)
			throw new SyncError("Unable to initialize mutex");
		m_readerQueue = new Condition(m_commonMutex);
		if (!m_readerQueue)
			throw new SyncError("Unable to initialize mutex");
		m_writerQueue = new Condition(m_commonMutex);
		if (!m_writerQueue)
			throw new SyncError("Unable to initialize mutex");
		m_policy = policy;
		m_reader = new Reader;
		m_writer = new Writer;
	}
	shared nothrow @safe this(Policy policy = Policy.PREFER_WRITERS)
	{
		m_commonMutex = new shared(Mutex);
		if (!m_commonMutex)
			throw new SyncError("Unable to initialize mutex");
		m_readerQueue = new shared(Condition)(m_commonMutex);
		if (!m_readerQueue)
			throw new SyncError("Unable to initialize mutex");
		m_writerQueue = new shared(Condition)(m_commonMutex);
		if (!m_writerQueue)
			throw new SyncError("Unable to initialize mutex");
		m_policy = policy;
		m_reader = new shared(Reader);
		m_writer = new shared(Writer);
	}
	nothrow @property @safe Policy policy();
	shared nothrow @property @safe Policy policy();
	nothrow @property @safe Reader reader();
	shared nothrow @property @safe shared(Reader) reader();
	nothrow @property @safe Writer writer();
	shared nothrow @property @safe shared(Writer) writer();
	class Reader : Object.Monitor
	{
		nothrow @trusted this(this Q)() if (is(Q == Reader) || is(Q == shared(Reader)))
		{
			m_proxy.link = this;
			this.__monitor = cast(void*)&m_proxy;
		}
		@trusted void lock();
		shared @trusted void lock();
		@trusted void unlock();
		shared @trusted void unlock();
		@trusted bool tryLock();
		shared @trusted bool tryLock();
		@trusted bool tryLock(Duration timeout);
		shared @trusted bool tryLock(Duration timeout);
		private
		{
			nothrow @nogc @property @safe bool shouldQueueReader(this Q)() if (is(Q == Reader) || is(Q == shared(Reader)))
			{
				if (m_numActiveWriters > 0)
					return true;
				switch (m_policy)
				{
					case Policy.PREFER_WRITERS:
					{
						return m_numQueuedWriters > 0;
					}
					case Policy.PREFER_READERS:
					{
					}
					default:
					{
						break;
					}
				}
				return false;
			}
			struct MonitorProxy
			{
				Object.Monitor link;
			}
			MonitorProxy m_proxy;
		}
	}
	class Writer : Object.Monitor
	{
		nothrow @trusted this(this Q)() if (is(Q == Writer) || is(Q == shared(Writer)))
		{
			m_proxy.link = this;
			this.__monitor = cast(void*)&m_proxy;
		}
		@trusted void lock();
		shared @trusted void lock();
		@trusted void unlock();
		shared @trusted void unlock();
		@trusted bool tryLock();
		shared @trusted bool tryLock();
		@trusted bool tryLock(Duration timeout);
		shared @trusted bool tryLock(Duration timeout);
		private
		{
			@property bool shouldQueueWriter(this Q)() if (is(Q == Writer) || is(Q == shared(Writer)))
			{
				if (m_numActiveWriters > 0 || m_numActiveReaders > 0)
					return true;
				switch (m_policy)
				{
					case Policy.PREFER_READERS:
					{
						return m_numQueuedReaders > 0;
					}
					case Policy.PREFER_WRITERS:
					{
					}
					default:
					{
						break;
					}
				}
				return false;
			}
			struct MonitorProxy
			{
				Object.Monitor link;
			}
			MonitorProxy m_proxy;
		}
	}
	private
	{
		Policy m_policy;
		Reader m_reader;
		Writer m_writer;
		Mutex m_commonMutex;
		Condition m_readerQueue;
		Condition m_writerQueue;
		int m_numQueuedReaders;
		int m_numActiveReaders;
		int m_numQueuedWriters;
		int m_numActiveWriters;
	}
}
