Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 #ifndef __ABSTRACT_BUFFER_H__
00025 #define __ABSTRACT_BUFFER_H__
00026 
00027 
00028 #include "libts.h"
00029 
00030 
00031 enum ABError
00032 {
00033   AB_ERROR_OK,
00034   AB_ERROR_BUSY,
00035   AB_ERROR_STATE,
00036   AB_ERROR_FULL,
00037   AB_ERROR_OFFSET
00038 };
00039 
00040 
00041 class AbstractBuffer
00042 {
00043 public:
00044   enum AbstractBufferState
00045   {
00046     AB_STATE_UNUSED,
00047     AB_STATE_INITIALIZING,
00048     AB_STATE_READ_WRITE,
00049     AB_STATE_READ_ONLY,
00050     AB_STATE_FLUSH,
00051     AB_STATE_FLUSH_COMPLETE
00052   };
00053 
00054 protected:
00055   union VolatileState
00056   {
00057     VolatileState()
00058     {
00059       ival = 0;
00060     }
00061 
00062     VolatileState(volatile VolatileState & vs)
00063     {
00064       ival = vs.ival;
00065     }
00066 
00067     VolatileState & operator =(volatile VolatileState & vs)
00068     {
00069       ival = vs.ival;
00070       return *this;
00071     }
00072 
00073     int64_t ival;
00074     struct
00075     {
00076       uint16_t reader_count;
00077       uint16_t writer_count;
00078       uint32_t offset:29;
00079       uint32_t state:3;
00080     } s;
00081   };
00082 
00083 public:
00084   AbstractBuffer(int xsize, int xalignment)
00085   : buffer(NULL), unaligned_buffer(NULL), size(xsize), alignment(xalignment)
00086   {
00087     clear();
00088   }
00089   virtual ~ AbstractBuffer() {
00090     clear();
00091   }
00092 
00093   char *data()
00094   {
00095     return buffer;
00096   }
00097   char &operator [] (int idx)
00098   {
00099     ink_assert(idx >= 0);
00100     ink_assert(idx < size);
00101     return buffer[idx];
00102   }
00103   int offset()
00104   {
00105     return vs.s.offset;
00106   }
00107 
00108   virtual ABError checkout_write(int *write_offset, int write_size, uint64_t retries = (uint64_t) - 1);
00109   virtual ABError checkout_read(int read_offset, int read_size);
00110   virtual ABError checkin_write(int write_offset);
00111   virtual ABError checkin_read(int read_offset);
00112 
00113   virtual void initialize();
00114   virtual void full();
00115   virtual void flush();
00116   virtual void flush_complete();
00117   virtual void destroy();
00118   virtual void clear();
00119 
00120   bool switch_state(VolatileState & old_state, VolatileState & new_state);
00121 
00122 public:
00123   volatile VolatileState vs;
00124   char *buffer;
00125   char *unaligned_buffer;
00126   int size;
00127   int alignment;
00128 
00129 public:
00130   VolatileState vs_history[AB_STATE_FLUSH_COMPLETE + 1];
00131 };
00132 
00133 
00134 class AbstractBufferReader
00135 {
00136 public:
00137   AbstractBufferReader(AbstractBuffer * xbuffer, int xoffset)
00138   : buffer(xbuffer), offset(xoffset)
00139   {
00140   }
00141 
00142    ~AbstractBufferReader()
00143   {
00144     buffer->checkin_read(offset);
00145   }
00146 
00147 private:
00148   AbstractBuffer * buffer;
00149   int offset;
00150 };
00151 
00152 
00153 class AbstractBufferWriter
00154 {
00155 public:
00156   AbstractBufferWriter(AbstractBuffer * xbuffer, int xoffset)
00157   : buffer(xbuffer), offset(xoffset)
00158   {
00159   }
00160 
00161    ~AbstractBufferWriter()
00162   {
00163     buffer->checkin_write(offset);
00164   }
00165 
00166 private:
00167   AbstractBuffer * buffer;
00168   int offset;
00169 };
00170 
00171 
00172 
00173 
00174 inline bool
00175 AbstractBuffer::switch_state(VolatileState & old_vs, VolatileState & new_vs)
00176 {
00177   if (ink_atomic_cas((int64_t *) & vs.ival, old_vs.ival, new_vs.ival)) {
00178     return true;
00179   }
00180 
00181   return false;
00182 }
00183 
00184 #endif