1#ifndef _XECALLQUEUE_HPP
2#define _XECALLQUEUE_HPP
3/*-------------------------------------------------------------------------
4 * drawElements Quality Program Test Executor
5 * ------------------------------------------
6 *
7 * Copyright 2014 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Cross-thread function call dispatcher.
24 *//*--------------------------------------------------------------------*/
25
26#include "xeDefs.hpp"
27#include "deMutex.hpp"
28#include "deSemaphore.hpp"
29#include "deRingBuffer.hpp"
30
31#include <vector>
32
33namespace xe
34{
35
36class Call;
37class CallReader;
38class CallWriter;
39class CallQueue;
40
41// \todo [2012-07-10 pyry] Optimize memory management in Call
42// \todo [2012-07-10 pyry] CallQueue API could be improved to match TestLog API more closely.
43//						   In order to do that, reference counting system for call object management is needed.
44
45class Call
46{
47public:
48	typedef void (*Function) (CallReader data);
49
50								Call				(void);
51								~Call				(void);
52
53	void						clear				(void);
54
55	Function					getFunction			(void) const	{ return m_func;				}
56	void						setFunction			(Function func)	{ m_func = func;				}
57
58	int							getDataSize			(void) const	{ return (int)m_data.size();	}
59	void						setDataSize			(int size)		{ m_data.resize(size);			}
60
61	const deUint8*				getData				(void) const	{ return m_data.empty() ? DE_NULL : &m_data[0];	}
62	deUint8*					getData				(void)			{ return m_data.empty() ? DE_NULL : &m_data[0];	}
63
64private:
65	Function					m_func;
66	std::vector<deUint8>		m_data;
67};
68
69class CallReader
70{
71public:
72					CallReader			(Call* call);
73					CallReader			(void) : m_call(DE_NULL), m_curPos(0) {}
74
75	void			read				(deUint8* bytes, int numBytes);
76	const deUint8*	getDataBlock		(int numBytes);					//!< \note Valid only during call.
77
78private:
79	Call*			m_call;
80	int				m_curPos;
81};
82
83class CallWriter
84{
85public:
86					CallWriter			(CallQueue* queue, Call::Function function);
87					~CallWriter			(void);
88
89	void			write				(const deUint8* bytes, int numBytes);
90	void			enqueue				(void);
91
92private:
93					CallWriter			(const CallWriter& other);
94	CallWriter&		operator=			(const CallWriter& other);
95
96	CallQueue*		m_queue;
97	Call*			m_call;
98	bool			m_enqueued;
99};
100
101class CallQueue
102{
103public:
104							CallQueue			(void);
105							~CallQueue			(void);
106
107	void					callNext			(void); //!< Executes and removes first call in queue. Will block if queue is empty.
108
109	Call*					getEmptyCall		(void);
110	void					enqueue				(Call* call);
111	void					freeCall			(Call* call);
112
113private:
114							CallQueue			(const CallQueue& other);
115	CallQueue&				operator=			(const CallQueue& other);
116
117	de::Semaphore			m_callSem;
118
119	de::Mutex				m_lock;
120	std::vector<Call*>		m_calls;
121	std::vector<Call*>		m_freeCalls;
122	de::RingBuffer<Call*>	m_callQueue;
123};
124
125// Stream operators for call reader / writer.
126
127CallReader&		operator>>	(CallReader& reader, std::string& value);
128CallWriter&		operator<<	(CallWriter& writer, const char* str);
129
130template <typename T>
131CallReader& operator>> (CallReader& reader, T& value)
132{
133	reader.read((deUint8*)&value, sizeof(T));
134	return reader;
135}
136
137template <typename T>
138CallWriter& operator<< (CallWriter& writer, T& value)
139{
140	writer.write((const deUint8*)&value, sizeof(T));
141	return writer;
142}
143
144} // xe
145
146#endif // _XECALLQUEUE_HPP
147