#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 <vector> 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; } int getDataSize (void) const { return (int)m_data.size(); } void setDataSize (int size) { m_data.resize(size); } const deUint8* getData (void) const { return m_data.empty() ? DE_NULL : &m_data[0]; } deUint8* getData (void) { return m_data.empty() ? DE_NULL : &m_data[0]; } private: Function m_func; std::vector<deUint8> m_data; }; class CallReader { public: CallReader (Call* call); CallReader (void) : m_call(DE_NULL), m_curPos(0) {} void read (deUint8* bytes, int numBytes); const deUint8* getDataBlock (int numBytes); //!< \note Valid only during call. private: Call* m_call; int m_curPos; }; class CallWriter { public: CallWriter (CallQueue* queue, Call::Function function); ~CallWriter (void); void write (const deUint8* bytes, int 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); private: CallQueue (const CallQueue& other); CallQueue& operator= (const CallQueue& other); de::Semaphore m_callSem; de::Mutex m_lock; std::vector<Call*> m_calls; std::vector<Call*> m_freeCalls; de::RingBuffer<Call*> m_callQueue; }; // Stream operators for call reader / writer. CallReader& operator>> (CallReader& reader, std::string& value); CallWriter& operator<< (CallWriter& writer, const char* str); template <typename T> CallReader& operator>> (CallReader& reader, T& value) { reader.read((deUint8*)&value, sizeof(T)); return reader; } template <typename T> CallWriter& operator<< (CallWriter& writer, T& value) { writer.write((const deUint8*)&value, sizeof(T)); return writer; } } // xe #endif // _XECALLQUEUE_HPP