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 #include "ink_config.h"
00025 #include <assert.h>
00026 #include <string.h>
00027 #include "AbstractBuffer.h"
00028
00029 #include "ink_align.h"
00030
00031
00032
00033
00034
00035 ABError AbstractBuffer::checkout_write(int *write_offset, int write_size, uint64_t retries)
00036 {
00037 VolatileState
00038 old_vs;
00039 VolatileState
00040 new_vs;
00041
00042 write_size = INK_ALIGN(write_size, alignment);
00043
00044
00045 old_vs = vs;
00046 new_vs = old_vs;
00047
00048 if (new_vs.s.state == AB_STATE_UNUSED) {
00049 new_vs.s.state = AB_STATE_INITIALIZING;
00050 if (switch_state(old_vs, new_vs)) {
00051 vs_history[AB_STATE_INITIALIZING] = old_vs;
00052 initialize();
00053 }
00054 }
00055
00056 while (retries-- > 0) {
00057 old_vs = vs;
00058 new_vs = old_vs;
00059
00060 if (new_vs.s.state != AB_STATE_READ_WRITE) {
00061 return AB_ERROR_STATE;
00062 }
00063
00064 if ((uint32_t) (new_vs.s.offset + write_size) > (uint32_t) size) {
00065 new_vs.s.state = AB_STATE_READ_ONLY;
00066 if (switch_state(old_vs, new_vs)) {
00067 vs_history[AB_STATE_READ_ONLY] = old_vs;
00068 full();
00069 }
00070 return AB_ERROR_FULL;
00071 }
00072
00073 *write_offset = new_vs.s.offset;
00074 new_vs.s.offset += write_size;
00075 new_vs.s.writer_count += 1;
00076
00077 if (switch_state(old_vs, new_vs)) {
00078 ink_assert((*write_offset + write_size) <= size);
00079 return AB_ERROR_OK;
00080 }
00081 }
00082
00083 return AB_ERROR_BUSY;
00084 }
00085
00086
00087
00088
00089 ABError AbstractBuffer::checkout_read(int read_offset, int read_size)
00090 {
00091 VolatileState
00092 old_vs;
00093 VolatileState
00094 new_vs;
00095
00096 do {
00097 old_vs = vs;
00098 new_vs = old_vs;
00099
00100 if ((new_vs.s.state != AB_STATE_READ_WRITE) &&
00101 (new_vs.s.state != AB_STATE_READ_ONLY) && (new_vs.s.state != AB_STATE_FLUSH)) {
00102 return AB_ERROR_STATE;
00103 }
00104
00105 if ((uint32_t) (read_offset + read_size) > new_vs.s.offset) {
00106 return AB_ERROR_OFFSET;
00107 }
00108
00109 new_vs.s.reader_count += 1;
00110 } while (!switch_state(old_vs, new_vs));
00111
00112 return AB_ERROR_OK;
00113 }
00114
00115
00116
00117
00118 ABError AbstractBuffer::checkin_write(int write_offset)
00119 {
00120 VolatileState
00121 old_vs;
00122 VolatileState
00123 new_vs;
00124
00125 do {
00126 old_vs = vs;
00127 new_vs = old_vs;
00128
00129 ink_assert(new_vs.s.writer_count > 0);
00130 ink_assert((new_vs.s.state == AB_STATE_READ_WRITE) || (new_vs.s.state == AB_STATE_READ_ONLY));
00131 ink_assert((uint32_t) write_offset < new_vs.s.offset);
00132
00133 new_vs.s.writer_count -= 1;
00134 } while (!switch_state(old_vs, new_vs));
00135
00136 old_vs = vs;
00137 new_vs = old_vs;
00138
00139 while ((new_vs.s.state == AB_STATE_READ_ONLY) && (new_vs.s.writer_count == 0)) {
00140 new_vs.s.state = AB_STATE_FLUSH;
00141 if (switch_state(old_vs, new_vs)) {
00142 vs_history[AB_STATE_FLUSH] = old_vs;
00143 flush();
00144 break;
00145 }
00146
00147 old_vs = vs;
00148 new_vs = old_vs;
00149 }
00150
00151 return AB_ERROR_OK;
00152 }
00153
00154
00155
00156
00157 ABError AbstractBuffer::checkin_read(int read_offset)
00158 {
00159 VolatileState
00160 old_vs;
00161 VolatileState
00162 new_vs;
00163
00164 do {
00165 old_vs = vs;
00166 new_vs = old_vs;
00167
00168 ink_assert(new_vs.s.reader_count > 0);
00169 ink_assert(new_vs.s.state != AB_STATE_UNUSED);
00170 ink_assert((uint32_t) read_offset < new_vs.s.offset);
00171
00172 new_vs.s.reader_count -= 1;
00173 } while (!switch_state(old_vs, new_vs));
00174
00175 if ((new_vs.s.state == AB_STATE_FLUSH_COMPLETE) && (new_vs.s.reader_count == 0)) {
00176 destroy();
00177 }
00178
00179 return AB_ERROR_OK;
00180 }
00181
00182
00183
00184
00185 void
00186 AbstractBuffer::initialize()
00187 {
00188 ink_assert(vs.s.state == AB_STATE_INITIALIZING);
00189 ink_assert(vs.s.writer_count == 0);
00190 ink_assert(vs.s.reader_count == 0);
00191
00192 if (!unaligned_buffer) {
00193 unaligned_buffer = new char[size + 511];
00194 buffer = (char *) align_pointer_forward(unaligned_buffer, 512);
00195 }
00196
00197 vs_history[AB_STATE_READ_WRITE] = vs;
00198
00199 vs.s.offset = 0;
00200 vs.s.state = AB_STATE_READ_WRITE;
00201 }
00202
00203
00204
00205
00206 void
00207 AbstractBuffer::full()
00208 {
00209 if ((vs.s.state == AB_STATE_READ_ONLY) && (vs.s.writer_count == 0)) {
00210 VolatileState old_vs(vs);
00211 VolatileState new_vs(old_vs);
00212
00213 while ((new_vs.s.state == AB_STATE_READ_ONLY) && (new_vs.s.writer_count == 0)) {
00214 new_vs.s.state = AB_STATE_FLUSH;
00215 if (switch_state(old_vs, new_vs)) {
00216 vs_history[AB_STATE_FLUSH] = old_vs;
00217 flush();
00218 break;
00219 }
00220
00221 old_vs = vs;
00222 new_vs = old_vs;
00223 }
00224 }
00225 }
00226
00227
00228
00229
00230 void
00231 AbstractBuffer::flush()
00232 {
00233 ink_assert(vs.s.state == AB_STATE_FLUSH);
00234 ink_assert(vs.s.writer_count == 0);
00235 }
00236
00237
00238
00239
00240 void
00241 AbstractBuffer::flush_complete()
00242 {
00243
00244 VolatileState old_vs;
00245 VolatileState new_vs;
00246
00247
00248
00249
00250
00251
00252 do {
00253 old_vs = vs;
00254 new_vs = old_vs;
00255
00256 ink_assert(vs.s.state == AB_STATE_FLUSH);
00257 ink_assert(vs.s.writer_count == 0);
00258 new_vs.s.state = AB_STATE_FLUSH_COMPLETE;
00259
00260 } while (!switch_state(old_vs, new_vs));
00261
00262 vs_history[AB_STATE_FLUSH_COMPLETE] = vs;
00263
00264 if (vs.s.reader_count == 0) {
00265 destroy();
00266 }
00267 }
00268
00269
00270
00271
00272 void
00273 AbstractBuffer::destroy()
00274 {
00275 ink_assert(vs.s.state == AB_STATE_FLUSH_COMPLETE);
00276 ink_assert(vs.s.writer_count == 0);
00277 ink_assert(vs.s.reader_count == 0);
00278
00279 vs_history[AB_STATE_UNUSED] = vs;
00280
00281 vs.s.offset = 0;
00282 vs.s.state = AB_STATE_UNUSED;
00283 }
00284
00285
00286
00287
00288 void
00289 AbstractBuffer::clear()
00290 {
00291 if (unaligned_buffer) {
00292 delete[]unaligned_buffer;
00293 }
00294 unaligned_buffer = buffer = NULL;
00295
00296 vs_history[AB_STATE_UNUSED] = vs;
00297
00298 vs.s.writer_count = 0;
00299 vs.s.reader_count = 0;
00300 vs.s.offset = 0;
00301 vs.s.state = AB_STATE_UNUSED;
00302 }