IM920地温観測システム用 cbUSB()関数定義だけ修正したもの

Fork of C027_Support by u-blox

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Pipe.h Source File

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 };