1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Test Executor
3 * ------------------------------------------
5 * Copyright 2014 The Android Open Source Project
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief Cross-thread function call dispatcher.
22 *//*--------------------------------------------------------------------*/
24 #include "xeCallQueue.hpp"
30 static inline int getNextQueueSize (int curSize, int minNewSize)
32 return de::max(curSize*2, 1<<deLog2Ceil32(minNewSize));
40 CallQueue::CallQueue (void)
46 CallQueue::~CallQueue (void)
49 for (vector<Call*>::iterator i = m_calls.begin(); i != m_calls.end(); i++)
53 void CallQueue::callNext (void)
58 m_callSem.decrement();
60 // Acquire call from buffer.
62 de::ScopedLock lock(m_lock);
63 call = m_callQueue.popBack();
68 // \note Enqueue lock is not held during call so it is possible to enqueue more work from dispatched call.
69 call->getFunction()(CallReader(call));
72 catch (const std::exception&)
76 // Try to push call into free calls list.
77 de::ScopedLock lock(m_lock);
78 m_freeCalls.push_back(call);
80 catch (const std::exception&)
82 // We can't do anything but ignore this.
88 // Push back to free calls list.
90 de::ScopedLock lock(m_lock);
91 m_freeCalls.push_back(call);
95 Call* CallQueue::getEmptyCall (void)
97 de::ScopedLock lock (m_lock);
100 // Try to get from free calls list.
101 if (!m_freeCalls.empty())
103 call = m_freeCalls.back();
104 m_freeCalls.pop_back();
107 // If no free calls were available, create a new.
110 m_calls.reserve(m_calls.size()+1);
112 m_calls.push_back(call);
118 void CallQueue::enqueue (Call* call)
120 de::ScopedLock lock(m_lock);
122 if (m_callQueue.getNumFree() == 0)
124 // Call queue must be grown.
125 m_callQueue.resize(getNextQueueSize(m_callQueue.getSize(), m_callQueue.getSize()+1));
128 m_callQueue.pushFront(call);
129 m_callSem.increment();
132 void CallQueue::freeCall (Call* call)
134 de::ScopedLock lock(m_lock);
135 m_freeCalls.push_back(call);
149 void Call::clear (void)
157 CallReader::CallReader (Call* call)
163 void CallReader::read (deUint8* bytes, int numBytes)
165 DE_ASSERT(m_curPos + numBytes <= m_call->getDataSize());
166 deMemcpy(bytes, m_call->getData()+m_curPos, numBytes);
167 m_curPos += numBytes;
170 const deUint8* CallReader::getDataBlock (int numBytes)
172 DE_ASSERT(m_curPos + numBytes <= m_call->getDataSize());
174 const deUint8* ptr = m_call->getData()+m_curPos;
175 m_curPos += numBytes;
180 CallReader& operator>> (CallReader& reader, std::string& value)
186 reader.read((deUint8*)&c, sizeof(char));
198 CallWriter::CallWriter (CallQueue* queue, Call::Function function)
200 , m_call (queue->getEmptyCall())
203 m_call->setFunction(function);
206 CallWriter::~CallWriter (void)
209 m_queue->freeCall(m_call);
212 void CallWriter::write (const deUint8* bytes, int numBytes)
214 DE_ASSERT(!m_enqueued);
215 int curPos = m_call->getDataSize();
216 m_call->setDataSize(curPos+numBytes);
217 deMemcpy(m_call->getData()+curPos, bytes, numBytes);
220 void CallWriter::enqueue (void)
222 DE_ASSERT(!m_enqueued);
223 m_queue->enqueue(m_call);
227 CallWriter& operator<< (CallWriter& writer, const char* str)
232 writer.write((const deUint8*)str + pos, sizeof(char));