GNU Radio 3.7.1 C++ API
|
00001 /* -*- c++ -*- */ 00002 /* 00003 * Copyright 2004,2009-2011,2013 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_RUNTIME_BUFFER_H 00024 #define INCLUDED_GR_RUNTIME_BUFFER_H 00025 00026 #include <gnuradio/api.h> 00027 #include <gnuradio/runtime_types.h> 00028 #include <gnuradio/tags.h> 00029 #include <boost/weak_ptr.hpp> 00030 #include <gnuradio/thread/thread.h> 00031 #include <deque> 00032 00033 namespace gr { 00034 00035 class vmcircbuf; 00036 00037 /*! 00038 * \brief Allocate a buffer that holds at least \p nitems of size \p sizeof_item. 00039 * 00040 * The total size of the buffer will be rounded up to a system 00041 * dependent boundary. This is typically the system page size, but 00042 * under MS windows is 64KB. 00043 * 00044 * \param nitems is the minimum number of items the buffer will hold. 00045 * \param sizeof_item is the size of an item in bytes. 00046 * \param link is the block that writes to this buffer. 00047 */ 00048 GR_RUNTIME_API buffer_sptr make_buffer(int nitems, size_t sizeof_item, 00049 block_sptr link=block_sptr()); 00050 00051 /*! 00052 * \brief Single writer, multiple reader fifo. 00053 * \ingroup internal 00054 */ 00055 class GR_RUNTIME_API buffer 00056 { 00057 public: 00058 virtual ~buffer(); 00059 00060 /*! 00061 * \brief return number of items worth of space available for writing 00062 */ 00063 int space_available(); 00064 00065 /*! 00066 * \brief return size of this buffer in items 00067 */ 00068 int bufsize() const { return d_bufsize; } 00069 00070 /*! 00071 * \brief return pointer to write buffer. 00072 * 00073 * The return value points at space that can hold at least 00074 * space_available() items. 00075 */ 00076 void *write_pointer(); 00077 00078 /*! 00079 * \brief tell buffer that we wrote \p nitems into it 00080 */ 00081 void update_write_pointer(int nitems); 00082 00083 void set_done(bool done); 00084 bool done() const { return d_done; } 00085 00086 /*! 00087 * \brief Return the block that writes to this buffer. 00088 */ 00089 block_sptr link() { return block_sptr(d_link); } 00090 00091 size_t nreaders() const { return d_readers.size(); } 00092 buffer_reader* reader(size_t index) { return d_readers[index]; } 00093 00094 gr::thread::mutex *mutex() { return &d_mutex; } 00095 00096 uint64_t nitems_written() { return d_abs_write_offset; } 00097 00098 size_t get_sizeof_item() { return d_sizeof_item; } 00099 00100 /*! 00101 * \brief Adds a new tag to the buffer. 00102 * 00103 * \param tag the new tag 00104 */ 00105 void add_item_tag(const tag_t &tag); 00106 00107 /*! 00108 * \brief Removes an existing tag from the buffer. 00109 * 00110 * If no such tag is found, does nothing. 00111 * Note: Doesn't actually physically delete the tag, but 00112 * marks it as deleted. For the user, this has the same effect: 00113 * Any subsequent calls to get_tags_in_range() will not return 00114 * the tag. 00115 * 00116 * \param tag the tag that needs to be removed 00117 * \param id the unique ID of the block calling this function 00118 */ 00119 void remove_item_tag(const tag_t &tag, long id); 00120 00121 /*! 00122 * \brief Removes all tags before \p max_time from buffer 00123 * 00124 * \param max_time the time (item number) to trim up until. 00125 */ 00126 void prune_tags(uint64_t max_time); 00127 00128 std::deque<tag_t>::iterator get_tags_begin() { return d_item_tags.begin(); } 00129 std::deque<tag_t>::iterator get_tags_end() { return d_item_tags.end(); } 00130 00131 // ------------------------------------------------------------------------- 00132 00133 private: 00134 friend class buffer_reader; 00135 friend GR_RUNTIME_API buffer_sptr make_buffer(int nitems, size_t sizeof_item, block_sptr link); 00136 friend GR_RUNTIME_API buffer_reader_sptr buffer_add_reader(buffer_sptr buf, int nzero_preload, block_sptr link); 00137 00138 protected: 00139 char *d_base; // base address of buffer 00140 unsigned int d_bufsize; // in items 00141 private: 00142 gr::vmcircbuf *d_vmcircbuf; 00143 size_t d_sizeof_item; // in bytes 00144 std::vector<buffer_reader *> d_readers; 00145 boost::weak_ptr<block> d_link; // block that writes to this buffer 00146 00147 // 00148 // The mutex protects d_write_index, d_abs_write_offset, d_done, d_item_tags 00149 // and the d_read_index's and d_abs_read_offset's in the buffer readers. 00150 // 00151 gr::thread::mutex d_mutex; 00152 unsigned int d_write_index; // in items [0,d_bufsize) 00153 uint64_t d_abs_write_offset; // num items written since the start 00154 bool d_done; 00155 std::deque<tag_t> d_item_tags; 00156 uint64_t d_last_min_items_read; 00157 00158 unsigned index_add(unsigned a, unsigned b) 00159 { 00160 unsigned s = a + b; 00161 00162 if(s >= d_bufsize) 00163 s -= d_bufsize; 00164 00165 assert(s < d_bufsize); 00166 return s; 00167 } 00168 00169 unsigned index_sub(unsigned a, unsigned b) 00170 { 00171 int s = a - b; 00172 00173 if(s < 0) 00174 s += d_bufsize; 00175 00176 assert((unsigned) s < d_bufsize); 00177 return s; 00178 } 00179 00180 virtual bool allocate_buffer(int nitems, size_t sizeof_item); 00181 00182 /*! 00183 * \brief constructor is private. Use gr_make_buffer to create instances. 00184 * 00185 * Allocate a buffer that holds at least \p nitems of size \p sizeof_item. 00186 * 00187 * \param nitems is the minimum number of items the buffer will hold. 00188 * \param sizeof_item is the size of an item in bytes. 00189 * \param link is the block that writes to this buffer. 00190 * 00191 * The total size of the buffer will be rounded up to a system 00192 * dependent boundary. This is typically the system page size, but 00193 * under MS windows is 64KB. 00194 */ 00195 buffer(int nitems, size_t sizeof_item, block_sptr link); 00196 00197 /*! 00198 * \brief disassociate \p reader from this buffer 00199 */ 00200 void drop_reader(buffer_reader *reader); 00201 }; 00202 00203 /*! 00204 * \brief Create a new gr::buffer_reader and attach it to buffer \p buf 00205 * \param buf is the buffer the \p gr::buffer_reader reads from. 00206 * \param nzero_preload -- number of zero items to "preload" into buffer. 00207 * \param link is the block that reads from the buffer using this gr::buffer_reader. 00208 */ 00209 GR_RUNTIME_API buffer_reader_sptr 00210 buffer_add_reader(buffer_sptr buf, int nzero_preload, block_sptr link=block_sptr()); 00211 00212 //! returns # of buffers currently allocated 00213 GR_RUNTIME_API long buffer_ncurrently_allocated(); 00214 00215 00216 // --------------------------------------------------------------------------- 00217 00218 /*! 00219 * \brief How we keep track of the readers of a gr::buffer. 00220 * \ingroup internal 00221 */ 00222 class GR_RUNTIME_API buffer_reader 00223 { 00224 public: 00225 ~buffer_reader(); 00226 00227 /*! 00228 * \brief Return number of items available for reading. 00229 */ 00230 int items_available() const; 00231 00232 /*! 00233 * \brief Return buffer this reader reads from. 00234 */ 00235 buffer_sptr buffer() const { return d_buffer; } 00236 00237 /*! 00238 * \brief Return maximum number of items that could ever be available for reading. 00239 * This is used as a sanity check in the scheduler to avoid looping forever. 00240 */ 00241 int max_possible_items_available() const { return d_buffer->d_bufsize - 1; } 00242 00243 /*! 00244 * \brief return pointer to read buffer. 00245 * 00246 * The return value points to items_available() number of items 00247 */ 00248 const void *read_pointer(); 00249 00250 /* 00251 * \brief tell buffer we read \p items from it 00252 */ 00253 void update_read_pointer(int nitems); 00254 00255 void set_done(bool done) { d_buffer->set_done(done); } 00256 bool done() const { return d_buffer->done(); } 00257 00258 gr::thread::mutex *mutex() { return d_buffer->mutex(); } 00259 00260 uint64_t nitems_read() { return d_abs_read_offset; } 00261 00262 size_t get_sizeof_item() { return d_buffer->get_sizeof_item(); } 00263 00264 /*! 00265 * \brief Return the block that reads via this reader. 00266 * 00267 */ 00268 block_sptr link() { return block_sptr(d_link); } 00269 00270 /*! 00271 * \brief Given a [start,end), returns a vector all tags in the range. 00272 * 00273 * Get a vector of tags in given range. Range of counts is from start to end-1. 00274 * 00275 * Tags are tuples of: 00276 * (item count, source id, key, value) 00277 * 00278 * \param v a vector reference to return tags into 00279 * \param abs_start a uint64 count of the start of the range of interest 00280 * \param abs_end a uint64 count of the end of the range of interest 00281 * \param id the unique ID of the block to make sure already deleted tags are not returned 00282 */ 00283 void get_tags_in_range(std::vector<tag_t> &v, 00284 uint64_t abs_start, 00285 uint64_t abs_end, 00286 long id); 00287 00288 // ------------------------------------------------------------------------- 00289 00290 private: 00291 friend class buffer; 00292 friend GR_RUNTIME_API buffer_reader_sptr 00293 buffer_add_reader(buffer_sptr buf, int nzero_preload, block_sptr link); 00294 00295 buffer_sptr d_buffer; 00296 unsigned int d_read_index; // in items [0,d->buffer.d_bufsize) 00297 uint64_t d_abs_read_offset; // num items seen since the start 00298 boost::weak_ptr<block> d_link; // block that reads via this buffer reader 00299 00300 //! constructor is private. Use gr::buffer::add_reader to create instances 00301 buffer_reader(buffer_sptr buffer, unsigned int read_index, block_sptr link); 00302 }; 00303 00304 //! returns # of buffer_readers currently allocated 00305 GR_RUNTIME_API long buffer_reader_ncurrently_allocated (); 00306 00307 } /* namespace gr */ 00308 00309 #endif /* INCLUDED_GR_RUNTIME_BUFFER_H */