00001 /* 00002 * Copyright (C) 2009, Edmundo Albuquerque de Souza e Silva. 00003 * 00004 * This file may be distributed under the terms of the Q Public License 00005 * as defined by Trolltech AS of Norway and appearing in the file 00006 * LICENSE.QPL included in the packaging of this file. 00007 * 00008 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING 00009 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00010 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, 00011 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING 00012 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 00013 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 00014 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00015 * 00016 * Thanks: Jose Renato Santos 00017 * 00018 */ 00019 00020 /////////////////////////////////////////////////////////////////////////////// 00021 // request.cpp : Implementation of request classes: 00022 // - CRequestQueue 00023 // - CRequestManager 00024 /////////////////////////////////////////////////////////////////////////////// 00025 00026 #include <request.h> 00027 #include <sserror.h> 00028 00029 #include <iostream> 00030 00031 #include "../interface/RioError.h" 00032 00033 using namespace std; 00034 00035 //////////////////////////// CRequestQueue /////////////////////////////////// 00036 00037 /////////////////////////////////////////////////////////////////////////////// 00038 // Put -- Put request at end of queue 00039 void CRequestQueue::Put(StrRequest* Request) 00040 { 00041 m_Queue.Put( (RioQueueEle*) Request); 00042 } 00043 00044 /////////////////////////////////////////////////////////////////////////////// 00045 // Get -- Get first element of queue. Block calling thread if none 00046 // available (Requires single thread using Get() ) 00047 StrRequest* CRequestQueue::Get() 00048 { 00049 //m_Queue � um tipo RioQueue. 00050 return (StrRequest*) m_Queue.Get(); 00051 } 00052 00053 /////////////////////////////////////////////////////////////////////////////// 00054 // Signal -- Force a thread blocked on Get() to unblock if there is 00055 // such a thread. Get() will return 0 in this case 00056 void CRequestQueue::Signal() 00057 { 00058 m_Queue.Signal(); 00059 } 00060 00061 //////////////////////////// CRequestManager ///////////////////////////////// 00062 00063 /////////////////////////////////////////////////////////////////////////////// 00064 CRequestManager::CRequestManager() 00065 { 00066 m_Request = NULL; 00067 m_n = 0; 00068 } 00069 00070 CRequestManager::~CRequestManager() 00071 { 00072 if(m_Request != 0) 00073 { 00074 delete[] m_Request; 00075 } 00076 } 00077 00078 /////////////////////////////////////////////////////////////////////////////// 00079 int CRequestManager::Initialize( const unsigned int nRequest, 00080 const unsigned int BufferSize ) 00081 { 00082 00083 // debug ----------------------------------------------- 00084 RioErr << "RequestManager: Max number = " << 0xffff << endl; 00085 RioErr << "RequestManager: Using = "<< nRequest << endl; 00086 // ------------------------------------------------------------------------ 00087 00088 // Request index has to fit in 16 bits 00089 if( ( nRequest <= 0 ) || ( nRequest > 0xffff )) 00090 { 00091 return ERROR_SS_PROGRAM_ERROR; 00092 } 00093 00094 // In case was initialized before 00095 if(m_Request != 0) 00096 { 00097 delete[] m_Request; 00098 m_n = 0; 00099 } 00100 00101 m_Request = new StrRequest[nRequest]; 00102 00103 if( m_Request == 0 ) 00104 return ERROR_SS_MEMORY; 00105 00106 m_n = nRequest; 00107 00108 int stat = m_BufferManager.Initialize( nRequest,BufferSize ); 00109 00110 if(stat < 0) 00111 { 00112 delete[] m_Request; 00113 return stat; 00114 } 00115 00116 for( int i= ((int)(nRequest))-1; i>=0; i-- ) 00117 { 00118 m_Request[i].Status = RequestStatusFree; 00119 m_Request[i].Id = i; 00120 m_Request[i].Buffer = m_BufferManager.New(); 00121 m_Request[i].Data = m_Request[i].Buffer->Data; 00122 m_FreeList.Free((RioQueueEle*)&m_Request[i]); 00123 } 00124 00125 return (0); 00126 00127 } 00128 00129 /////////////////////////////////////////////////////////////////////////////// 00130 // Free --Return Request to free list 00131 void CRequestManager::Free(StrRequest* Request) 00132 { 00133 // Higher order 16 bits are version number, incremented every time 00134 // request is free. Lower order 16 bits are index to 00135 // vector m_Request 00136 00137 //RioErr << "Free request: (before): " << (void *) Request->Id << endl; 00138 00139 u32 Version = ((Request->Id & 0xffff0000) >> 16 ); 00140 Version ++; 00141 u32 Ind = Request->Id & 0xffff; 00142 Request->Id = Ind | (Version << 16); 00143 Request->Status = RequestStatusFree; 00144 00145 00146 //RioErr << "Version: " << (void*) Version << endl; 00147 //RioErr << "Free request: (after): " << (void*) Request->Id << endl; 00148 00149 m_FreeList.Free( (RioQueueEle*)Request); 00150 } 00151 00152 /////////////////////////////////////////////////////////////////////////////// 00153 // New -- Get new request structure from free list if available, otherwise 00154 // return null 00155 StrRequest* CRequestManager::New() 00156 { 00157 StrRequest* rp; 00158 00159 rp = (StrRequest*) m_FreeList.GetNB(); 00160 00161 return rp; 00162 } 00163 00164 /////////////////////////////////////////////////////////////////////////////// 00165 // Get -- Get address of request structure associated with a given request id 00166 StrRequest* CRequestManager::Get(const u32 ReqId) 00167 { 00168 StrRequest* rp; 00169 00170 // lower 16 bits are index to vector m_Request; 00171 unsigned int ind = ReqId & 0xffff; 00172 00173 if(ind >= m_n) 00174 return 0; 00175 00176 rp = &m_Request[ind]; 00177 00178 // Request must be in use and Request Id version must match 00179 if( (rp->Status != RequestStatusFree) && (rp->Id == ReqId) ) 00180 return rp; 00181 else 00182 return 0; 00183 } 00184