allsensors
Fork of C027_Support by
Embed:
(wiki syntax)
Show/hide line numbers
Pipe.h
00001 #pragma once 00002 00003 /** pipe, this class implements a buffered pipe that can be savely 00004 written and read between two context. E.g. Written from a task 00005 and read from a interrupt. 00006 */ 00007 template <class T> 00008 class Pipe 00009 { 00010 public: 00011 /* Constructor 00012 \param n size of the pipe/buffer 00013 \param b optional buffer that should be used. 00014 if NULL the constructor will allocate a buffer of size n. 00015 */ 00016 Pipe(int n, T* b = NULL) 00017 { 00018 _a = b ? NULL : n ? new T[n] : NULL; 00019 _r = 0; 00020 _w = 0; 00021 _b = b ? b : _a; 00022 _s = n; 00023 } 00024 /** Destructor 00025 frees a allocated buffer. 00026 */ 00027 ~Pipe(void) 00028 { 00029 if (_a) 00030 delete [] _a; 00031 } 00032 00033 /* This function can be used during debugging to hexdump the 00034 content of a buffer to the stdout. 00035 */ 00036 void dump(void) 00037 { 00038 int o = _r; 00039 printf("pipe: %d/%d ", size(), _s); 00040 while (o != _w) { 00041 T t = _b[o]; 00042 printf("%0*X", sizeof(T)*2, t); 00043 o = _inc(o); 00044 } 00045 printf("\n"); 00046 } 00047 00048 // writing thread/context API 00049 //------------------------------------------------------------- 00050 00051 /** Check if buffer is writeable (=not full) 00052 \return true if writeable 00053 */ 00054 bool writeable(void) 00055 { 00056 return free() > 0; 00057 } 00058 00059 /** Return the number of free elements in the buffer 00060 \return the number of free elements 00061 */ 00062 int free(void) 00063 { 00064 int s = _r - _w; 00065 if (s <= 0) 00066 s += _s; 00067 return s - 1; 00068 } 00069 00070 /* Add a single element to the buffer. (blocking) 00071 \param c the element to add. 00072 \return c 00073 */ 00074 T putc(T c) 00075 { 00076 int i = _w; 00077 int j = i; 00078 i = _inc(i); 00079 while (i == _r) // = !writeable() 00080 /* nothing / just wait */; 00081 _b[j] = c; 00082 _w = i; 00083 return c; 00084 } 00085 00086 /* Add a buffer of elements to the buffer. 00087 \param p the elements to add 00088 \param n the number elements to add from p 00089 \param t set to true if blocking, false otherwise 00090 \return number elements added 00091 */ 00092 int put(const T* p, int n, bool t = false) 00093 { 00094 int c = n; 00095 while (c) 00096 { 00097 int f; 00098 for (;;) // wait for space 00099 { 00100 f = free(); 00101 if (f > 0) break; // data avail 00102 if (!t) return n - c; // no more space and not blocking 00103 /* nothing / just wait */; 00104 } 00105 // check free space 00106 if (c < f) f = c; 00107 int w = _w; 00108 int m = _s - w; 00109 // check wrap 00110 if (f > m) f = m; 00111 memcpy(&_b[w], p, f); 00112 _w = _inc(w, f); 00113 c -= f; 00114 p += f; 00115 } 00116 return n - c; 00117 } 00118 00119 // reading thread/context API 00120 // -------------------------------------------------------- 00121 00122 /** Check if there are any emelemnt available (readble / not empty) 00123 \return true if readable/not empty 00124 */ 00125 bool readable(void) 00126 { 00127 return (_r != _w); 00128 } 00129 00130 /** Get the number of values available in the buffer 00131 return the number of element available 00132 */ 00133 int size(void) 00134 { 00135 int s = _w - _r; 00136 if (s < 0) 00137 s += _s; 00138 return s; 00139 } 00140 00141 /** get a single value from buffered pipe (this function will block if no values available) 00142 \return the element extracted 00143 */ 00144 T getc(void) 00145 { 00146 int r = _r; 00147 while (r == _w) // = !readable() 00148 /* nothing / just wait */; 00149 T t = _b[r]; 00150 _r = _inc(r); 00151 return t; 00152 } 00153 00154 /*! get elements from the buffered pipe 00155 \param p the elements extracted 00156 \param n the maximum number elements to extract 00157 \param t set to true if blocking, false otherwise 00158 \return number elements extracted 00159 */ 00160 int get(T* p, int n, bool t = false) 00161 { 00162 int c = n; 00163 while (c) 00164 { 00165 int f; 00166 for (;;) // wait for data 00167 { 00168 f = size(); 00169 if (f) break; // free space 00170 if (!t) return n - c; // no space and not blocking 00171 /* nothing / just wait */; 00172 } 00173 // check available data 00174 if (c < f) f = c; 00175 int r = _r; 00176 int m = _s - r; 00177 // check wrap 00178 if (f > m) f = m; 00179 memcpy(p, &_b[r], f); 00180 _r = _inc(r, f); 00181 c -= f; 00182 p += f; 00183 } 00184 return n - c; 00185 } 00186 00187 // the following functions are useful if you like to inspect 00188 // or parse the buffer in the reading thread/context 00189 // -------------------------------------------------------- 00190 00191 /** set the parsing index and return the number of available 00192 elments starting this position. 00193 \param ix the index to set. 00194 \return the number of elements starting at this position 00195 */ 00196 int set(int ix) 00197 { 00198 int sz = size(); 00199 ix = (ix > sz) ? sz : ix; 00200 _o = _inc(_r, ix); 00201 return sz - ix; 00202 } 00203 00204 /** get the next element from parsing position and increment parsing index 00205 \return the extracted element. 00206 */ 00207 T next(void) 00208 { 00209 int o = _o; 00210 T t = _b[o]; 00211 _o = _inc(o); 00212 return t; 00213 } 00214 00215 /** commit the index, mark the current parsing index as consumed data. 00216 */ 00217 void done(void) 00218 { 00219 _r = _o; 00220 } 00221 00222 private: 00223 /** increment the index 00224 \param i index to increment 00225 \param n the step to increment 00226 \return the incremented index. 00227 */ 00228 inline int _inc(int i, int n = 1) 00229 { 00230 i += n; 00231 if (i >= _s) 00232 i -= _s; 00233 return i; 00234 } 00235 00236 T* _b; //!< buffer 00237 T* _a; //!< allocated buffer 00238 int _s; //!< size of buffer (s - 1) elements can be stored 00239 volatile int _w; //!< write index 00240 volatile int _r; //!< read index 00241 int _o; //!< offest index used by parsing functions 00242 };
Generated on Wed Jul 13 2022 00:19:01 by 1.7.2