![]() |
Shadowrun: Awakened 29 September 2011 - Build 871
|
00001 /* 00002 Copyright (c) 2009-2010 Christopher A. Taylor. All rights reserved. 00003 00004 Redistribution and use in source and binary forms, with or without 00005 modification, are permitted provided that the following conditions are met: 00006 00007 * Redistributions of source code must retain the above copyright notice, 00008 this list of conditions and the following disclaimer. 00009 * Redistributions in binary form must reproduce the above copyright notice, 00010 this list of conditions and the following disclaimer in the documentation 00011 and/or other materials provided with the distribution. 00012 * Neither the name of LibCat nor the names of its contributors may be used 00013 to endorse or promote products derived from this software without 00014 specific prior written permission. 00015 00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00017 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00018 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00019 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00020 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00021 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00022 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00023 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00024 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00025 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00026 POSSIBILITY OF SUCH DAMAGE. 00027 */ 00028 00029 #ifndef CAT_ASYNC_BUFFER_HPP 00030 #define CAT_ASYNC_BUFFER_HPP 00031 00032 #include <cat/Platform.hpp> 00033 #include <cat/port/FastDelegate.h> 00034 00035 #if defined(CAT_OS_WINDOWS) 00036 # include <cat/port/WindowsInclude.hpp> 00037 #endif 00038 00039 namespace cat { 00040 00041 00042 class ThreadPoolLocalStorage; 00043 class AsyncBuffer; 00044 00045 00046 typedef fastdelegate::FastDelegate4<ThreadPoolLocalStorage *, int, AsyncBuffer *, u32, bool> AsyncCallback; 00047 00048 00049 // Overlapped base object 00050 #if defined(CAT_OS_WINDOWS) 00051 typedef OVERLAPPED AsyncOv; 00052 #else 00053 #error "TODO" 00054 #endif 00055 00056 00057 /* 00058 AsyncBuffer: Utility object representing the buffers for a single I/O operation. 00059 00060 This is flexible enough to represent network and file IO buffers. 00061 */ 00062 class AsyncBuffer 00063 { 00064 private: 00065 AsyncOv _ov; 00066 AsyncCallback _callback; 00067 u8 *_data; 00068 u32 _data_bytes, _tag_bytes; 00069 u8 _tag[1]; 00070 00071 public: 00072 // Reset AsyncOv and set offset and callback 00073 CAT_INLINE void Reset(const AsyncCallback &callback, u64 offset = 0) 00074 { 00075 #if defined(CAT_OS_WINDOWS) 00076 _ov.hEvent = 0; 00077 _ov.Internal = 0; 00078 _ov.InternalHigh = 0; 00079 _ov.OffsetHigh = (u32)(offset >> 32); 00080 _ov.Offset = (u32)offset; 00081 #else 00082 #error "TODO" 00083 #endif 00084 _callback = callback; 00085 } 00086 00087 public: 00088 static CAT_INLINE u32 OVERHEAD() { return (u32)(offsetof(AsyncBuffer, _tag)); } 00089 00090 CAT_INLINE AsyncOv *GetOv() { return &_ov; } 00091 CAT_INLINE u64 GetOffset() { return ((u64)_ov.OffsetHigh << 32) | _ov.Offset; } 00092 00093 CAT_INLINE bool Call(ThreadPoolLocalStorage *tls, int error, AsyncBuffer *buffer, u32 bytes) 00094 { 00095 if (!_callback) return true; 00096 return _callback(tls, error, buffer, bytes); 00097 } 00098 00099 CAT_INLINE void Zero() 00100 { 00101 CAT_CLR(_data, _data_bytes); 00102 } 00103 00104 public: 00105 CAT_INLINE u32 GetDataBytes() { return _data_bytes; } 00106 00107 CAT_INLINE u8 *GetData() { return reinterpret_cast<u8*>( _data ); } 00108 00109 template<class T> 00110 CAT_INLINE T *GetData() { return reinterpret_cast<T*>( _data ); } 00111 00112 template<class T> 00113 CAT_INLINE T *GetData(T * &ptr) { return (ptr = reinterpret_cast<T*>( _data )); } 00114 00115 public: 00116 CAT_INLINE u32 GetTagBytes() { return _tag_bytes; } 00117 00118 CAT_INLINE u8 *GetTagData() { return _tag; } 00119 00120 template<class T> 00121 CAT_INLINE T *GetTag() { return reinterpret_cast<T*>( _tag ); } 00122 00123 template<class T> 00124 CAT_INLINE T *GetTag(T * &ptr) { return (ptr = reinterpret_cast<T*>( _tag )); } 00125 00126 public: 00127 // Acquire with built-in data pointer 00128 static CAT_INLINE AsyncBuffer *Acquire(AsyncBuffer * &ptr, u32 data_bytes = 0, u32 tag_bytes = 0) 00129 { 00130 const u32 OVERHEAD_BYTES = (u32)(offsetof(AsyncBuffer, _tag)); 00131 00132 AsyncBuffer *buffer = reinterpret_cast<AsyncBuffer*>( 00133 RegionAllocator::ii->Acquire(OVERHEAD_BYTES + data_bytes + tag_bytes) ); 00134 00135 if (!buffer) return 0; 00136 00137 buffer->_data_bytes = data_bytes; 00138 buffer->_tag_bytes = tag_bytes; 00139 buffer->_data = buffer->_tag + tag_bytes; 00140 00141 return (ptr = buffer); 00142 } 00143 00144 // Change number of data bytes allocated to the buffer 00145 // Returns a new data pointer that may be different from the old data pointer 00146 CAT_INLINE AsyncBuffer *Resize(u32 data_bytes) 00147 { 00148 const u32 OVERHEAD_BYTES = (u32)(offsetof(AsyncBuffer, _tag)); 00149 00150 AsyncBuffer *buffer = reinterpret_cast<AsyncBuffer*>( 00151 RegionAllocator::ii->Resize( this, 00152 OVERHEAD_BYTES + _tag_bytes + data_bytes) ); 00153 00154 if (!buffer) return 0; 00155 00156 buffer->_data_bytes = data_bytes; 00157 buffer->_data = buffer->_tag + buffer->_tag_bytes; 00158 00159 return buffer; 00160 } 00161 00162 public: 00163 // Acquire with built-in data pointer 00164 static CAT_INLINE u8 *Acquire(u32 data_bytes = 0, u32 tag_bytes = 0) 00165 { 00166 AsyncBuffer *buffer; 00167 00168 if (!Acquire(buffer, data_bytes, tag_bytes)) return 0; 00169 00170 return buffer->_data; 00171 } 00172 00173 // Acquire with built-in data pointer 00174 template<class T> 00175 static CAT_INLINE T *Acquire(T * &data, u32 tag_bytes = 0) 00176 { 00177 AsyncBuffer *buffer; 00178 00179 if (!Acquire(buffer, sizeof(T), tag_bytes)) return 0; 00180 00181 return (data = reinterpret_cast<T*>( buffer->_data )); 00182 } 00183 00184 // Change number of data bytes allocated to the buffer 00185 // Returns a new data pointer that may be different from the old data pointer 00186 static CAT_INLINE u8 *Resize(void *vdata, u32 data_bytes) 00187 { 00188 u8 *data = reinterpret_cast<u8*>( vdata ); 00189 const u32 OVERHEAD_BYTES = (u32)(offsetof(AsyncBuffer, _tag)); 00190 00191 if (!data) return Acquire(data_bytes); 00192 00193 AsyncBuffer *buffer = reinterpret_cast<AsyncBuffer*>( data - OVERHEAD_BYTES ); 00194 00195 buffer = reinterpret_cast<AsyncBuffer*>( 00196 RegionAllocator::ii->Resize(buffer, 00197 OVERHEAD_BYTES + buffer->_tag_bytes + data_bytes) ); 00198 00199 if (!buffer) return 0; 00200 00201 buffer->_data_bytes = data_bytes; 00202 00203 return (buffer->_data = buffer->_tag + buffer->_tag_bytes); 00204 } 00205 00206 public: 00207 // Wrap external data pointer 00208 static CAT_INLINE AsyncBuffer *Wrap(void *vdata, u32 data_bytes, u32 tag_bytes = 0) 00209 { 00210 u8 *data = reinterpret_cast<u8*>( vdata ); 00211 const u32 OVERHEAD_BYTES = (u32)(offsetof(AsyncBuffer, _tag)); 00212 00213 AsyncBuffer *buffer = reinterpret_cast<AsyncBuffer*>( 00214 RegionAllocator::ii->Acquire(OVERHEAD_BYTES + tag_bytes) ); 00215 00216 if (!buffer) return 0; 00217 00218 buffer->_data_bytes = data_bytes; 00219 buffer->_tag_bytes = tag_bytes; 00220 buffer->_data = data; 00221 return buffer; 00222 } 00223 00224 public: 00225 // Only works on Acquired() buffers, not Wrap()ed buffers 00226 static CAT_INLINE AsyncBuffer *Promote(void *vdata) 00227 { 00228 u8 *data = reinterpret_cast<u8*>( vdata ); 00229 const u32 OVERHEAD_BYTES = (u32)(offsetof(AsyncBuffer, _tag)); 00230 00231 if (!data) return 0; 00232 return reinterpret_cast<AsyncBuffer*>( data - OVERHEAD_BYTES ); 00233 } 00234 00235 public: 00236 // Release memory 00237 CAT_INLINE void Release() 00238 { 00239 RegionAllocator::ii->Release(this); 00240 } 00241 static CAT_INLINE void Release(AsyncBuffer *buffer) 00242 { 00243 RegionAllocator::ii->Release(buffer); 00244 } 00245 static CAT_INLINE void Release(void *vdata) 00246 { 00247 u8 *data = reinterpret_cast<u8*>( vdata ); 00248 const u32 OVERHEAD_BYTES = (u32)(offsetof(AsyncBuffer, _tag)); 00249 00250 if (!data) return; 00251 00252 AsyncBuffer *buffer = reinterpret_cast<AsyncBuffer*>( data - OVERHEAD_BYTES ); 00253 00254 RegionAllocator::ii->Release(buffer); 00255 } 00256 }; 00257 00258 00259 } // namespace cat 00260 00261 #endif // CAT_ASYNC_BUFFER_HPP
Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.