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 
33 namespace xe
34 {
35 
36 class Call;
37 class CallReader;
38 class CallWriter;
39 class 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 
45 class Call
46 {
47 public:
48 	typedef void (*Function) (CallReader& data);
49 
50 								Call				(void);
51 								~Call				(void);
52 
53 	void						clear				(void);
54 
getFunction(void) const55 	Function					getFunction			(void) const	{ return m_func;				}
setFunction(Function func)56 	void						setFunction			(Function func)	{ m_func = func;				}
57 
getDataSize(void) const58 	size_t						getDataSize			(void) const	{ return m_data.size();			}
setDataSize(size_t size)59 	void						setDataSize			(size_t size)	{ m_data.resize(size);			}
60 
getData(void) const61 	const deUint8*				getData				(void) const	{ return m_data.empty() ? DE_NULL : &m_data[0];	}
getData(void)62 	deUint8*					getData				(void)			{ return m_data.empty() ? DE_NULL : &m_data[0];	}
63 
64 private:
65 	Function					m_func;
66 	std::vector<deUint8>		m_data;
67 };
68 
69 class CallReader
70 {
71 public:
72 					CallReader			(Call* call);
CallReader(void)73 					CallReader			(void) : m_call(DE_NULL), m_curPos(0) {}
74 
75 	void			read				(deUint8* bytes, size_t numBytes);
76 	const deUint8*	getDataBlock		(size_t numBytes);					//!< \note Valid only during call.
77 	bool			isDataConsumed		(void) const;						//!< all data has been consumed
78 
79 private:
80 					CallReader			(const CallReader& other);	//!< disallowed
81 	CallReader&		operator=			(const CallReader& other);	//!< disallowed
82 
83 	Call*			m_call;
84 	size_t			m_curPos;
85 };
86 
87 class CallWriter
88 {
89 public:
90 					CallWriter			(CallQueue* queue, Call::Function function);
91 					~CallWriter			(void);
92 
93 	void			write				(const deUint8* bytes, size_t numBytes);
94 	void			enqueue				(void);
95 
96 private:
97 					CallWriter			(const CallWriter& other);
98 	CallWriter&		operator=			(const CallWriter& other);
99 
100 	CallQueue*		m_queue;
101 	Call*			m_call;
102 	bool			m_enqueued;
103 };
104 
105 class CallQueue
106 {
107 public:
108 							CallQueue			(void);
109 							~CallQueue			(void);
110 
111 	void					callNext			(void); //!< Executes and removes first call in queue. Will block if queue is empty.
112 
113 	Call*					getEmptyCall		(void);
114 	void					enqueue				(Call* call);
115 	void					freeCall			(Call* call);
116 	void					cancel				(void);
117 
118 private:
119 							CallQueue			(const CallQueue& other);
120 	CallQueue&				operator=			(const CallQueue& other);
121 
122 	bool					m_canceled;
123 	de::Semaphore			m_callSem;
124 
125 	de::Mutex				m_lock;
126 	std::vector<Call*>		m_calls;
127 	std::vector<Call*>		m_freeCalls;
128 	de::RingBuffer<Call*>	m_callQueue;
129 };
130 
131 // Stream operators for call reader / writer.
132 
133 CallReader&		operator>>	(CallReader& reader, std::string& value);
134 CallWriter&		operator<<	(CallWriter& writer, const char* str);
135 
136 template <typename T>
operator >>(CallReader & reader,T & value)137 CallReader& operator>> (CallReader& reader, T& value)
138 {
139 	reader.read((deUint8*)&value, sizeof(T));
140 	return reader;
141 }
142 
143 template <typename T>
operator <<(CallWriter & writer,T & value)144 CallWriter& operator<< (CallWriter& writer, T& value)
145 {
146 	writer.write((const deUint8*)&value, sizeof(T));
147 	return writer;
148 }
149 
150 } // xe
151 
152 #endif // _XECALLQUEUE_HPP
153