#ifndef _XECALLQUEUE_HPP #define _XECALLQUEUE_HPP /*------------------------------------------------------------------------- * drawElements Quality Program Test Executor * ------------------------------------------ * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Cross-thread function call dispatcher. *//*--------------------------------------------------------------------*/ #include "xeDefs.hpp" #include "deMutex.hpp" #include "deSemaphore.hpp" #include "deRingBuffer.hpp" #include namespace xe { class Call; class CallReader; class CallWriter; class CallQueue; // \todo [2012-07-10 pyry] Optimize memory management in Call // \todo [2012-07-10 pyry] CallQueue API could be improved to match TestLog API more closely. // In order to do that, reference counting system for call object management is needed. class Call { public: typedef void (*Function)(CallReader &data); Call(void); ~Call(void); void clear(void); Function getFunction(void) const { return m_func; } void setFunction(Function func) { m_func = func; } size_t getDataSize(void) const { return m_data.size(); } void setDataSize(size_t size) { m_data.resize(size); } const uint8_t *getData(void) const { return m_data.empty() ? DE_NULL : &m_data[0]; } uint8_t *getData(void) { return m_data.empty() ? DE_NULL : &m_data[0]; } private: Function m_func; std::vector m_data; }; class CallReader { public: CallReader(Call *call); CallReader(void) : m_call(DE_NULL), m_curPos(0) { } void read(uint8_t *bytes, size_t numBytes); const uint8_t *getDataBlock(size_t numBytes); //!< \note Valid only during call. bool isDataConsumed(void) const; //!< all data has been consumed private: CallReader(const CallReader &other); //!< disallowed CallReader &operator=(const CallReader &other); //!< disallowed Call *m_call; size_t m_curPos; }; class CallWriter { public: CallWriter(CallQueue *queue, Call::Function function); ~CallWriter(void); void write(const uint8_t *bytes, size_t numBytes); void enqueue(void); private: CallWriter(const CallWriter &other); CallWriter &operator=(const CallWriter &other); CallQueue *m_queue; Call *m_call; bool m_enqueued; }; class CallQueue { public: CallQueue(void); ~CallQueue(void); void callNext(void); //!< Executes and removes first call in queue. Will block if queue is empty. Call *getEmptyCall(void); void enqueue(Call *call); void freeCall(Call *call); void cancel(void); private: CallQueue(const CallQueue &other); CallQueue &operator=(const CallQueue &other); bool m_canceled; de::Semaphore m_callSem; de::Mutex m_lock; std::vector m_calls; std::vector m_freeCalls; de::RingBuffer m_callQueue; }; // Stream operators for call reader / writer. CallReader &operator>>(CallReader &reader, std::string &value); CallWriter &operator<<(CallWriter &writer, const char *str); template CallReader &operator>>(CallReader &reader, T &value) { reader.read((uint8_t *)&value, sizeof(T)); return reader; } template CallWriter &operator<<(CallWriter &writer, T &value) { writer.write((const uint8_t *)&value, sizeof(T)); return writer; } } // namespace xe #endif // _XECALLQUEUE_HPP