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