/*-------------------------------------------------------------------------
 * drawElements C++ Base Library
 * -----------------------------
 *
 * Copyright 2015 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 Fast ordered append-only container
 *//*--------------------------------------------------------------------*/

#include "deAppendList.hpp"
#include "deThread.hpp"
#include "deSpinBarrier.hpp"
#include "deSharedPtr.hpp"

#include <vector>
#include <algorithm>

namespace de
{

namespace
{

using std::vector;

struct TestElem
{
	deUint32	threadNdx;
	deUint32	elemNdx;

	TestElem (deUint32 threadNdx_, deUint32 elemNdx_)
		: threadNdx	(threadNdx_)
		, elemNdx	(elemNdx_)
	{}

	TestElem (void)
		: threadNdx	(0)
		, elemNdx	(0)
	{}
};

struct SharedState
{
	deUint32				numElements;
	SpinBarrier				barrier;
	AppendList<TestElem>	testList;

	SharedState (deUint32 numThreads, deUint32 numElements_, deUint32 numElementsHint)
		: numElements	(numElements_)
		, barrier		(numThreads)
		, testList		(numElementsHint)
	{}
};

class TestThread : public Thread
{
public:
	TestThread (SharedState* shared, deUint32 threadNdx)
		: m_shared		(shared)
		, m_threadNdx	(threadNdx)
	{}

	void run (void)
	{
		const deUint32	syncPerElems	= 10000;

		for (deUint32 elemNdx = 0; elemNdx < m_shared->numElements; elemNdx++)
		{
			if (elemNdx % syncPerElems == 0)
				m_shared->barrier.sync(SpinBarrier::WAIT_MODE_AUTO);

			m_shared->testList.append(TestElem(m_threadNdx, elemNdx));
		}
	}

private:
	SharedState* const	m_shared;
	const deUint32		m_threadNdx;
};

typedef SharedPtr<TestThread> TestThreadSp;

void runAppendListTest (deUint32 numThreads, deUint32 numElements, deUint32 numElementsHint)
{
	SharedState				sharedState		(numThreads, numElements, numElementsHint);
	vector<TestThreadSp>	threads			(numThreads);

	for (deUint32 threadNdx = 0; threadNdx < numThreads; ++threadNdx)
	{
		threads[threadNdx] = TestThreadSp(new TestThread(&sharedState, threadNdx));
		threads[threadNdx]->start();
	}

	for (deUint32 threadNdx = 0; threadNdx < numThreads; ++threadNdx)
		threads[threadNdx]->join();

	DE_TEST_ASSERT(sharedState.testList.size() == (size_t)numElements*(size_t)numThreads);

	{
		vector<deUint32>	countByThread	(numThreads);

		std::fill(countByThread.begin(), countByThread.end(), 0);

		for (AppendList<TestElem>::const_iterator elemIter = sharedState.testList.begin();
			 elemIter != sharedState.testList.end();
			 ++elemIter)
		{
			const TestElem&	elem	= *elemIter;

			DE_TEST_ASSERT(de::inBounds(elem.threadNdx, 0u, numThreads));
			DE_TEST_ASSERT(countByThread[elem.threadNdx] == elem.elemNdx);

			countByThread[elem.threadNdx] += 1;
		}

		for (deUint32 threadNdx = 0; threadNdx < numThreads; ++threadNdx)
			DE_TEST_ASSERT(countByThread[threadNdx] == numElements);
	}
}

} // anonymous

void AppendList_selfTest (void)
{
	// Single-threaded
	runAppendListTest(1, 1000, 500);
	runAppendListTest(1, 1000, 2000);
	runAppendListTest(1, 35, 1);

	// Multi-threaded
	runAppendListTest(2, 10000, 500);
	runAppendListTest(2, 100, 10);

	if (deGetNumAvailableLogicalCores() >= 4)
	{
		runAppendListTest(4, 10000, 500);
		runAppendListTest(4, 100, 10);
	}
}

} // de
