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:
44fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	enum Result
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
46fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi		RESULT_NOT_READY = 0,
47fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi		RESULT_OK,
48fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi		RESULT_FAILED
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
51fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi					Event 		(void);
52fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi					~Event		(void);
53fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	void			setResult	(Result result);
54fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	Result			waitReady	(void);
55fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	Result			getResult	(void) const { return m_result; }
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
58fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	volatile Result	m_result;
59fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	volatile 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:
72fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi										Object		(const char* type, de::SharedPtr<Event> createEvent);
73fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	virtual								~Object		(void);
74fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	const char*							getType		(void) const { return m_type; }
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Used by class Operation only
77fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	void								read		(de::SharedPtr<Event> event, std::vector<de::SharedPtr<Event> >& deps);
78fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	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
86fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi										Object		(const Object&);
87fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	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:
124fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	deUint64			m_time;
125fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	std::string			m_message;
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Base class for operations executed by threads
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass Operation
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
132fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi											Operation		(const char* name);
133fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	virtual									~Operation		(void);
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
135fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	const char*								getName			(void) const { return m_name; }
136fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	de::SharedPtr<Event>					getEvent		(void) { return m_event; }
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
138fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	void									readObject		(de::SharedPtr<Object> object) { object->read(m_event, m_deps); }
139fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	void									modifyObject	(de::SharedPtr<Object> object) { object->modify(m_event, m_deps); }
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
141fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	virtual void							exec			(Thread& thread) = 0;	//!< Overwritten by inherited class to perform actual operation
142fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	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
149fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi											Operation		(const Operation&);
150fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	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	};
165fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi							Thread				(int seed);
166fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi							~Thread				(void);
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
168fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	virtual void			init				(void) {}	//!< Called first before any Operation
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \todo [mika] Should the result of execution be passed to deinit?
171fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	virtual void			deinit				(void) {}	//!< Called after after operation
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
173fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	void					addOperation		(Operation* operation);
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
175fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	void					exec				(void);
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
177fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	deUint8*				getDummyData		(size_t size);	//!< Return data pointer that contains at least size bytes. Valid until next call
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
179fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	ThreadStatus			getStatus			(void) const { return m_status; }
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
181fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	MessageBuilder			newMessage			(void) { return MessageBuilder(*this); }
182fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	de::Random&				getRandom			(void) { return m_random; }
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Used to by test case to read log messages
185fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	int						getMessageCount		(void) const;
186fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	Message					getMessage			(int index) const;
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Used by message builder
189fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	void					pushMessage			(const std::string& str);
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
192fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	virtual void			run					(void);
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<Operation*>	m_operations;
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::Random				m_random;
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
197fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	mutable de::Mutex		m_messageLock;
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<Message>	m_messages;
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ThreadStatus			m_status;
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<deUint8>	m_dummyData;
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Disabled
203fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi							Thread				(const Thread&);
204fd41d5db179bcd04819c656c3100324a787a456fMika Isojärvi	Thread					operator=			(const Thread&);
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass DataBlock : public Object
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DataBlock	(de::SharedPtr<Event> event);
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void			setData		(size_t size, const void* data);
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const deUint8*	getData		(void) const { return &(m_data[0]); }
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	size_t			getSize		(void) const { return m_data.size(); }
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::vector<deUint8> m_data;
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyryclass CompareData : public Operation
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyrypublic:
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			CompareData	(de::SharedPtr<DataBlock> a, de::SharedPtr<DataBlock> b);
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	void	exec		(Thread& thread);
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyryprivate:
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::SharedPtr<DataBlock>	m_a;
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	de::SharedPtr<DataBlock>	m_b;
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // ThreadUtil
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // tcu
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif // _TCUTHREADUTIL_HPP
236