GNU Radio 3.3.0 C++ API
|
00001 /* -*- c++ -*- */ 00002 /* 00003 * Copyright 2004,2009 Free Software Foundation, Inc. 00004 * 00005 * This file is part of GNU Radio 00006 * 00007 * GNU Radio is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 3, or (at your option) 00010 * any later version. 00011 * 00012 * GNU Radio is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with GNU Radio; see the file COPYING. If not, write to 00019 * the Free Software Foundation, Inc., 51 Franklin Street, 00020 * Boston, MA 02110-1301, USA. 00021 */ 00022 00023 #ifndef INCLUDED_GR_BUFFER_H 00024 #define INCLUDED_GR_BUFFER_H 00025 00026 #include <gr_runtime_types.h> 00027 #include <boost/weak_ptr.hpp> 00028 #include <gruel/thread.h> 00029 00030 class gr_vmcircbuf; 00031 00032 /*! 00033 * \brief Allocate a buffer that holds at least \p nitems of size \p sizeof_item. 00034 * 00035 * The total size of the buffer will be rounded up to a system 00036 * dependent boundary. This is typically the system page size, but 00037 * under MS windows is 64KB. 00038 * 00039 * \param nitems is the minimum number of items the buffer will hold. 00040 * \param sizeof_item is the size of an item in bytes. 00041 * \param link is the block that writes to this buffer. 00042 */ 00043 gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item, gr_block_sptr link=gr_block_sptr()); 00044 00045 00046 /*! 00047 * \brief Single writer, multiple reader fifo. 00048 * \ingroup internal 00049 */ 00050 class gr_buffer { 00051 public: 00052 00053 virtual ~gr_buffer (); 00054 00055 /*! 00056 * \brief return number of items worth of space available for writing 00057 */ 00058 int space_available (); 00059 00060 /*! 00061 * \brief return size of this buffer in items 00062 */ 00063 int bufsize() const { return d_bufsize; } 00064 00065 /*! 00066 * \brief return pointer to write buffer. 00067 * 00068 * The return value points at space that can hold at least 00069 * space_available() items. 00070 */ 00071 void *write_pointer (); 00072 00073 /*! 00074 * \brief tell buffer that we wrote \p nitems into it 00075 */ 00076 void update_write_pointer (int nitems); 00077 00078 void set_done (bool done); 00079 bool done () const { return d_done; } 00080 00081 /*! 00082 * \brief Return the block that writes to this buffer. 00083 */ 00084 gr_block_sptr link() { return gr_block_sptr(d_link); } 00085 00086 size_t nreaders() const { return d_readers.size(); } 00087 gr_buffer_reader* reader(size_t index) { return d_readers[index]; } 00088 00089 gruel::mutex *mutex() { return &d_mutex; } 00090 00091 // ------------------------------------------------------------------------- 00092 00093 private: 00094 00095 friend class gr_buffer_reader; 00096 friend gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item, gr_block_sptr link); 00097 friend gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link); 00098 00099 protected: 00100 char *d_base; // base address of buffer 00101 unsigned int d_bufsize; // in items 00102 private: 00103 gr_vmcircbuf *d_vmcircbuf; 00104 size_t d_sizeof_item; // in bytes 00105 std::vector<gr_buffer_reader *> d_readers; 00106 boost::weak_ptr<gr_block> d_link; // block that writes to this buffer 00107 00108 // 00109 // The mutex protects d_write_index, d_done and the d_read_index's in the buffer readers. 00110 // 00111 gruel::mutex d_mutex; 00112 unsigned int d_write_index; // in items [0,d_bufsize) 00113 bool d_done; 00114 00115 unsigned 00116 index_add (unsigned a, unsigned b) 00117 { 00118 unsigned s = a + b; 00119 00120 if (s >= d_bufsize) 00121 s -= d_bufsize; 00122 00123 assert (s < d_bufsize); 00124 return s; 00125 } 00126 00127 unsigned 00128 index_sub (unsigned a, unsigned b) 00129 { 00130 int s = a - b; 00131 00132 if (s < 0) 00133 s += d_bufsize; 00134 00135 assert ((unsigned) s < d_bufsize); 00136 return s; 00137 } 00138 00139 virtual bool allocate_buffer (int nitems, size_t sizeof_item); 00140 00141 /*! 00142 * \brief constructor is private. Use gr_make_buffer to create instances. 00143 * 00144 * Allocate a buffer that holds at least \p nitems of size \p sizeof_item. 00145 * 00146 * \param nitems is the minimum number of items the buffer will hold. 00147 * \param sizeof_item is the size of an item in bytes. 00148 * \param link is the block that writes to this buffer. 00149 * 00150 * The total size of the buffer will be rounded up to a system 00151 * dependent boundary. This is typically the system page size, but 00152 * under MS windows is 64KB. 00153 */ 00154 gr_buffer (int nitems, size_t sizeof_item, gr_block_sptr link); 00155 00156 /*! 00157 * \brief disassociate \p reader from this buffer 00158 */ 00159 void drop_reader (gr_buffer_reader *reader); 00160 00161 }; 00162 00163 /*! 00164 * \brief Create a new gr_buffer_reader and attach it to buffer \p buf 00165 * \param buf is the buffer the \p gr_buffer_reader reads from. 00166 * \param nzero_preload -- number of zero items to "preload" into buffer. 00167 * \param link is the block that reads from the buffer using this gr_buffer_reader. 00168 */ 00169 gr_buffer_reader_sptr 00170 gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link=gr_block_sptr()); 00171 00172 //! returns # of gr_buffers currently allocated 00173 long gr_buffer_ncurrently_allocated (); 00174 00175 00176 // --------------------------------------------------------------------------- 00177 00178 /*! 00179 * \brief How we keep track of the readers of a gr_buffer. 00180 * \ingroup internal 00181 */ 00182 00183 class gr_buffer_reader { 00184 public: 00185 00186 ~gr_buffer_reader (); 00187 00188 /*! 00189 * \brief Return number of items available for reading. 00190 */ 00191 int items_available () const; 00192 00193 /*! 00194 * \brief Return buffer this reader reads from. 00195 */ 00196 gr_buffer_sptr buffer () const { return d_buffer; } 00197 00198 00199 /*! 00200 * \brief Return maximum number of items that could ever be available for reading. 00201 * This is used as a sanity check in the scheduler to avoid looping forever. 00202 */ 00203 int max_possible_items_available () const { return d_buffer->d_bufsize - 1; } 00204 00205 /*! 00206 * \brief return pointer to read buffer. 00207 * 00208 * The return value points to items_available() number of items 00209 */ 00210 const void *read_pointer (); 00211 00212 /* 00213 * \brief tell buffer we read \p items from it 00214 */ 00215 void update_read_pointer (int nitems); 00216 00217 void set_done (bool done) { d_buffer->set_done (done); } 00218 bool done () const { return d_buffer->done (); } 00219 00220 gruel::mutex *mutex() { return d_buffer->mutex(); } 00221 00222 00223 /*! 00224 * \brief Return the block that reads via this reader. 00225 */ 00226 gr_block_sptr link() { return gr_block_sptr(d_link); } 00227 00228 // ------------------------------------------------------------------------- 00229 00230 private: 00231 00232 friend class gr_buffer; 00233 friend gr_buffer_reader_sptr 00234 gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link); 00235 00236 00237 gr_buffer_sptr d_buffer; 00238 unsigned int d_read_index; // in items [0,d->buffer.d_bufsize) 00239 boost::weak_ptr<gr_block> d_link; // block that reads via this buffer reader 00240 00241 //! constructor is private. Use gr_buffer::add_reader to create instances 00242 gr_buffer_reader (gr_buffer_sptr buffer, unsigned int read_index, gr_block_sptr link); 00243 }; 00244 00245 //! returns # of gr_buffer_readers currently allocated 00246 long gr_buffer_reader_ncurrently_allocated (); 00247 00248 00249 #endif /* INCLUDED_GR_BUFFER_H */