/*-------------------------------------------------------------------------
 * drawElements C++ Base Library
 * -----------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief Block-based thread-safe queue.
 *//*--------------------------------------------------------------------*/

#include "deBlockBuffer.hpp"
#include "deRandom.hpp"
#include "deThread.hpp"
#include "deInt32.h"
#include "deMemory.h"

#include <vector>

namespace de
{

using std::vector;

namespace BlockBufferBasicTest
{

struct Message
{
	deUint32 data;

	Message (deUint16 threadId, deUint16 payload)
		: data((threadId << 16) | payload)
	{
	}

	Message (void)
		: data(0)
	{
	}

	deUint16 getThreadId	(void) const { return (deUint16)(data >> 16);		}
	deUint16 getPayload		(void) const { return (deUint16)(data & 0xffff);	}
};

typedef BlockBuffer<Message> MessageBuffer;

class Consumer : public Thread
{
public:
	Consumer (MessageBuffer& buffer, int numProducers)
		: m_buffer		(buffer)
	{
		m_lastPayload.resize(numProducers, 0);
		m_payloadSum.resize(numProducers, 0);
	}

	void run (void)
	{
		Random	rnd		((deUint32)m_lastPayload.size());
		Message	tmpBuf	[64];
		bool	consume	= true;

		while (consume)
		{
			int numToRead	= rnd.getInt(1, DE_LENGTH_OF_ARRAY(tmpBuf));
			int numRead		= m_buffer.tryRead(numToRead, &tmpBuf[0]);

			for (int ndx = 0; ndx < numRead; ndx++)
			{
				const Message& msg = tmpBuf[ndx];

				deUint16 threadId = msg.getThreadId();

				if (threadId == 0xffff)
				{
					/* Feed back rest of messages to buffer (they are end messages) so other consumers wake up. */
					if (ndx+1 < numRead)
					{
						m_buffer.write(numRead-ndx-1, &tmpBuf[ndx+1]);
						m_buffer.flush();
					}

					consume = false;
					break;
				}
				else
				{
					/* Verify message. */
					DE_TEST_ASSERT(de::inBounds<int>(threadId, 0, (int)m_lastPayload.size()));
					DE_TEST_ASSERT((m_lastPayload[threadId] == 0 && msg.getPayload() == 0) || m_lastPayload[threadId] < msg.getPayload());

					m_lastPayload[threadId]	 = msg.getPayload();
					m_payloadSum[threadId]	+= (deUint32)msg.getPayload();
				}
			}
		}
	}

	deUint32 getPayloadSum (deUint16 threadId) const
	{
		return m_payloadSum[threadId];
	}

private:
	MessageBuffer&			m_buffer;
	vector<deUint16>		m_lastPayload;
	vector<deUint32>		m_payloadSum;
};

class Producer : public Thread
{
public:
	Producer (MessageBuffer& buffer, deUint16 threadId, int numMessages)
		: m_buffer		(buffer)
		, m_threadId	(threadId)
		, m_numMessages	(numMessages)
	{
	}

	void run (void)
	{
		// Yield to give main thread chance to start other producers.
		deSleep(1);

		Random	rnd		(m_threadId);
		int		msgNdx	= 0;
		Message	tmpBuf[64];

		while (msgNdx < m_numMessages)
		{
			int writeSize = rnd.getInt(1, de::min(m_numMessages-msgNdx, DE_LENGTH_OF_ARRAY(tmpBuf)));
			for (int ndx = 0; ndx < writeSize; ndx++)
				tmpBuf[ndx] = Message(m_threadId, (deUint16)msgNdx++);

			m_buffer.write(writeSize, &tmpBuf[0]);
			if (rnd.getBool())
				m_buffer.flush();
		}
	}

private:
	MessageBuffer&	m_buffer;
	deUint16		m_threadId;
	int				m_numMessages;
};

void runTest (void)
{
	const int numIterations = 8;
	for (int iterNdx = 0; iterNdx < numIterations; iterNdx++)
	{
		Random							rnd				(iterNdx);
		int								numBlocks		= rnd.getInt(2, 128);
		int								blockSize		= rnd.getInt(1, 16);
		int								numProducers	= rnd.getInt(1, 16);
		int								numConsumers	= rnd.getInt(1, 16);
		int								dataSize		= rnd.getInt(50, 200);
		MessageBuffer					buffer			(blockSize, numBlocks);
		vector<Producer*>				producers;
		vector<Consumer*>				consumers;

		for (int i = 0; i < numProducers; i++)
			producers.push_back(new Producer(buffer, (deUint16)i, dataSize));

		for (int i = 0; i < numConsumers; i++)
			consumers.push_back(new Consumer(buffer, numProducers));

		// Start consumers.
		for (vector<Consumer*>::iterator i = consumers.begin(); i != consumers.end(); i++)
			(*i)->start();

		// Start producers.
		for (vector<Producer*>::iterator i = producers.begin(); i != producers.end(); i++)
			(*i)->start();

		// Wait for producers.
		for (vector<Producer*>::iterator i = producers.begin(); i != producers.end(); i++)
			(*i)->join();

		// Write end messages for consumers.
		const Message endMsg(0xffff, 0);
		for (int i = 0; i < numConsumers; i++)
			buffer.write(1, &endMsg);
		buffer.flush();

		// Wait for consumers.
		for (vector<Consumer*>::iterator i = consumers.begin(); i != consumers.end(); i++)
			(*i)->join();

		// Verify payload sums.
		deUint32 refSum = 0;
		for (int i = 0; i < dataSize; i++)
			refSum += (deUint32)(deUint16)i;

		for (int i = 0; i < numProducers; i++)
		{
			deUint32 cmpSum = 0;
			for (int j = 0; j < numConsumers; j++)
				cmpSum += consumers[j]->getPayloadSum((deUint16)i);
			DE_TEST_ASSERT(refSum == cmpSum);
		}

		// Free resources.
		for (vector<Producer*>::iterator i = producers.begin(); i != producers.end(); i++)
			delete *i;
		for (vector<Consumer*>::iterator i = consumers.begin(); i != consumers.end(); i++)
			delete *i;
	}
}

} // BlockBufferBasicTest

namespace BlockBufferCancelTest
{

class Producer : public Thread
{
public:
	Producer (BlockBuffer<deUint8>* buffer, deUint32 seed)
		: m_buffer	(buffer)
		, m_seed	(seed)
	{
	}

	void run (void)
	{
		deUint8	tmp[1024];
		Random	rnd(m_seed);

		deMemset(tmp, 0, DE_LENGTH_OF_ARRAY(tmp));

		for (;;)
		{
			int blockSize = rnd.getInt(1, DE_LENGTH_OF_ARRAY(tmp));

			try
			{
				m_buffer->write(blockSize, &tmp[0]);

				if (rnd.getBool())
					m_buffer->flush();
			}
			catch (const BlockBuffer<deUint8>::CanceledException&)
			{
				break;
			}
		}
	}

private:
	BlockBuffer<deUint8>*	m_buffer;
	deUint32				m_seed;
};

class Consumer : public Thread
{
public:
	Consumer (BlockBuffer<deUint8>* buffer, deUint32 seed)
		: m_buffer	(buffer)
		, m_seed	(seed)
	{
	}

	void run (void)
	{
		deUint8	tmp[1024];
		Random	rnd(m_seed);

		for (;;)
		{
			int blockSize = rnd.getInt(1, DE_LENGTH_OF_ARRAY(tmp));

			try
			{
				m_buffer->read(blockSize, &tmp[0]);
			}
			catch (const BlockBuffer<deUint8>::CanceledException&)
			{
				break;
			}
		}
	}

private:
	BlockBuffer<deUint8>*	m_buffer;
	deUint32				m_seed;
};

void runTest (void)
{
	BlockBuffer<deUint8>	buffer			(64, 16);
	const int				numIterations	= 8;

	for (int iterNdx = 0; iterNdx < numIterations; iterNdx++)
	{
		Random				rnd				(deInt32Hash(iterNdx));
		int					numThreads		= rnd.getInt(1, 16);
		int					sleepMs			= rnd.getInt(1, 200);
		vector<Thread*>		threads;

		for (int i = 0; i < numThreads; i++)
		{
			if (rnd.getBool())
				threads.push_back(new Consumer(&buffer, rnd.getUint32()));
			else
				threads.push_back(new Producer(&buffer, rnd.getUint32()));
		}

		// Start threads.
		for (vector<Thread*>::iterator i = threads.begin(); i != threads.end(); i++)
			(*i)->start();

		// Sleep for a while.
		deSleep(sleepMs);

		// Cancel buffer.
		buffer.cancel();

		// Wait for threads to finish.
		for (vector<Thread*>::iterator i = threads.begin(); i != threads.end(); i++)
			(*i)->join();

		// Reset buffer.
		buffer.clear();

		// Delete threads
		for (vector<Thread*>::iterator thread = threads.begin(); thread != threads.end(); ++thread)
			delete *thread;
	}
}

} // BlockBufferCancelTest

void BlockBuffer_selfTest (void)
{
	BlockBufferBasicTest::runTest();
	BlockBufferCancelTest::runTest();
}

} // de
