Shadowrun: Awakened 29 September 2011 - Build 871
AsyncBuffer.hpp
Go to the documentation of this file.
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.

GNU Lesser General Public License 3 Sourceforge.net