00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef ringbuffer_npt_h
00022 #define ringbuffer_npt_h
00023
00024 #include <stdio.h>
00025
00026 #if ! defined (Q_WS_WIN)
00027 #include <sys/mman.h>
00028 #endif
00029
00030 #include "defines.h"
00031
00032
00033
00034 template<class T>
00035 class RingBufferNPT
00036 {
00037 public:
00038 RingBufferNPT (size_t sz) {
00039 size = sz;
00040 buf = new T[size];
00041 #ifdef USE_MLOCK
00042 if (mlock (buf, size)) {
00043 printf("Unable to lock memory\n");
00044 }
00045 #endif
00046 reset ();
00047
00048 };
00049
00050 virtual ~RingBufferNPT() {
00051 #ifdef USE_MLOCK
00052 munlock (buf, size);
00053 #endif
00054 delete [] buf;
00055 }
00056
00057 void reset () {
00058
00059 t_atomic_int_set (&write_ptr, 0);
00060 t_atomic_int_set (&read_ptr, 0);
00061 }
00062
00063 void set (size_t r, size_t w) {
00064
00065 t_atomic_int_set (&write_ptr, w);
00066 t_atomic_int_set (&read_ptr, r);
00067 }
00068
00069 size_t read (T *dest, size_t cnt);
00070 size_t write (T *src, size_t cnt);
00071
00072 struct rw_vector {
00073 T *buf[2];
00074 size_t len[2];
00075 };
00076
00077 void get_read_vector (rw_vector *);
00078 void get_write_vector (rw_vector *);
00079
00080 void decrement_read_ptr (size_t cnt) {
00081 t_atomic_int_set (&read_ptr, (t_atomic_int_get(&read_ptr) - cnt) % size);
00082 }
00083
00084 void increment_read_ptr (size_t cnt) {
00085 t_atomic_int_set (&read_ptr, (t_atomic_int_get(&read_ptr) + cnt) % size);
00086 }
00087
00088 void increment_write_ptr (size_t cnt) {
00089 t_atomic_int_set (&write_ptr, (t_atomic_int_get(&write_ptr) + cnt) % size);
00090 }
00091
00092 size_t write_space () {
00093 size_t w, r;
00094
00095 w = t_atomic_int_get (&write_ptr);
00096 r = t_atomic_int_get (&read_ptr);
00097
00098 if (w > r) {
00099 return ((r - w + size) % size) - 1;
00100 } else if (w < r) {
00101 return (r - w) - 1;
00102 } else {
00103 return size - 1;
00104 }
00105 }
00106
00107 size_t read_space () {
00108 size_t w, r;
00109
00110 w = t_atomic_int_get (&write_ptr);
00111 r = t_atomic_int_get (&read_ptr);
00112
00113 if (w > r) {
00114 return w - r;
00115 } else {
00116 return (w - r + size) % size;
00117 }
00118 }
00119
00120 T *buffer () { return buf; }
00121 size_t get_write_ptr () const { return t_atomic_int_get (&write_ptr); }
00122 size_t get_read_ptr () const { return t_atomic_int_get (&read_ptr); }
00123 size_t bufsize () const { return size; }
00124
00125 protected:
00126 T *buf;
00127 size_t size;
00128 mutable volatile int write_ptr;
00129 mutable volatile int read_ptr;
00130 };
00131
00132 template<class T> size_t
00133 RingBufferNPT<T>::read (T *dest, size_t cnt)
00134 {
00135 size_t free_cnt;
00136 size_t cnt2;
00137 size_t to_read;
00138 size_t n1, n2;
00139 size_t priv_read_ptr;
00140
00141 priv_read_ptr=t_atomic_int_get(&read_ptr);
00142
00143 if ((free_cnt = read_space ()) == 0) {
00144 return 0;
00145 }
00146
00147 to_read = cnt > free_cnt ? free_cnt : cnt;
00148
00149 cnt2 = priv_read_ptr + to_read;
00150
00151 if (cnt2 > size) {
00152 n1 = size - priv_read_ptr;
00153 n2 = cnt2 % size;
00154 } else {
00155 n1 = to_read;
00156 n2 = 0;
00157 }
00158
00159 memcpy (dest, &buf[priv_read_ptr], n1 * sizeof (T));
00160 priv_read_ptr = (priv_read_ptr + n1) % size;
00161
00162 if (n2) {
00163 memcpy (dest+n1, buf, n2 * sizeof (T));
00164 priv_read_ptr = n2;
00165 }
00166
00167 t_atomic_int_set(&read_ptr, priv_read_ptr);
00168 return to_read;
00169 }
00170
00171 template<class T> size_t
00172 RingBufferNPT<T>::write (T *src, size_t cnt)
00173 {
00174 size_t free_cnt;
00175 size_t cnt2;
00176 size_t to_write;
00177 size_t n1, n2;
00178 size_t priv_write_ptr;
00179
00180 priv_write_ptr=t_atomic_int_get(&write_ptr);
00181
00182 if ((free_cnt = write_space ()) == 0) {
00183 return 0;
00184 }
00185
00186 to_write = cnt > free_cnt ? free_cnt : cnt;
00187
00188 cnt2 = priv_write_ptr + to_write;
00189
00190 if (cnt2 > size) {
00191 n1 = size - priv_write_ptr;
00192 n2 = cnt2 % size;
00193 } else {
00194 n1 = to_write;
00195 n2 = 0;
00196 }
00197
00198 memcpy (&buf[priv_write_ptr], src, n1 * sizeof (T));
00199 priv_write_ptr = (priv_write_ptr + n1) % size;
00200
00201 if (n2) {
00202 memcpy (buf, src+n1, n2 * sizeof (T));
00203 priv_write_ptr = n2;
00204 }
00205
00206 t_atomic_int_set(&write_ptr, priv_write_ptr);
00207 return to_write;
00208 }
00209
00210 template<class T> void
00211 RingBufferNPT<T>::get_read_vector (RingBufferNPT<T>::rw_vector *vec)
00212 {
00213 size_t free_cnt;
00214 size_t cnt2;
00215 size_t w, r;
00216
00217 w = t_atomic_int_get (&write_ptr);
00218 r = t_atomic_int_get (&read_ptr);
00219
00220 if (w > r) {
00221 free_cnt = w - r;
00222 } else {
00223 free_cnt = (w - r + size) % size;
00224 }
00225
00226 cnt2 = r + free_cnt;
00227
00228 if (cnt2 > size) {
00229
00230
00231
00232
00233
00234 vec->buf[0] = &buf[r];
00235 vec->len[0] = size - r;
00236 vec->buf[1] = buf;
00237 vec->len[1] = cnt2 % size;
00238
00239 } else {
00240
00241
00242
00243 vec->buf[0] = &buf[r];
00244 vec->len[0] = free_cnt;
00245 vec->len[1] = 0;
00246 }
00247 }
00248
00249 template<class T> void
00250 RingBufferNPT<T>::get_write_vector (RingBufferNPT<T>::rw_vector *vec)
00251 {
00252 size_t free_cnt;
00253 size_t cnt2;
00254 size_t w, r;
00255
00256 w = t_atomic_int_get (&write_ptr);
00257 r = t_atomic_int_get (&read_ptr);
00258
00259 if (w > r) {
00260 free_cnt = ((r - w + size) % size) - 1;
00261 } else if (w < r) {
00262 free_cnt = (r - w) - 1;
00263 } else {
00264 free_cnt = size - 1;
00265 }
00266
00267 cnt2 = w + free_cnt;
00268
00269 if (cnt2 > size) {
00270
00271
00272
00273
00274
00275
00276 vec->buf[0] = &buf[w];
00277 vec->len[0] = size - w;
00278 vec->buf[1] = buf;
00279 vec->len[1] = cnt2 % size;
00280 } else {
00281 vec->buf[0] = &buf[w];
00282 vec->len[0] = free_cnt;
00283 vec->len[1] = 0;
00284 }
00285 }
00286
00287 #endif