Imported Upstream version 3.0
[debian/gnuradio] / gnuradio-core / src / lib / runtime / gr_buffer.h
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2004 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #ifndef INCLUDED_GR_BUFFER_H
24 #define INCLUDED_GR_BUFFER_H
25
26 #include <gr_runtime.h>
27
28 class gr_vmcircbuf;
29
30 /*!
31  * \brief Allocate a buffer that holds at least \p nitems of size \p sizeof_item.
32  *
33  * The total size of the buffer will be rounded up to a system
34  * dependent boundary.  This is typically the system page size, but
35  * under MS windows is 64KB.
36  */
37 gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item);
38
39
40 /*!
41  * \brief Single writer, multiple reader fifo.
42  * \ingroup internal
43  */
44 class gr_buffer {
45  public:
46   virtual ~gr_buffer ();
47
48   /*!
49    * \brief return number of items worth of space available for writing
50    */
51   int space_available () const;
52
53   /*!
54    * \brief return pointer to write buffer.
55    *
56    * The return value points at space that can hold at least
57    * space_available() items.
58    */
59   void *write_pointer ();
60
61   /*!
62    * \brief tell buffer that we wrote \p nitems into it
63    */
64   void update_write_pointer (int nitems);
65
66
67   void set_done (bool done)   { d_done = done; }
68   bool done () const { return d_done; }
69
70   // -------------------------------------------------------------------------
71
72  private:
73
74   friend class gr_buffer_reader;
75   friend gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item);
76   friend gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload);
77
78  protected:
79   char                                 *d_base;         // base address of buffer
80   unsigned int                          d_bufsize;      // in items
81  private:
82   gr_vmcircbuf                         *d_vmcircbuf;
83   size_t                                d_sizeof_item;  // in bytes
84   unsigned int                          d_write_index;  // in items [0,d_bufsize)
85   std::vector<gr_buffer_reader *>       d_readers;
86   bool                                  d_done;
87   
88   unsigned
89   index_add (unsigned a, unsigned b)
90   {
91     unsigned s = a + b;
92
93     if (s >= d_bufsize)
94       s -= d_bufsize;
95
96     assert (s < d_bufsize);
97     return s;
98   }
99
100   unsigned
101   index_sub (unsigned a, unsigned b)
102   {
103     int s = a - b;
104
105     if (s < 0)
106       s += d_bufsize;
107
108     assert ((unsigned) s < d_bufsize);
109     return s;
110   }
111
112   virtual bool allocate_buffer (int nitems, size_t sizeof_item);
113
114   /*!
115    * \brief constructor is private.  Use gr_make_buffer to create instances.
116    *
117    * Allocate a buffer that holds at least \p nitems of size \p sizeof_item.
118    *
119    * The total size of the buffer will be rounded up to a system
120    * dependent boundary.  This is typically the system page size, but
121    * under MS windows is 64KB.
122    */
123   gr_buffer (int nitems, size_t sizeof_item);
124
125   /*!
126    * \brief disassociate \p reader from this buffer
127    */
128   void drop_reader (gr_buffer_reader *reader);
129
130 };
131
132 /*!
133  * \brief create a new gr_buffer_reader and attach it to buffer \p buf
134  * \param nzero_preload -- number of zero items to "preload" into buffer.
135  */
136 gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload);
137
138 //! returns # of gr_buffers currently allocated
139 long gr_buffer_ncurrently_allocated ();
140
141
142 // ---------------------------------------------------------------------------
143
144 /*!
145  * \brief How we keep track of the readers of a gr_buffer.
146  * \ingroup internal
147  */
148
149 class gr_buffer_reader {
150
151  public:
152   ~gr_buffer_reader ();
153
154   /*!
155    * \brief Return number of items available for reading.
156    */
157   int items_available () const;
158
159   /*!
160    * \brief Return maximum number of items that could ever be available for reading.
161    * This is used as a sanity check in the scheduler to avoid looping forever.
162    */
163   int max_possible_items_available () const { return d_buffer->d_bufsize - 1; }
164
165   /*!
166    * \brief return pointer to read buffer.
167    *
168    * The return value points to items_available() number of items
169    */
170   const void *read_pointer ();
171
172   /*
173    * \brief tell buffer we read \p items from it
174    */
175   void update_read_pointer (int nitems);
176
177   void set_done (bool done)   { d_buffer->set_done (done); }
178   bool done () const { return d_buffer->done (); }
179
180   // -------------------------------------------------------------------------
181
182  private:
183
184   friend class gr_buffer;
185   friend gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload);
186
187
188   gr_buffer_sptr                d_buffer;
189   unsigned int                  d_read_index;   // in items [0,d->buffer.d_bufsize)
190
191   //! constructor is private.  Use gr_buffer::add_reader to create instances
192   gr_buffer_reader (gr_buffer_sptr buffer, unsigned int read_index);
193 };
194
195 //! returns # of gr_buffer_readers currently allocated
196 long gr_buffer_reader_ncurrently_allocated ();
197
198
199 #endif /* INCLUDED_GR_BUFFER_H */