Imported Upstream version 3.2.2
[debian/gnuradio] / gnuradio-core / src / lib / runtime / gr_buffer.h
index cbfdc4f18a89bf888eb561ea7218cb2b4d4a70a9..cb593eea3453b7c8e6401922f050626acf9558aa 100644 (file)
@@ -23,7 +23,9 @@
 #ifndef INCLUDED_GR_BUFFER_H
 #define INCLUDED_GR_BUFFER_H
 
-#include <gr_runtime.h>
+#include <gr_runtime_types.h>
+#include <boost/weak_ptr.hpp>
+#include <boost/thread.hpp>
 
 class gr_vmcircbuf;
 
@@ -33,8 +35,12 @@ class gr_vmcircbuf;
  * The total size of the buffer will be rounded up to a system
  * dependent boundary.  This is typically the system page size, but
  * under MS windows is 64KB.
+ *
+ * \param nitems is the minimum number of items the buffer will hold.
+ * \param sizeof_item is the size of an item in bytes.
+ * \param link is the block that writes to this buffer.
  */
-gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item);
+gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item, gr_block_sptr link=gr_block_sptr());
 
 
 /*!
@@ -43,12 +49,20 @@ gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item);
  */
 class gr_buffer {
  public:
+
+  typedef boost::unique_lock<boost::mutex>  scoped_lock;
+
   virtual ~gr_buffer ();
 
   /*!
    * \brief return number of items worth of space available for writing
    */
-  int space_available () const;
+  int space_available ();
+
+  /*!
+   * \brief return size of this buffer in items
+   */
+  int bufsize() const { return d_bufsize; }
 
   /*!
    * \brief return pointer to write buffer.
@@ -63,17 +77,26 @@ class gr_buffer {
    */
   void update_write_pointer (int nitems);
 
-
-  void set_done (bool done)   { d_done = done; }
+  void set_done (bool done);
   bool done () const { return d_done; }
 
+  /*!
+   * \brief Return the block that writes to this buffer.
+   */
+  gr_block_sptr link() { return gr_block_sptr(d_link); }
+
+  size_t nreaders() const { return d_readers.size(); }
+  gr_buffer_reader* reader(size_t index) { return d_readers[index]; }
+
+  boost::mutex *mutex() { return &d_mutex; }
+
   // -------------------------------------------------------------------------
 
  private:
 
   friend class gr_buffer_reader;
-  friend gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item);
-  friend gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload);
+  friend gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item, gr_block_sptr link);
+  friend gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link);
 
  protected:
   char                                *d_base;         // base address of buffer
@@ -81,8 +104,14 @@ class gr_buffer {
  private:
   gr_vmcircbuf                        *d_vmcircbuf;
   size_t                               d_sizeof_item;  // in bytes
-  unsigned int                         d_write_index;  // in items [0,d_bufsize)
   std::vector<gr_buffer_reader *>      d_readers;
+  boost::weak_ptr<gr_block>            d_link;         // block that writes to this buffer
+
+  //
+  // The mutex protects d_write_index, d_done and the d_read_index's in the buffer readers.
+  //
+  boost::mutex                         d_mutex;
+  unsigned int                         d_write_index;  // in items [0,d_bufsize)
   bool                                 d_done;
   
   unsigned
@@ -116,11 +145,15 @@ class gr_buffer {
    *
    * Allocate a buffer that holds at least \p nitems of size \p sizeof_item.
    *
+   * \param nitems is the minimum number of items the buffer will hold.
+   * \param sizeof_item is the size of an item in bytes.
+   * \param link is the block that writes to this buffer.
+   *
    * The total size of the buffer will be rounded up to a system
    * dependent boundary.  This is typically the system page size, but
    * under MS windows is 64KB.
    */
-  gr_buffer (int nitems, size_t sizeof_item);
+  gr_buffer (int nitems, size_t sizeof_item, gr_block_sptr link);
 
   /*!
    * \brief disassociate \p reader from this buffer
@@ -130,10 +163,13 @@ class gr_buffer {
 };
 
 /*!
- * \brief create a new gr_buffer_reader and attach it to buffer \p buf
+ * \brief Create a new gr_buffer_reader and attach it to buffer \p buf
+ * \param buf is the buffer the \p gr_buffer_reader reads from.
  * \param nzero_preload -- number of zero items to "preload" into buffer.
+ * \param link is the block that reads from the buffer using this gr_buffer_reader.
  */
-gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload);
+gr_buffer_reader_sptr 
+gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link=gr_block_sptr());
 
 //! returns # of gr_buffers currently allocated
 long gr_buffer_ncurrently_allocated ();
@@ -147,8 +183,10 @@ long gr_buffer_ncurrently_allocated ();
  */
 
 class gr_buffer_reader {
-
  public:
+
+  typedef gr_buffer::scoped_lock scoped_lock;
+
   ~gr_buffer_reader ();
 
   /*!
@@ -156,6 +194,12 @@ class gr_buffer_reader {
    */
   int items_available () const;
 
+  /*!
+   * \brief Return buffer this reader reads from.
+   */
+  gr_buffer_sptr buffer () const { return d_buffer; }
+
+
   /*!
    * \brief Return maximum number of items that could ever be available for reading.
    * This is used as a sanity check in the scheduler to avoid looping forever.
@@ -177,19 +221,29 @@ class gr_buffer_reader {
   void set_done (bool done)   { d_buffer->set_done (done); }
   bool done () const { return d_buffer->done (); }
 
+  boost::mutex *mutex() { return d_buffer->mutex(); }
+
+
+  /*!
+   * \brief Return the block that reads via this reader.
+   */
+  gr_block_sptr link() { return gr_block_sptr(d_link); }
+
   // -------------------------------------------------------------------------
 
  private:
 
   friend class gr_buffer;
-  friend gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload);
+  friend gr_buffer_reader_sptr 
+  gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link);
 
 
   gr_buffer_sptr               d_buffer;
   unsigned int                 d_read_index;   // in items [0,d->buffer.d_bufsize)
+  boost::weak_ptr<gr_block>    d_link;         // block that reads via this buffer reader
 
   //! constructor is private.  Use gr_buffer::add_reader to create instances
-  gr_buffer_reader (gr_buffer_sptr buffer, unsigned int read_index);
+  gr_buffer_reader (gr_buffer_sptr buffer, unsigned int read_index, gr_block_sptr link);
 };
 
 //! returns # of gr_buffer_readers currently allocated