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