13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifndef _TCUTHREADUTIL_HPP
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define _TCUTHREADUTIL_HPP
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program Tester Core
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ----------------------------------------
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Thread test utilities
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "tcuDefs.hpp"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deSharedPtr.hpp"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMutex.hpp"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deSemaphore.hpp"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deThread.hpp"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deRandom.hpp"
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <vector>
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <sstream>
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace tcu
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace ThreadUtil
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Event object for synchronizing threads
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Event
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum	Result
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			RESULT_NOT_READY = 0,
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			RESULT_OK,
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			RESULT_FAILED
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			Event 		(void);
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			~Event		(void);
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	setResult	(Result result);
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Result	waitReady	(void);
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Result	getResult	(void) const { return m_result; }
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Result			m_result;
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				m_waiterCount;
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Semaphore	m_waiters;
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Mutex		m_lock;
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Disabled
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					Event		(const Event&);
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Event&			operator=	(const Event&);
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Base class for objects which modifications should be tracked between threads
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Object
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					Object				(const char* type, de::SharedPtr<Event> createEvent);
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual			~Object				(void);
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*		getType				(void) const { return m_type; }
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Used by class Operation only
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			read				(de::SharedPtr<Event> event, std::vector<de::SharedPtr<Event> >& deps);
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			modify				(de::SharedPtr<Event> event, std::vector<de::SharedPtr<Event> >& deps);
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*							m_type;
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::SharedPtr<Event>				m_modify;
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<de::SharedPtr<Event> >	m_reads;
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Disabled
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					Object				(const Object&);
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Object&			operator=			(const Object&);
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Thread;
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass MessageBuilder
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						MessageBuilder		(Thread& thread) : m_thread(thread) {}
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						MessageBuilder		(const MessageBuilder& other) : m_thread(other.m_thread), m_stream(other.m_stream.str()) {}
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	template<class T>
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MessageBuilder&		operator<<			(const T& t) { m_stream << t; return *this; }
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	class EndToken
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	public:
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						EndToken			(void) {}
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void 				operator<<			(const EndToken&);
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Thread&				m_thread;
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::stringstream	m_stream;
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Message
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						Message		(deUint64 time, const char* message) : m_time(time), m_message(message) {}
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint64			getTime		(void) const { return m_time; }
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const std::string&	getMessage	(void) const { return m_message; }
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const MessageBuilder::EndToken End;
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint64		m_time;
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string		m_message;
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Base class for operations executed by threads
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Operation
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							Operation		(const char* name);
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual					~Operation		(void);
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*				getName			(void) const { return m_name; }
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::SharedPtr<Event>	getEvent		(void) { return m_event; }
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					readObject		(de::SharedPtr<Object> object) { object->read(m_event, m_deps); }
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void					modifyObject	(de::SharedPtr<Object> object) { object->modify(m_event, m_deps); }
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void			exec			(Thread& thread) = 0;	//!< Overwritten by inherited class to perform actual operation
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void			execute			(Thread& thread);		//!< May Be overwritten by inherited class to change how syncronization is done
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprotected:
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char*								m_name;
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<de::SharedPtr<Event> >		m_deps;
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::SharedPtr<Event>					m_event;
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						Operation		(const Operation&);
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Operation&			operator=		(const Operation&);
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Thread : public de::Thread
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum ThreadStatus
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		THREADSTATUS_NOT_STARTED = 0,
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		THREADSTATUS_INIT_FAILED,
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		THREADSTATUS_RUNNING,
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		THREADSTATUS_READY,
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		THREADSTATUS_FAILED,
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		THREADSTATUS_NOT_SUPPORTED
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					Thread				(int seed);
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					~Thread				(void);
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void	init				(void) {}	//!< Called first before any Operation
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [mika] Should the result of execution be passed to deinit?
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void	deinit				(void) {}	//!< Called after after operation
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			addOperation		(Operation* operation);
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			exec				(void);
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	deUint8*		getDummyData		(size_t size);	//!< Return data pointer that contains at least size bytes. Valid until next call
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ThreadStatus	getStatus			(void) const { return m_status; }
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	MessageBuilder	newMessage			(void) { return MessageBuilder(*this); }
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random&		getRandom			(void) { return m_random; }
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Used to by test case to read log messages
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int				getMessageCount		(void) const { return (int)(m_messages.size()); }
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const Message&	getMessage			(int index) const { return m_messages[index]; }
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Used by message builder
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			pushMessage			(const std::string& str);
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	virtual void	run					(void);
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<Operation*>	m_operations;
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random				m_random;
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<Message>	m_messages;
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ThreadStatus			m_status;
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<deUint8>	m_dummyData;
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Disabled
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					Thread				(const Thread&);
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	Thread			operator=			(const Thread&);
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass DataBlock : public Object
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DataBlock	(de::SharedPtr<Event> event);
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			setData		(size_t size, const void* data);
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint8*	getData		(void) const { return &(m_data[0]); }
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	size_t			getSize		(void) const { return m_data.size(); }
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<deUint8> m_data;
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CompareData : public Operation
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			CompareData	(de::SharedPtr<DataBlock> a, de::SharedPtr<DataBlock> b);
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	exec		(Thread& thread);
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::SharedPtr<DataBlock>	m_a;
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::SharedPtr<DataBlock>	m_b;
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // ThreadUtil
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // tcu
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif // _TCUTHREADUTIL_HPP
235