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 }