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 	int							getDataSize			(void) const	{ return (int)m_data.size();	}
setDataSize(int size)59 	void						setDataSize			(int 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, int numBytes);
76 	const deUint8*	getDataBlock		(int numBytes);					//!< \note Valid only during call.
77 
78 private:
79 	Call*			m_call;
80 	int				m_curPos;
81 };
82 
83 class CallWriter
84 {
85 public:
86 					CallWriter			(CallQueue* queue, Call::Function function);
87 					~CallWriter			(void);
88 
89 	void			write				(const deUint8* bytes, int numBytes);
90 	void			enqueue				(void);
91 
92 private:
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 
101 class CallQueue
102 {
103 public:
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 
113 private:
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 
127 CallReader&		operator>>	(CallReader& reader, std::string& value);
128 CallWriter&		operator<<	(CallWriter& writer, const char* str);
129 
130 template <typename T>
operator >>(CallReader & reader,T & value)131 CallReader& operator>> (CallReader& reader, T& value)
132 {
133 	reader.read((deUint8*)&value, sizeof(T));
134 	return reader;
135 }
136 
137 template <typename T>
operator <<(CallWriter & writer,T & value)138 CallWriter& 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