gr_blocks may now produce different number of output items on each output stream.
authoreb <eb@221aa14e-8319-0410-a670-987f0aec2ac5>
Sat, 15 Aug 2009 17:39:10 +0000 (17:39 +0000)
committereb <eb@221aa14e-8319-0410-a670-987f0aec2ac5>
Sat, 15 Aug 2009 17:39:10 +0000 (17:39 +0000)
Merged eb/varying -r11178:11595 into trunk. Needs QA and examples.

git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@11597 221aa14e-8319-0410-a670-987f0aec2ac5

gnuradio-core/src/lib/runtime/gr_block.cc
gnuradio-core/src/lib/runtime/gr_block.h
gnuradio-core/src/lib/runtime/gr_block_detail.cc
gnuradio-core/src/lib/runtime/gr_block_detail.h
gnuradio-core/src/lib/runtime/gr_block_executor.cc

index b8b1bd9c73ac9db1c5449f8e6792039d11337e21..8915f3360fb56c9a6c6459bd3565bee82ffaba7b 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2004 Free Software Foundation, Inc.
+ * Copyright 2004,2009 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -99,6 +99,12 @@ gr_block::consume_each (int how_many_items)
   d_detail->consume_each (how_many_items);
 }
 
+void
+gr_block::produce (int which_output, int how_many_items)
+{
+  d_detail->produce (which_output, how_many_items);
+}
+
 int
 gr_block::fixed_rate_ninput_to_noutput(int ninput)
 {
index 354695c0b70bb9de3d6b27a7d66310e6f58c54d7..b6f724dde0a89bc79629602209b0baf710ef6a10 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2004,2007 Free Software Foundation, Inc.
+ * Copyright 2004,2007,2009 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -57,6 +57,12 @@ class gr_block : public gr_basic_block {
 
  public:
   
+  //! Magic return values from general_work
+  enum {
+    WORK_CALLED_PRODUCE = -2,
+    WORK_DONE = -1
+  };
+
   virtual ~gr_block ();
 
   /*!
@@ -70,7 +76,7 @@ class gr_block : public gr_basic_block {
   void  set_history (unsigned history) { d_history = history; }
   
   /*!
-   * \brief return true if this block has a fixed input to output rate
+   * \brief Return true if this block has a fixed input to output rate.
    *
    * If true, then fixed_rate_in_to_out and fixed_rate_out_to_in may be called.
    */
@@ -149,6 +155,13 @@ class gr_block : public gr_basic_block {
    */
   void consume_each (int how_many_items);
 
+  /*!
+   * \brief Tell the scheduler \p how_many_items were produced on output stream \p which_output.
+   *
+   * If the block's general_work method calls produce, \p general_work must return WORK_CALLED_PRODUCE.
+   */
+  void produce (int which_output, int how_many_items);
+
   /*!
    * \brief Set the approximate output rate / input rate
    *
@@ -191,7 +204,7 @@ class gr_block : public gr_basic_block {
 
   int                   d_output_multiple;
   double                d_relative_rate;       // approx output_rate / input_rate
-  gr_block_detail_sptr d_detail;                   // implementation details
+  gr_block_detail_sptr d_detail;               // implementation details
   unsigned              d_history;
   bool                  d_fixed_rate;
     
index ae1ea25628d63631df41dcd4924fa85cdfa1a8ed..f36a6c2155e75f36bc8f154896705da869e90d5d 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2004 Free Software Foundation, Inc.
+ * Copyright 2004,2009 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -36,7 +36,8 @@ gr_block_detail_ncurrently_allocated ()
 }
 
 gr_block_detail::gr_block_detail (unsigned int ninputs, unsigned int noutputs)
-  : d_ninputs (ninputs), d_noutputs (noutputs),
+  : d_produce_or(0),
+    d_ninputs (ninputs), d_noutputs (noutputs),
     d_input (ninputs), d_output (noutputs),
     d_done (false)
 {
@@ -99,10 +100,21 @@ gr_block_detail::consume_each (int how_many_items)
       d_input[i]->update_read_pointer (how_many_items);
 }
 
+void
+gr_block_detail::produce (int which_output, int how_many_items)
+{
+  if (how_many_items > 0){
+    d_output[which_output]->update_write_pointer (how_many_items);
+    d_produce_or |= how_many_items;
+  }
+}
+
 void
 gr_block_detail::produce_each (int how_many_items)
 {
-  if (how_many_items > 0)
+  if (how_many_items > 0){
     for (int i = 0; i < noutputs (); i++)
       d_output[i]->update_write_pointer (how_many_items);
+    d_produce_or |= how_many_items;
+  }
 }
index 2856c402c7a7925a5d8f762adc9d2eb7f5861633..f32a875ec4019f506e0f4387a8ae0de5c5017c7a 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2004 Free Software Foundation, Inc.
+ * Copyright 2004,2009 Free Software Foundation, Inc.
  *
  * This file is part of GNU Radio
  *
@@ -73,13 +73,20 @@ class gr_block_detail {
    */
   void consume_each (int how_many_items);
 
+  /*!
+   * \brief Tell the scheduler \p how_many_items were produced on output stream \p which_output.
+   */
+  void produce (int which_output, int how_many_items);
+
   /*!
    * \brief Tell the scheduler \p how_many_items were produced on each output stream.
    */
   void produce_each (int how_many_items);
 
 
+
   gr_tpb_detail                             d_tpb;     // used by thread-per-block scheduler
+  int                               d_produce_or;
 
   // ----------------------------------------------------------------------------
 
index e8d30b9632a3417efaeca9f5655fe32702f60d86..2c21a0b0f26815b764bf5df89ca5789d1be671b3 100644 (file)
@@ -1,6 +1,6 @@
 /* -*- c++ -*- */
 /*
- * Copyright 2004,2008 Free Software Foundation, Inc.
+ * Copyright 2004,2008,2009 Free Software Foundation, Inc.
  * 
  * This file is part of GNU Radio
  * 
@@ -290,6 +290,7 @@ gr_block_executor::run_one_iteration()
 
   setup_call_to_work:
 
+    d->d_produce_or = 0;
     for (int i = 0; i < d->noutputs (); i++)
       d_output_items[i] = d->output(i)->write_pointer();
 
@@ -299,11 +300,13 @@ gr_block_executor::run_one_iteration()
     LOG(*d_log << "  general_work: noutput_items = " << noutput_items
        << " result = " << n << std::endl);
 
-    if (n == -1)               // block is done
+    if (n == gr_block::WORK_DONE)
       goto were_done;
 
-    d->produce_each (n);       // advance write pointers
-    if (n > 0)
+    if (n != gr_block::WORK_CALLED_PRODUCE)
+      d->produce_each (n);     // advance write pointers
+    
+    if (d->d_produce_or > 0)   // block produced something
       return READY;
 
     // We didn't produce any output even though we called general_work.
@@ -312,7 +315,7 @@ gr_block_executor::run_one_iteration()
     // If this is a source, it's broken.
     if (d->source_p()){
       std::cerr << "gr_block_executor: source " << m
-               << " returned 0 from work.  We're marking it DONE.\n";
+               << " produced no output.  We're marking it DONE.\n";
       // FIXME maybe we ought to raise an exception...
       goto were_done;
     }