| /** @file | 
 |  | 
 |   A brief file description | 
 |  | 
 |   @section license License | 
 |  | 
 |   Licensed to the Apache Software Foundation (ASF) under one | 
 |   or more contributor license agreements.  See the NOTICE file | 
 |   distributed with this work for additional information | 
 |   regarding copyright ownership.  The ASF licenses this file | 
 |   to you 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. | 
 |  */ | 
 |  | 
 | #ifndef __ABSTRACT_BUFFER_H__ | 
 | #define __ABSTRACT_BUFFER_H__ | 
 |  | 
 |  | 
 | #include "inktomi++.h" | 
 |  | 
 |  | 
 | enum ABError | 
 | { | 
 |   AB_ERROR_OK, | 
 |   AB_ERROR_BUSY, | 
 |   AB_ERROR_STATE, | 
 |   AB_ERROR_FULL, | 
 |   AB_ERROR_OFFSET | 
 | }; | 
 |  | 
 |  | 
 | class AbstractBuffer | 
 | { | 
 | public: | 
 |   enum AbstractBufferState | 
 |   { | 
 |     AB_STATE_UNUSED, | 
 |     AB_STATE_INITIALIZING, | 
 |     AB_STATE_READ_WRITE, | 
 |     AB_STATE_READ_ONLY, | 
 |     AB_STATE_FLUSH, | 
 |     AB_STATE_FLUSH_COMPLETE | 
 |   }; | 
 |  | 
 | protected: | 
 |   union VolatileState | 
 |   { | 
 |     VolatileState() | 
 |     { | 
 |       ival = 0; | 
 |     } | 
 |  | 
 |     VolatileState(volatile VolatileState & vs) | 
 |     { | 
 |       ival = vs.ival; | 
 |     } | 
 |  | 
 |     VolatileState & operator =(volatile VolatileState & vs) | 
 |     { | 
 |       ival = vs.ival; | 
 |       return *this; | 
 |     } | 
 |  | 
 |     int64 ival; | 
 |     struct | 
 |     { | 
 |       uint16 reader_count; | 
 |       uint16 writer_count; | 
 |       uint32 offset:29; | 
 |       uint32 state:3; | 
 |     } s; | 
 |   }; | 
 |  | 
 | public: | 
 |   AbstractBuffer(int xsize, int xalignment) | 
 |   : buffer(NULL), unaligned_buffer(NULL), size(xsize), alignment(xalignment) | 
 |   { | 
 |     clear(); | 
 |   } | 
 |   virtual ~ AbstractBuffer() { | 
 |     clear(); | 
 |   } | 
 |  | 
 |   char *data() | 
 |   { | 
 |     return buffer; | 
 |   } | 
 |   char &operator [] (int idx) | 
 |   { | 
 |     ink_assert(idx >= 0); | 
 |     ink_assert(idx < size); | 
 |     return buffer[idx]; | 
 |   } | 
 |   int offset() | 
 |   { | 
 |     return vs.s.offset; | 
 |   } | 
 |  | 
 |   virtual ABError checkout_write(int *write_offset, int write_size, uint64 retries = (uint64) - 1); | 
 |   virtual ABError checkout_read(int read_offset, int read_size); | 
 |   virtual ABError checkin_write(int write_offset); | 
 |   virtual ABError checkin_read(int read_offset); | 
 |  | 
 |   virtual void initialize(); | 
 |   virtual void full(); | 
 |   virtual void flush(); | 
 |   virtual void flush_complete(); | 
 |   virtual void destroy(); | 
 |   virtual void clear(); | 
 |  | 
 |   bool switch_state(VolatileState & old_state, VolatileState & new_state); | 
 |  | 
 | public: | 
 |   volatile VolatileState vs; | 
 |   char *buffer; | 
 |   char *unaligned_buffer; | 
 |   int size; | 
 |   int alignment; | 
 |  | 
 | public: | 
 |   VolatileState vs_history[AB_STATE_FLUSH_COMPLETE + 1]; | 
 | }; | 
 |  | 
 |  | 
 | class AbstractBufferReader | 
 | { | 
 | public: | 
 |   AbstractBufferReader(AbstractBuffer * xbuffer, int xoffset) | 
 |   : buffer(xbuffer), offset(xoffset) | 
 |   { | 
 |   } | 
 |  | 
 |    ~AbstractBufferReader() | 
 |   { | 
 |     buffer->checkin_read(offset); | 
 |   } | 
 |  | 
 | private: | 
 |   AbstractBuffer * buffer; | 
 |   int offset; | 
 | }; | 
 |  | 
 |  | 
 | class AbstractBufferWriter | 
 | { | 
 | public: | 
 |   AbstractBufferWriter(AbstractBuffer * xbuffer, int xoffset) | 
 |   : buffer(xbuffer), offset(xoffset) | 
 |   { | 
 |   } | 
 |  | 
 |    ~AbstractBufferWriter() | 
 |   { | 
 |     buffer->checkin_write(offset); | 
 |   } | 
 |  | 
 | private: | 
 |   AbstractBuffer * buffer; | 
 |   int offset; | 
 | }; | 
 |  | 
 | /*------------------------------------------------------------------------- | 
 |   -------------------------------------------------------------------------*/ | 
 |  | 
 | inline bool | 
 | AbstractBuffer::switch_state(VolatileState & old_vs, VolatileState & new_vs) | 
 | { | 
 |   if (ink_atomic_cas64((int64 *) & vs.ival, old_vs.ival, new_vs.ival)) { | 
 |     return true; | 
 |   } | 
 |  | 
 |   return false; | 
 | } | 
 |  | 
 | #endif /* __ABSTRACT_BUFFER_H__ */ |