00001
#ifndef RAGE_UTIL_CIRCULAR_BUFFER
00002
#define RAGE_UTIL_CIRCULAR_BUFFER
00003
00004
00005
00006
template<
class T>
00007 class CircBuf
00008 {
00009 T *buf;
00010
00011
00012
00013
00014
00015
00016
00017 unsigned size;
00018
00019
00020 volatile unsigned read_pos, write_pos;
00021
00022
public:
00023 CircBuf()
00024 {
00025 buf = NULL;
00026
clear();
00027 }
00028
00029 ~CircBuf()
00030 {
00031
delete[] buf;
00032 }
00033
00034
00035 unsigned num_readable()
const
00036
{
00037
const int rpos = read_pos;
00038
const int wpos = write_pos;
00039
if( rpos < wpos )
00040
00041
return wpos - rpos;
00042
else if( rpos > wpos )
00043
00044
return size - (rpos - wpos);
00045
else
00046
00047
return 0;
00048 }
00049
00050
00051
00052 unsigned num_writable()
const
00053
{
00054
const int rpos = read_pos;
00055
const int wpos = write_pos;
00056
00057
int ret;
00058
if( rpos < wpos )
00059
00060 ret = size - (wpos - rpos);
00061
else if( rpos > wpos )
00062
00063 ret = rpos - wpos;
00064
else
00065
00066 ret = size;
00067
00068
00069
return ret - 1;
00070 }
00071
00072 unsigned capacity()
const {
return size; }
00073
00074 void reserve(
unsigned n )
00075 {
00076
clear();
00077
delete[] buf;
00078 buf = NULL;
00079
00080
00081
00082
00083
if( n != 0 )
00084 {
00085 buf =
new T[n+1];
00086 size = n+1;
00087 }
00088
else
00089 size = 0;
00090 }
00091
00092 void clear()
00093 {
00094 read_pos = write_pos = 0;
00095 }
00096
00097
00098 void advance_write_pointer(
int n )
00099 {
00100 write_pos = (write_pos + n) % size;
00101 }
00102
00103
00104 void advance_read_pointer(
int n )
00105 {
00106 read_pos = (read_pos + n) % size;
00107 }
00108
00109 void get_write_pointers( T *pPointers[2],
unsigned pSizes[2] )
00110 {
00111
const int rpos = read_pos;
00112
const int wpos = write_pos;
00113
00114
if( rpos <= wpos )
00115 {
00116
00117 pPointers[0] = buf+wpos;
00118 pPointers[1] = buf;
00119
00120 pSizes[0] = size - wpos;
00121 pSizes[1] = rpos;
00122 }
00123
else if( rpos > wpos )
00124 {
00125
00126 pPointers[0] = buf+wpos;
00127 pPointers[1] = NULL;
00128
00129 pSizes[0] = rpos - wpos;
00130 pSizes[1] = 0;
00131 }
00132
00133
00134
if( pSizes[1] )
00135 --pSizes[1];
00136
else
00137 --pSizes[0];
00138 }
00139
00140 void get_read_pointers( T *pPointers[2],
unsigned pSizes[2] )
00141 {
00142
const int rpos = read_pos;
00143
const int wpos = write_pos;
00144
00145
if( rpos < wpos )
00146 {
00147
00148 pPointers[0] = buf+rpos;
00149 pPointers[1] = NULL;
00150
00151 pSizes[0] = wpos - rpos;
00152 pSizes[1] = 0;
00153 }
00154
else if( rpos > wpos )
00155 {
00156
00157 pPointers[0] = buf+rpos;
00158 pPointers[1] = buf;
00159
00160 pSizes[0] = size - rpos;
00161 pSizes[1] = wpos;
00162 }
00163
else
00164 {
00165
00166 pPointers[0] = NULL;
00167 pPointers[1] = NULL;
00168
00169 pSizes[0] = 0;
00170 pSizes[1] = 0;
00171 }
00172 }
00173
00174
00175
00176
00177 bool write(
const T *buffer,
unsigned buffer_size )
00178 {
00179
T *p[2];
00180
unsigned sizes[2];
00181 get_write_pointers( p, sizes );
00182
00183
if( buffer_size > sizes[0] + sizes[1] )
00184
return false;
00185
00186
const int from_first =
min( buffer_size, sizes[0] );
00187 memcpy( p[0], buffer, from_first*
sizeof(
T) );
00188
if( buffer_size > sizes[0] )
00189 memcpy( p[1], buffer+from_first,
max(buffer_size-sizes[0], 0u)*
sizeof(
T) );
00190
00191 advance_write_pointer( buffer_size );
00192
00193
return true;
00194 }
00195
00196
00197
00198
00199 bool read( T *buffer,
unsigned buffer_size )
00200 {
00201
T *p[2];
00202
unsigned sizes[2];
00203 get_read_pointers( p, sizes );
00204
00205
if( buffer_size > sizes[0] + sizes[1] )
00206
return false;
00207
00208
const int from_first =
min( buffer_size, sizes[0] );
00209 memcpy( buffer, p[0], from_first*
sizeof(
T) );
00210
if( buffer_size > sizes[0] )
00211 memcpy( buffer+from_first, p[1],
max(buffer_size-sizes[0], 0u)*
sizeof(
T) );
00212
00213
00214
00215 memset( p[0], 0xFF, from_first*
sizeof(
T) );
00216
if( buffer_size > sizes[0] )
00217 memset( p[1], 0xFF,
max(buffer_size-sizes[0], 0u)*
sizeof(
T) );
00218
00219 advance_read_pointer( buffer_size );
00220
return true;
00221 }
00222 };
00223
00224
#endif
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249