1e5c31af7Sopenharmony_ci/*------------------------------------------------------------------------- 2e5c31af7Sopenharmony_ci * drawElements Quality Program Test Executor 3e5c31af7Sopenharmony_ci * ------------------------------------------ 4e5c31af7Sopenharmony_ci * 5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project 6e5c31af7Sopenharmony_ci * 7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License. 9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at 10e5c31af7Sopenharmony_ci * 11e5c31af7Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 12e5c31af7Sopenharmony_ci * 13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and 17e5c31af7Sopenharmony_ci * limitations under the License. 18e5c31af7Sopenharmony_ci * 19e5c31af7Sopenharmony_ci *//*! 20e5c31af7Sopenharmony_ci * \file 21e5c31af7Sopenharmony_ci * \brief Cross-thread function call dispatcher. 22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/ 23e5c31af7Sopenharmony_ci 24e5c31af7Sopenharmony_ci#include "xeCallQueue.hpp" 25e5c31af7Sopenharmony_ci#include "deInt32.h" 26e5c31af7Sopenharmony_ci#include "deMemory.h" 27e5c31af7Sopenharmony_ci 28e5c31af7Sopenharmony_ciusing std::vector; 29e5c31af7Sopenharmony_ci 30e5c31af7Sopenharmony_cistatic inline int getNextQueueSize (int curSize, int minNewSize) 31e5c31af7Sopenharmony_ci{ 32e5c31af7Sopenharmony_ci return de::max(curSize*2, 1<<deLog2Ceil32(minNewSize)); 33e5c31af7Sopenharmony_ci} 34e5c31af7Sopenharmony_ci 35e5c31af7Sopenharmony_cinamespace xe 36e5c31af7Sopenharmony_ci{ 37e5c31af7Sopenharmony_ci 38e5c31af7Sopenharmony_ci// CallQueue 39e5c31af7Sopenharmony_ci 40e5c31af7Sopenharmony_ciCallQueue::CallQueue (void) 41e5c31af7Sopenharmony_ci : m_canceled (false) 42e5c31af7Sopenharmony_ci , m_callSem (0) 43e5c31af7Sopenharmony_ci , m_callQueue (64) 44e5c31af7Sopenharmony_ci{ 45e5c31af7Sopenharmony_ci} 46e5c31af7Sopenharmony_ci 47e5c31af7Sopenharmony_ciCallQueue::~CallQueue (void) 48e5c31af7Sopenharmony_ci{ 49e5c31af7Sopenharmony_ci // Destroy all calls. 50e5c31af7Sopenharmony_ci for (vector<Call*>::iterator i = m_calls.begin(); i != m_calls.end(); i++) 51e5c31af7Sopenharmony_ci delete *i; 52e5c31af7Sopenharmony_ci} 53e5c31af7Sopenharmony_ci 54e5c31af7Sopenharmony_civoid CallQueue::cancel (void) 55e5c31af7Sopenharmony_ci{ 56e5c31af7Sopenharmony_ci m_canceled = true; 57e5c31af7Sopenharmony_ci m_callSem.increment(); 58e5c31af7Sopenharmony_ci} 59e5c31af7Sopenharmony_ci 60e5c31af7Sopenharmony_civoid CallQueue::callNext (void) 61e5c31af7Sopenharmony_ci{ 62e5c31af7Sopenharmony_ci Call* call = DE_NULL; 63e5c31af7Sopenharmony_ci 64e5c31af7Sopenharmony_ci // Wait for a call. 65e5c31af7Sopenharmony_ci m_callSem.decrement(); 66e5c31af7Sopenharmony_ci 67e5c31af7Sopenharmony_ci if (m_canceled) 68e5c31af7Sopenharmony_ci return; 69e5c31af7Sopenharmony_ci 70e5c31af7Sopenharmony_ci // Acquire call from buffer. 71e5c31af7Sopenharmony_ci { 72e5c31af7Sopenharmony_ci de::ScopedLock lock(m_lock); 73e5c31af7Sopenharmony_ci call = m_callQueue.popBack(); 74e5c31af7Sopenharmony_ci } 75e5c31af7Sopenharmony_ci 76e5c31af7Sopenharmony_ci try 77e5c31af7Sopenharmony_ci { 78e5c31af7Sopenharmony_ci // \note Enqueue lock is not held during call so it is possible to enqueue more work from dispatched call. 79e5c31af7Sopenharmony_ci CallReader reader(call); 80e5c31af7Sopenharmony_ci 81e5c31af7Sopenharmony_ci call->getFunction()(reader); 82e5c31af7Sopenharmony_ci 83e5c31af7Sopenharmony_ci // check callee consumed all 84e5c31af7Sopenharmony_ci DE_ASSERT(reader.isDataConsumed()); 85e5c31af7Sopenharmony_ci call->clear(); 86e5c31af7Sopenharmony_ci } 87e5c31af7Sopenharmony_ci catch (const std::exception&) 88e5c31af7Sopenharmony_ci { 89e5c31af7Sopenharmony_ci try 90e5c31af7Sopenharmony_ci { 91e5c31af7Sopenharmony_ci // Try to push call into free calls list. 92e5c31af7Sopenharmony_ci de::ScopedLock lock(m_lock); 93e5c31af7Sopenharmony_ci m_freeCalls.push_back(call); 94e5c31af7Sopenharmony_ci } 95e5c31af7Sopenharmony_ci catch (const std::exception&) 96e5c31af7Sopenharmony_ci { 97e5c31af7Sopenharmony_ci // We can't do anything but ignore this. 98e5c31af7Sopenharmony_ci } 99e5c31af7Sopenharmony_ci 100e5c31af7Sopenharmony_ci throw; 101e5c31af7Sopenharmony_ci } 102e5c31af7Sopenharmony_ci 103e5c31af7Sopenharmony_ci // Push back to free calls list. 104e5c31af7Sopenharmony_ci { 105e5c31af7Sopenharmony_ci de::ScopedLock lock(m_lock); 106e5c31af7Sopenharmony_ci m_freeCalls.push_back(call); 107e5c31af7Sopenharmony_ci } 108e5c31af7Sopenharmony_ci} 109e5c31af7Sopenharmony_ci 110e5c31af7Sopenharmony_ciCall* CallQueue::getEmptyCall (void) 111e5c31af7Sopenharmony_ci{ 112e5c31af7Sopenharmony_ci de::ScopedLock lock (m_lock); 113e5c31af7Sopenharmony_ci Call* call = DE_NULL; 114e5c31af7Sopenharmony_ci 115e5c31af7Sopenharmony_ci // Try to get from free calls list. 116e5c31af7Sopenharmony_ci if (!m_freeCalls.empty()) 117e5c31af7Sopenharmony_ci { 118e5c31af7Sopenharmony_ci call = m_freeCalls.back(); 119e5c31af7Sopenharmony_ci m_freeCalls.pop_back(); 120e5c31af7Sopenharmony_ci } 121e5c31af7Sopenharmony_ci 122e5c31af7Sopenharmony_ci // If no free calls were available, create a new. 123e5c31af7Sopenharmony_ci if (!call) 124e5c31af7Sopenharmony_ci { 125e5c31af7Sopenharmony_ci m_calls.reserve(m_calls.size()+1); 126e5c31af7Sopenharmony_ci call = new Call(); 127e5c31af7Sopenharmony_ci m_calls.push_back(call); 128e5c31af7Sopenharmony_ci } 129e5c31af7Sopenharmony_ci 130e5c31af7Sopenharmony_ci return call; 131e5c31af7Sopenharmony_ci} 132e5c31af7Sopenharmony_ci 133e5c31af7Sopenharmony_civoid CallQueue::enqueue (Call* call) 134e5c31af7Sopenharmony_ci{ 135e5c31af7Sopenharmony_ci de::ScopedLock lock(m_lock); 136e5c31af7Sopenharmony_ci 137e5c31af7Sopenharmony_ci if (m_callQueue.getNumFree() == 0) 138e5c31af7Sopenharmony_ci { 139e5c31af7Sopenharmony_ci // Call queue must be grown. 140e5c31af7Sopenharmony_ci m_callQueue.resize(getNextQueueSize(m_callQueue.getSize(), m_callQueue.getSize()+1)); 141e5c31af7Sopenharmony_ci } 142e5c31af7Sopenharmony_ci 143e5c31af7Sopenharmony_ci m_callQueue.pushFront(call); 144e5c31af7Sopenharmony_ci m_callSem.increment(); 145e5c31af7Sopenharmony_ci} 146e5c31af7Sopenharmony_ci 147e5c31af7Sopenharmony_civoid CallQueue::freeCall (Call* call) 148e5c31af7Sopenharmony_ci{ 149e5c31af7Sopenharmony_ci de::ScopedLock lock(m_lock); 150e5c31af7Sopenharmony_ci m_freeCalls.push_back(call); 151e5c31af7Sopenharmony_ci} 152e5c31af7Sopenharmony_ci 153e5c31af7Sopenharmony_ci// Call 154e5c31af7Sopenharmony_ci 155e5c31af7Sopenharmony_ciCall::Call (void) 156e5c31af7Sopenharmony_ci : m_func(DE_NULL) 157e5c31af7Sopenharmony_ci{ 158e5c31af7Sopenharmony_ci} 159e5c31af7Sopenharmony_ci 160e5c31af7Sopenharmony_ciCall::~Call (void) 161e5c31af7Sopenharmony_ci{ 162e5c31af7Sopenharmony_ci} 163e5c31af7Sopenharmony_ci 164e5c31af7Sopenharmony_civoid Call::clear (void) 165e5c31af7Sopenharmony_ci{ 166e5c31af7Sopenharmony_ci m_func = DE_NULL; 167e5c31af7Sopenharmony_ci m_data.clear(); 168e5c31af7Sopenharmony_ci} 169e5c31af7Sopenharmony_ci 170e5c31af7Sopenharmony_ci// CallReader 171e5c31af7Sopenharmony_ci 172e5c31af7Sopenharmony_ciCallReader::CallReader (Call* call) 173e5c31af7Sopenharmony_ci : m_call (call) 174e5c31af7Sopenharmony_ci , m_curPos (0) 175e5c31af7Sopenharmony_ci{ 176e5c31af7Sopenharmony_ci} 177e5c31af7Sopenharmony_ci 178e5c31af7Sopenharmony_civoid CallReader::read (deUint8* bytes, size_t numBytes) 179e5c31af7Sopenharmony_ci{ 180e5c31af7Sopenharmony_ci DE_ASSERT(m_curPos + numBytes <= m_call->getDataSize()); 181e5c31af7Sopenharmony_ci deMemcpy(bytes, m_call->getData()+m_curPos, numBytes); 182e5c31af7Sopenharmony_ci m_curPos += numBytes; 183e5c31af7Sopenharmony_ci} 184e5c31af7Sopenharmony_ci 185e5c31af7Sopenharmony_ciconst deUint8* CallReader::getDataBlock (size_t numBytes) 186e5c31af7Sopenharmony_ci{ 187e5c31af7Sopenharmony_ci DE_ASSERT(m_curPos + numBytes <= m_call->getDataSize()); 188e5c31af7Sopenharmony_ci 189e5c31af7Sopenharmony_ci const deUint8* ptr = m_call->getData()+m_curPos; 190e5c31af7Sopenharmony_ci m_curPos += numBytes; 191e5c31af7Sopenharmony_ci 192e5c31af7Sopenharmony_ci return ptr; 193e5c31af7Sopenharmony_ci} 194e5c31af7Sopenharmony_ci 195e5c31af7Sopenharmony_cibool CallReader::isDataConsumed (void) const 196e5c31af7Sopenharmony_ci{ 197e5c31af7Sopenharmony_ci return m_curPos == m_call->getDataSize(); 198e5c31af7Sopenharmony_ci} 199e5c31af7Sopenharmony_ci 200e5c31af7Sopenharmony_ciCallReader& operator>> (CallReader& reader, std::string& value) 201e5c31af7Sopenharmony_ci{ 202e5c31af7Sopenharmony_ci value.clear(); 203e5c31af7Sopenharmony_ci for (;;) 204e5c31af7Sopenharmony_ci { 205e5c31af7Sopenharmony_ci char c; 206e5c31af7Sopenharmony_ci reader.read((deUint8*)&c, sizeof(char)); 207e5c31af7Sopenharmony_ci if (c != 0) 208e5c31af7Sopenharmony_ci value.push_back(c); 209e5c31af7Sopenharmony_ci else 210e5c31af7Sopenharmony_ci break; 211e5c31af7Sopenharmony_ci } 212e5c31af7Sopenharmony_ci 213e5c31af7Sopenharmony_ci return reader; 214e5c31af7Sopenharmony_ci} 215e5c31af7Sopenharmony_ci 216e5c31af7Sopenharmony_ci// CallWriter 217e5c31af7Sopenharmony_ci 218e5c31af7Sopenharmony_ciCallWriter::CallWriter (CallQueue* queue, Call::Function function) 219e5c31af7Sopenharmony_ci : m_queue (queue) 220e5c31af7Sopenharmony_ci , m_call (queue->getEmptyCall()) 221e5c31af7Sopenharmony_ci , m_enqueued (false) 222e5c31af7Sopenharmony_ci{ 223e5c31af7Sopenharmony_ci m_call->setFunction(function); 224e5c31af7Sopenharmony_ci} 225e5c31af7Sopenharmony_ci 226e5c31af7Sopenharmony_ciCallWriter::~CallWriter (void) 227e5c31af7Sopenharmony_ci{ 228e5c31af7Sopenharmony_ci if (!m_enqueued) 229e5c31af7Sopenharmony_ci m_queue->freeCall(m_call); 230e5c31af7Sopenharmony_ci} 231e5c31af7Sopenharmony_ci 232e5c31af7Sopenharmony_civoid CallWriter::write (const deUint8* bytes, size_t numBytes) 233e5c31af7Sopenharmony_ci{ 234e5c31af7Sopenharmony_ci DE_ASSERT(!m_enqueued); 235e5c31af7Sopenharmony_ci size_t curPos = m_call->getDataSize(); 236e5c31af7Sopenharmony_ci m_call->setDataSize(curPos+numBytes); 237e5c31af7Sopenharmony_ci deMemcpy(m_call->getData()+curPos, bytes, numBytes); 238e5c31af7Sopenharmony_ci} 239e5c31af7Sopenharmony_ci 240e5c31af7Sopenharmony_civoid CallWriter::enqueue (void) 241e5c31af7Sopenharmony_ci{ 242e5c31af7Sopenharmony_ci DE_ASSERT(!m_enqueued); 243e5c31af7Sopenharmony_ci m_queue->enqueue(m_call); 244e5c31af7Sopenharmony_ci m_enqueued = true; 245e5c31af7Sopenharmony_ci} 246e5c31af7Sopenharmony_ci 247e5c31af7Sopenharmony_ciCallWriter& operator<< (CallWriter& writer, const char* str) 248e5c31af7Sopenharmony_ci{ 249e5c31af7Sopenharmony_ci int pos = 0; 250e5c31af7Sopenharmony_ci for (;;) 251e5c31af7Sopenharmony_ci { 252e5c31af7Sopenharmony_ci writer.write((const deUint8*)str + pos, sizeof(char)); 253e5c31af7Sopenharmony_ci if (str[pos] == 0) 254e5c31af7Sopenharmony_ci break; 255e5c31af7Sopenharmony_ci pos += 1; 256e5c31af7Sopenharmony_ci } 257e5c31af7Sopenharmony_ci 258e5c31af7Sopenharmony_ci return writer; 259e5c31af7Sopenharmony_ci} 260e5c31af7Sopenharmony_ci 261e5c31af7Sopenharmony_ci} // xe 262