summaryrefslogtreecommitdiff
path: root/gnuradio-core/src/lib/runtime
diff options
context:
space:
mode:
authorTom Rondeau2011-06-05 15:36:47 -0400
committerTom Rondeau2011-06-05 15:36:47 -0400
commit233f960474f86bc8cc519ce7257b29d8615c4000 (patch)
tree1a4c846119a01a5a195a9e9ee5b854384b0b6535 /gnuradio-core/src/lib/runtime
parent024c79a7fb13c08bae7b97079a245f711ecf12a7 (diff)
parenta23a0a46c3bf446cbe09d71bc8e10b061256ef56 (diff)
downloadgnuradio-233f960474f86bc8cc519ce7257b29d8615c4000.tar.gz
gnuradio-233f960474f86bc8cc519ce7257b29d8615c4000.tar.bz2
gnuradio-233f960474f86bc8cc519ce7257b29d8615c4000.zip
Merge branch 'master' into turbo
Diffstat (limited to 'gnuradio-core/src/lib/runtime')
-rw-r--r--gnuradio-core/src/lib/runtime/Makefile.am18
-rw-r--r--gnuradio-core/src/lib/runtime/gr_basic_block.cc2
-rw-r--r--gnuradio-core/src/lib/runtime/gr_basic_block.h58
-rw-r--r--gnuradio-core/src/lib/runtime/gr_basic_block.i6
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.cc68
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.h87
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block.i10
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_detail.cc92
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_detail.h73
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_executor.cc86
-rw-r--r--gnuradio-core/src/lib/runtime/gr_block_executor.h3
-rw-r--r--gnuradio-core/src/lib/runtime/gr_buffer.cc83
-rw-r--r--gnuradio-core/src/lib/runtime/gr_buffer.h51
-rw-r--r--gnuradio-core/src/lib/runtime/gr_error_handler.cc1
-rw-r--r--gnuradio-core/src/lib/runtime/gr_error_handler.h1
-rw-r--r--gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc7
-rw-r--r--gnuradio-core/src/lib/runtime/gr_flowgraph.cc3
-rw-r--r--gnuradio-core/src/lib/runtime/gr_hier_block2.cc5
-rw-r--r--gnuradio-core/src/lib/runtime/gr_hier_block2.h2
-rw-r--r--gnuradio-core/src/lib/runtime/gr_hier_block2.i7
-rw-r--r--gnuradio-core/src/lib/runtime/gr_msg_queue.i65
-rw-r--r--gnuradio-core/src/lib/runtime/gr_preferences.cc34
-rw-r--r--gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.i3
-rw-r--r--gnuradio-core/src/lib/runtime/gr_sync_block.h2
-rw-r--r--gnuradio-core/src/lib/runtime/gr_sys_paths.cc55
-rw-r--r--gnuradio-core/src/lib/runtime/gr_sys_paths.h (renamed from gnuradio-core/src/lib/runtime/gr_tmp_path.h)18
-rw-r--r--gnuradio-core/src/lib/runtime/gr_tag_info.cc38
-rw-r--r--gnuradio-core/src/lib/runtime/gr_tag_info.h87
-rw-r--r--gnuradio-core/src/lib/runtime/gr_top_block.cc6
-rw-r--r--gnuradio-core/src/lib/runtime/gr_top_block.h7
-rw-r--r--gnuradio-core/src/lib/runtime/gr_top_block.i43
-rw-r--r--gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc8
-rw-r--r--gnuradio-core/src/lib/runtime/gr_unittests.h40
-rw-r--r--gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.cc3
-rw-r--r--gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.cc4
-rw-r--r--gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc4
-rw-r--r--gnuradio-core/src/lib/runtime/qa_block_tags.cc450
-rw-r--r--gnuradio-core/src/lib/runtime/qa_block_tags.h52
-rw-r--r--gnuradio-core/src/lib/runtime/qa_runtime.cc6
-rw-r--r--gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc85
-rw-r--r--gnuradio-core/src/lib/runtime/qa_set_msg_handler.h (renamed from gnuradio-core/src/lib/runtime/gr_tmp_path.cc)41
-rw-r--r--gnuradio-core/src/lib/runtime/runtime.i7
42 files changed, 1563 insertions, 158 deletions
diff --git a/gnuradio-core/src/lib/runtime/Makefile.am b/gnuradio-core/src/lib/runtime/Makefile.am
index f67e8843d..eca92e526 100644
--- a/gnuradio-core/src/lib/runtime/Makefile.am
+++ b/gnuradio-core/src/lib/runtime/Makefile.am
@@ -1,5 +1,5 @@
#
-# Copyright 2003,2004,2007,2008,2009,2010 Free Software Foundation, Inc.
+# Copyright 2003,2004,2007,2008,2009,2010,2011 Free Software Foundation, Inc.
#
# This file is part of GNU Radio
#
@@ -58,7 +58,7 @@ libruntime_la_SOURCES = \
gr_sync_block.cc \
gr_sync_decimator.cc \
gr_sync_interpolator.cc \
- gr_tmp_path.cc \
+ gr_sys_paths.cc \
gr_top_block.cc \
gr_top_block_impl.cc \
gr_tpb_detail.cc \
@@ -68,7 +68,8 @@ libruntime_la_SOURCES = \
gr_vmcircbuf_mmap_tmpfile.cc \
gr_vmcircbuf_createfilemapping.cc \
gr_vmcircbuf_sysv_shm.cc \
- gr_select_handler.cc
+ gr_select_handler.cc \
+ gr_tag_info.cc
libruntime_qa_la_SOURCES = \
qa_gr_block.cc \
@@ -79,6 +80,8 @@ libruntime_qa_la_SOURCES = \
qa_gr_top_block.cc \
qa_gr_io_signature.cc \
qa_gr_vmcircbuf.cc \
+ qa_block_tags.cc \
+ qa_set_msg_handler.cc \
qa_runtime.cc
grinclude_HEADERS = \
@@ -118,10 +121,11 @@ grinclude_HEADERS = \
gr_tpb_detail.h \
gr_tpb_thread_body.h \
gr_timer.h \
- gr_tmp_path.h \
+ gr_sys_paths.h \
gr_types.h \
gr_unittests.h \
- gr_vmcircbuf.h
+ gr_vmcircbuf.h \
+ gr_tag_info.h
noinst_HEADERS = \
gr_vmcircbuf_mmap_shm_open.h \
@@ -136,9 +140,10 @@ noinst_HEADERS = \
qa_gr_io_signature.h \
qa_gr_top_block.h \
qa_gr_vmcircbuf.h \
+ qa_block_tags.h \
+ qa_set_msg_handler.h \
qa_runtime.h
-if PYTHON
swiginclude_HEADERS = \
gr_basic_block.i \
gr_block.i \
@@ -158,4 +163,3 @@ swiginclude_HEADERS = \
gr_sync_interpolator.i \
gr_top_block.i \
runtime.i
-endif
diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.cc b/gnuradio-core/src/lib/runtime/gr_basic_block.cc
index 2fa1066cb..0e0dad16b 100644
--- a/gnuradio-core/src/lib/runtime/gr_basic_block.cc
+++ b/gnuradio-core/src/lib/runtime/gr_basic_block.cc
@@ -56,7 +56,7 @@ gr_basic_block::~gr_basic_block()
}
gr_basic_block_sptr
-gr_basic_block::basic_block()
+gr_basic_block::to_basic_block()
{
return shared_from_this();
}
diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.h b/gnuradio-core/src/lib/runtime/gr_basic_block.h
index b8797fdc6..3b0cd51dd 100644
--- a/gnuradio-core/src/lib/runtime/gr_basic_block.h
+++ b/gnuradio-core/src/lib/runtime/gr_basic_block.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2006,2008,2009 Free Software Foundation, Inc.
+ * Copyright 2006,2008,2009,2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -26,6 +26,7 @@
#include <gr_runtime_types.h>
#include <gr_sptr_magic.h>
#include <boost/enable_shared_from_this.hpp>
+#include <boost/function.hpp>
#include <gr_msg_accepter.h>
#include <string>
@@ -42,9 +43,27 @@
class gr_basic_block : public gr_msg_accepter, public boost::enable_shared_from_this<gr_basic_block>
{
+ typedef boost::function<void(pmt::pmt_t)> msg_handler_t;
+
+private:
+ /*
+ * This function is called by the runtime system to dispatch messages.
+ *
+ * The thread-safety guarantees mentioned in set_msg_handler are implemented
+ * by the callers of this method.
+ */
+ void dispatch_msg(pmt::pmt_t msg)
+ {
+ if (d_msg_handler) // Is there a handler?
+ d_msg_handler(msg); // Yes, invoke it.
+ };
+
+ msg_handler_t d_msg_handler;
+
protected:
friend class gr_flowgraph;
friend class gr_flat_flowgraph; // TODO: will be redundant
+ friend class gr_tpb_thread_body;
enum vcolor { WHITE, GREY, BLACK };
@@ -54,6 +73,8 @@ protected:
long d_unique_id;
vcolor d_color;
+ gr_basic_block(void){} //allows pure virtual interface sub-classes
+
//! Protected constructor prevents instantiation by non-derived classes
gr_basic_block(const std::string &name,
gr_io_signature_sptr input_signature,
@@ -81,7 +102,7 @@ public:
std::string name() const { return d_name; }
gr_io_signature_sptr input_signature() const { return d_input_signature; }
gr_io_signature_sptr output_signature() const { return d_output_signature; }
- gr_basic_block_sptr basic_block(); // Needed for Python type coercion
+ gr_basic_block_sptr to_basic_block(); // Needed for Python/Guile type coercion
/*!
* \brief Confirm that ninputs and noutputs is an acceptable combination.
@@ -99,15 +120,34 @@ public:
virtual bool check_topology(int ninputs, int noutputs) { return true; }
/*!
- * \brief Block message handler.
- *
- * \param msg Arbitrary message encapsulated as pmt::pmt_t
+ * \brief Set the callback that is fired when messages are available.
*
- * This function is called by the runtime system whenever there are
- * messages in its queue. Blocks should override this to receive
- * messages; the default behavior is to drop them on the floor.
+ * \p msg_handler can be any kind of function pointer or function object
+ * that has the signature:
+ * <pre>
+ * void msg_handler(pmt::pmt msg);
+ * </pre>
+ *
+ * (You may want to use boost::bind to massage your callable into the
+ * correct form. See gr_nop.{h,cc} for an example that sets up a class
+ * method as the callback.)
+ *
+ * Blocks that desire to handle messages must call this method in their
+ * constructors to register the handler that will be invoked when messages
+ * are available.
+ *
+ * If the block inherits from gr_block, the runtime system will ensure that
+ * msg_handler is called in a thread-safe manner, such that work and
+ * msg_handler will never be called concurrently. This allows msg_handler
+ * to update state variables without having to worry about thread-safety
+ * issues with work, general_work or another invocation of msg_handler.
+ *
+ * If the block inherits from gr_hier_block2, the runtime system will
+ * ensure that no reentrant calls are made to msg_handler.
*/
- virtual void handle_msg(pmt::pmt_t msg) { };
+ template <typename T> void set_msg_handler(T msg_handler){
+ d_msg_handler = msg_handler_t(msg_handler);
+ }
};
inline bool operator<(gr_basic_block_sptr lhs, gr_basic_block_sptr rhs)
diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.i b/gnuradio-core/src/lib/runtime/gr_basic_block.i
index 60e08aac3..03d4725d5 100644
--- a/gnuradio-core/src/lib/runtime/gr_basic_block.i
+++ b/gnuradio-core/src/lib/runtime/gr_basic_block.i
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2006 Free Software Foundation, Inc.
+ * Copyright 2006,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -40,13 +40,15 @@ public:
gr_io_signature_sptr input_signature() const;
gr_io_signature_sptr output_signature() const;
long unique_id() const;
- gr_basic_block_sptr basic_block();
+ gr_basic_block_sptr to_basic_block();
bool check_topology (int ninputs, int noutputs);
};
%rename(block_ncurrently_allocated) gr_basic_block_ncurrently_allocated;
long gr_basic_block_ncurrently_allocated();
+#ifdef SWIGPYTHON
%pythoncode %{
gr_basic_block_sptr.__repr__ = lambda self: "<gr_basic_block %s (%d)>" % (self.name(), self.unique_id ())
%}
+#endif
diff --git a/gnuradio-core/src/lib/runtime/gr_block.cc b/gnuradio-core/src/lib/runtime/gr_block.cc
index 8915f3360..81a55af9d 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2009 Free Software Foundation, Inc.
+ * Copyright 2004,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -36,7 +36,8 @@ gr_block::gr_block (const std::string &name,
d_output_multiple (1),
d_relative_rate (1.0),
d_history(1),
- d_fixed_rate(false)
+ d_fixed_rate(false),
+ d_tag_propagation_policy(TPP_ALL_TO_ALL)
{
}
@@ -117,6 +118,69 @@ gr_block::fixed_rate_noutput_to_ninput(int noutput)
throw std::runtime_error("Unimplemented");
}
+uint64_t
+gr_block::nitems_read(unsigned int which_input)
+{
+ if(d_detail) {
+ return d_detail->nitems_read(which_input);
+ }
+ else {
+ //throw std::runtime_error("No block_detail associated with block yet");
+ return 0;
+ }
+}
+
+uint64_t
+gr_block::nitems_written(unsigned int which_output)
+{
+ if(d_detail) {
+ return d_detail->nitems_written(which_output);
+ }
+ else {
+ //throw std::runtime_error("No block_detail associated with block yet");
+ return 0;
+ }
+}
+
+void
+gr_block::add_item_tag(unsigned int which_output,
+ uint64_t offset,
+ const pmt::pmt_t &key,
+ const pmt::pmt_t &value,
+ const pmt::pmt_t &srcid)
+{
+ d_detail->add_item_tag(which_output, offset, key, value, srcid);
+}
+
+void
+gr_block::get_tags_in_range(std::vector<pmt::pmt_t> &v,
+ unsigned int which_output,
+ uint64_t start, uint64_t end)
+{
+ d_detail->get_tags_in_range(v, which_output, start, end);
+}
+
+void
+gr_block::get_tags_in_range(std::vector<pmt::pmt_t> &v,
+ unsigned int which_output,
+ uint64_t start, uint64_t end,
+ const pmt::pmt_t &key)
+{
+ d_detail->get_tags_in_range(v, which_output, start, end, key);
+}
+
+gr_block::tag_propagation_policy_t
+gr_block::tag_propagation_policy()
+{
+ return d_tag_propagation_policy;
+}
+
+void
+gr_block::set_tag_propagation_policy(tag_propagation_policy_t p)
+{
+ d_tag_propagation_policy = p;
+}
+
std::ostream&
operator << (std::ostream& os, const gr_block *m)
{
diff --git a/gnuradio-core/src/lib/runtime/gr_block.h b/gnuradio-core/src/lib/runtime/gr_block.h
index b6f724dde..fc22f9ea8 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.h
+++ b/gnuradio-core/src/lib/runtime/gr_block.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2007,2009 Free Software Foundation, Inc.
+ * Copyright 2004,2007,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -63,6 +63,12 @@ class gr_block : public gr_basic_block {
WORK_DONE = -1
};
+ enum tag_propagation_policy_t {
+ TPP_DONT = 0,
+ TPP_ALL_TO_ALL = 1,
+ TPP_ONE_TO_ONE = 2
+ };
+
virtual ~gr_block ();
/*!
@@ -198,6 +204,26 @@ class gr_block : public gr_basic_block {
*/
virtual int fixed_rate_noutput_to_ninput(int noutput);
+ /*!
+ * \brief Return the number of items read on input stream which_input
+ */
+ uint64_t nitems_read(unsigned int which_input);
+
+ /*!
+ * \brief Return the number of items written on output stream which_output
+ */
+ uint64_t nitems_written(unsigned int which_output);
+
+ /*!
+ * \brief Asks for the policy used by the scheduler to moved tags downstream.
+ */
+ tag_propagation_policy_t tag_propagation_policy();
+
+ /*!
+ * \brief Set the policy by the scheduler to determine how tags are moved downstream.
+ */
+ void set_tag_propagation_policy(tag_propagation_policy_t p);
+
// ----------------------------------------------------------------------------
private:
@@ -207,15 +233,72 @@ class gr_block : public gr_basic_block {
gr_block_detail_sptr d_detail; // implementation details
unsigned d_history;
bool d_fixed_rate;
+ tag_propagation_policy_t d_tag_propagation_policy; // policy for moving tags downstream
protected:
-
+ gr_block (void){} //allows pure virtual interface sub-classes
gr_block (const std::string &name,
gr_io_signature_sptr input_signature,
gr_io_signature_sptr output_signature);
void set_fixed_rate(bool fixed_rate){ d_fixed_rate = fixed_rate; }
+
+ /*!
+ * \brief Adds a new tag onto the given output buffer.
+ *
+ * \param which_output an integer of which output stream to attach the tag
+ * \param abs_offset a uint64 number of the absolute item number
+ * assicated with the tag. Can get from nitems_written.
+ * \param key the tag key as a PMT symbol
+ * \param value any PMT holding any value for the given key
+ * \param srcid optional source ID specifier; defaults to PMT_F
+ */
+ void add_item_tag(unsigned int which_output,
+ uint64_t abs_offset,
+ const pmt::pmt_t &key,
+ const pmt::pmt_t &value,
+ const pmt::pmt_t &srcid=pmt::PMT_F);
+
+ /*!
+ * \brief Given a [start,end), returns a vector of all tags in the range.
+ *
+ * Range of counts is from start to end-1.
+ *
+ * Tags are tuples of:
+ * (item count, source id, key, value)
+ *
+ * \param v a vector reference to return tags into
+ * \param which_input an integer of which input stream to pull from
+ * \param abs_start a uint64 count of the start of the range of interest
+ * \param abs_end a uint64 count of the end of the range of interest
+ */
+ void get_tags_in_range(std::vector<pmt::pmt_t> &v,
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end);
+
+ /*!
+ * \brief Given a [start,end), returns a vector of all tags in the range
+ * with a given key.
+ *
+ * Range of counts is from start to end-1.
+ *
+ * Tags are tuples of:
+ * (item count, source id, key, value)
+ *
+ * \param v a vector reference to return tags into
+ * \param which_input an integer of which input stream to pull from
+ * \param abs_start a uint64 count of the start of the range of interest
+ * \param abs_end a uint64 count of the end of the range of interest
+ * \param key a PMT symbol key to filter only tags of this key
+ */
+ void get_tags_in_range(std::vector<pmt::pmt_t> &v,
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end,
+ const pmt::pmt_t &key);
+
// These are really only for internal use, but leaving them public avoids
// having to work up an ever-varying list of friends
diff --git a/gnuradio-core/src/lib/runtime/gr_block.i b/gnuradio-core/src/lib/runtime/gr_block.i
index c2e2aa4b8..bb0c5f221 100644
--- a/gnuradio-core/src/lib/runtime/gr_block.i
+++ b/gnuradio-core/src/lib/runtime/gr_block.i
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004 Free Software Foundation, Inc.
+ * Copyright 2004,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -49,12 +49,10 @@ class gr_block : public gr_basic_block {
bool start();
bool stop();
+ uint64_t nitems_read(unsigned int which_input);
+ uint64_t nitems_written(unsigned int which_output);
+
// internal use
gr_block_detail_sptr detail () const { return d_detail; }
void set_detail (gr_block_detail_sptr detail) { d_detail = detail; }
};
-
-%pythoncode %{
-gr_block_sptr.__repr__ = lambda self: "<gr_block %s (%d)>" % (self.name(), self.unique_id ())
-gr_block_sptr.block = lambda self: self
-%}
diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.cc b/gnuradio-core/src/lib/runtime/gr_block_detail.cc
index 38d4a13ca..a360240c0 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_detail.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block_detail.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2009 Free Software Foundation, Inc.
+ * Copyright 2004,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -27,6 +27,8 @@
#include <gr_block_detail.h>
#include <gr_buffer.h>
+using namespace pmt;
+
static long s_ncurrently_allocated = 0;
long
@@ -88,16 +90,20 @@ gr_block_detail::set_done (bool done)
void
gr_block_detail::consume (int which_input, int how_many_items)
{
- if (how_many_items > 0)
+ if (how_many_items > 0) {
input (which_input)->update_read_pointer (how_many_items);
+ }
}
+
void
gr_block_detail::consume_each (int how_many_items)
{
- if (how_many_items > 0)
- for (int i = 0; i < ninputs (); i++)
+ if (how_many_items > 0) {
+ for (int i = 0; i < ninputs (); i++) {
d_input[i]->update_read_pointer (how_many_items);
+ }
+ }
}
void
@@ -112,16 +118,88 @@ gr_block_detail::produce (int which_output, int how_many_items)
void
gr_block_detail::produce_each (int how_many_items)
{
- if (how_many_items > 0){
- for (int i = 0; i < noutputs (); i++)
+ 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;
}
}
void
-gr_block_detail::_post(pmt::pmt_t msg)
+gr_block_detail::_post(pmt_t msg)
{
d_tpb.insert_tail(msg);
}
+
+uint64_t
+gr_block_detail::nitems_read(unsigned int which_input)
+{
+ if(which_input >= d_ninputs)
+ throw std::invalid_argument ("gr_block_detail::n_input_items");
+ return d_input[which_input]->nitems_read();
+}
+
+uint64_t
+gr_block_detail::nitems_written(unsigned int which_output)
+{
+ if(which_output >= d_noutputs)
+ throw std::invalid_argument ("gr_block_detail::n_output_items");
+ return d_output[which_output]->nitems_written();
+}
+
+void
+gr_block_detail::add_item_tag(unsigned int which_output,
+ uint64_t abs_offset,
+ const pmt_t &key,
+ const pmt_t &value,
+ const pmt_t &srcid)
+{
+ if(!pmt_is_symbol(key)) {
+ throw pmt_wrong_type("gr_block_detail::add_item_tag key", key);
+ }
+ else {
+ // build tag tuple
+ pmt_t nitem = pmt_from_uint64(abs_offset);
+ pmt_t tuple = pmt_make_tuple(nitem, srcid, key, value);
+
+ // Add tag to gr_buffer's deque tags
+ d_output[which_output]->add_item_tag(tuple);
+ }
+}
+
+void
+gr_block_detail::get_tags_in_range(std::vector<pmt::pmt_t> &v,
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end)
+{
+ // get from gr_buffer_reader's deque of tags
+ d_input[which_input]->get_tags_in_range(v, abs_start, abs_end);
+}
+
+void
+gr_block_detail::get_tags_in_range(std::vector<pmt_t> &v,
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end,
+ const pmt_t &key)
+{
+ std::vector<pmt_t> found_items;
+
+ v.resize(0);
+
+ // get from gr_buffer_reader's deque of tags
+ d_input[which_input]->get_tags_in_range(found_items, abs_start, abs_end);
+
+ // Filter further by key name
+ pmt_t itemkey;
+ std::vector<pmt_t>::iterator itr;
+ for(itr = found_items.begin(); itr != found_items.end(); itr++) {
+ itemkey = pmt_tuple_ref(*itr, 2);
+ if(pmt_eqv(key, itemkey)) {
+ v.push_back(*itr);
+ }
+ }
+}
diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.h b/gnuradio-core/src/lib/runtime/gr_block_detail.h
index c5787a5ad..d7ec3b136 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_detail.h
+++ b/gnuradio-core/src/lib/runtime/gr_block_detail.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2009 Free Software Foundation, Inc.
+ * Copyright 2004,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -25,6 +25,7 @@
#include <gr_runtime_types.h>
#include <gr_tpb_detail.h>
+#include <gr_tag_info.h>
#include <stdexcept>
/*!
@@ -88,6 +89,75 @@ class gr_block_detail {
*/
void _post(pmt::pmt_t msg);
+ // Return the number of items read on input stream which_input
+ uint64_t nitems_read(unsigned int which_input);
+
+ // Return the number of items written on output stream which_output
+ uint64_t nitems_written(unsigned int which_output);
+
+
+ /*!
+ * \brief Adds a new tag to the given output stream.
+ *
+ * This takes the input parameters and builds a PMT tuple
+ * from it. It then calls gr_buffer::add_item_tag(pmt::pmt_t t),
+ * which appends the tag onto its deque.
+ *
+ * \param which_output an integer of which output stream to attach the tag
+ * \param abs_offset a uint64 number of the absolute item number
+ * assicated with the tag. Can get from nitems_written.
+ * \param key the tag key as a PMT symbol
+ * \param value any PMT holding any value for the given key
+ * \param srcid a PMT source ID specifier
+ */
+ void add_item_tag(unsigned int which_output,
+ uint64_t abs_offset,
+ const pmt::pmt_t &key,
+ const pmt::pmt_t &value,
+ const pmt::pmt_t &srcid);
+
+ /*!
+ * \brief Given a [start,end), returns a vector of all tags in the range.
+ *
+ * Pass-through function to gr_buffer_reader to get a vector of tags
+ * in given range. Range of counts is from start to end-1.
+ *
+ * Tags are tuples of:
+ * (item count, source id, key, value)
+ *
+ * \param v a vector reference to return tags into
+ * \param which_input an integer of which input stream to pull from
+ * \param abs_start a uint64 count of the start of the range of interest
+ * \param abs_end a uint64 count of the end of the range of interest
+ */
+ void get_tags_in_range(std::vector<pmt::pmt_t> &v,
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end);
+
+ /*!
+ * \brief Given a [start,end), returns a vector of all tags in the range
+ * with a given key.
+ *
+ * Calls get_tags_in_range(which_input, abs_start, abs_end) to get a vector of
+ * tags from the buffers. This function then provides a secondary filter to
+ * the tags to extract only tags with the given 'key'.
+ *
+ * Tags are tuples of:
+ * (item count, source id, key, value)
+ *
+ * \param v a vector reference to return tags into
+ * \param which_input an integer of which input stream to pull from
+ * \param abs_start a uint64 count of the start of the range of interest
+ * \param abs_end a uint64 count of the end of the range of interest
+ * \param key a PMT symbol to select only tags of this key
+ */
+ void get_tags_in_range(std::vector<pmt::pmt_t> &v,
+ unsigned int which_input,
+ uint64_t abs_start,
+ uint64_t abs_end,
+ const pmt::pmt_t &key);
+
gr_tpb_detail d_tpb; // used by thread-per-block scheduler
int d_produce_or;
@@ -100,7 +170,6 @@ class gr_block_detail {
std::vector<gr_buffer_sptr> d_output;
bool d_done;
-
gr_block_detail (unsigned int ninputs, unsigned int noutputs);
friend class gr_tpb_detail;
diff --git a/gnuradio-core/src/lib/runtime/gr_block_executor.cc b/gnuradio-core/src/lib/runtime/gr_block_executor.cc
index 2c21a0b0f..a8d0bc1c8 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_executor.cc
+++ b/gnuradio-core/src/lib/runtime/gr_block_executor.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2008,2009 Free Software Foundation, Inc.
+ * Copyright 2004,2008,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -87,7 +87,79 @@ min_available_space (gr_block_detail *d, int output_multiple)
return min_space;
}
+static bool
+propagate_tags(gr_block::tag_propagation_policy_t policy, gr_block_detail *d,
+ const std::vector<uint64_t> &start_nitems_read, double rrate,
+ std::vector<pmt::pmt_t> &rtags)
+{
+ // Move tags downstream
+ // if a sink, we don't need to move downstream
+ if(d->sink_p()) {
+ return true;
+ }
+ switch(policy) {
+ case gr_block::TPP_DONT:
+ return true;
+ break;
+ case gr_block::TPP_ALL_TO_ALL:
+ // every tag on every input propogates to everyone downstream
+ for(int i = 0; i < d->ninputs(); i++) {
+ d->get_tags_in_range(rtags, i, start_nitems_read[i],
+ d->nitems_read(i));
+
+ std::vector<pmt::pmt_t>::iterator t;
+ if(rrate == 1.0) {
+ for(t = rtags.begin(); t != rtags.end(); t++) {
+ for(int o = 0; o < d->noutputs(); o++)
+ d->output(o)->add_item_tag(*t);
+ }
+ }
+ else {
+ for(t = rtags.begin(); t != rtags.end(); t++) {
+ uint64_t newcount = pmt::pmt_to_uint64(pmt::pmt_tuple_ref(*t, 0));
+ pmt::pmt_t newtup = pmt::mp(pmt::pmt_from_uint64(newcount * rrate),
+ pmt::pmt_tuple_ref(*t, 1),
+ pmt::pmt_tuple_ref(*t, 2),
+ pmt::pmt_tuple_ref(*t, 3));
+
+ for(int o = 0; o < d->noutputs(); o++)
+ d->output(o)->add_item_tag(newtup);
+ }
+ }
+ }
+ break;
+ case gr_block::TPP_ONE_TO_ONE:
+ // tags from input i only go to output i
+ // this requires d->ninputs() == d->noutputs; this is checked when this
+ // type of tag-propagation system is selected in gr_block_detail
+ if(d->ninputs() == d->noutputs()) {
+ for(int i = 0; i < d->ninputs(); i++) {
+ d->get_tags_in_range(rtags, i, start_nitems_read[i],
+ d->nitems_read(i));
+
+ std::vector<pmt::pmt_t>::iterator t;
+ for(t = rtags.begin(); t != rtags.end(); t++) {
+ uint64_t newcount = pmt::pmt_to_uint64(pmt::pmt_tuple_ref(*t, 0));
+ pmt::pmt_t newtup = pmt::mp(pmt::pmt_from_uint64(newcount * rrate),
+ pmt::pmt_tuple_ref(*t, 1),
+ pmt::pmt_tuple_ref(*t, 2),
+ pmt::pmt_tuple_ref(*t, 3));
+ d->output(i)->add_item_tag(newtup);
+ }
+ }
+ }
+ else {
+ std::cerr << "Error: gr_block_executor: propagation_policy 'ONE-TO-ONE' requires ninputs == noutputs" << std::endl;
+ return false;
+ }
+
+ break;
+ default:
+ return true;
+ }
+ return true;
+}
gr_block_executor::gr_block_executor (gr_block_sptr block)
: d_block(block), d_log(0)
@@ -134,6 +206,7 @@ gr_block_executor::run_one_iteration()
d_input_items.resize (0);
d_input_done.resize(0);
d_output_items.resize (d->noutputs ());
+ d_start_nitems_read.resize(0);
// determine the minimum available output space
noutput_items = min_available_space (d, m->output_multiple ());
@@ -155,6 +228,7 @@ gr_block_executor::run_one_iteration()
d_input_items.resize (d->ninputs ());
d_input_done.resize(d->ninputs());
d_output_items.resize (0);
+ d_start_nitems_read.resize(d->ninputs());
LOG(*d_log << " sink\n");
max_items_avail = 0;
@@ -198,6 +272,7 @@ gr_block_executor::run_one_iteration()
d_input_items.resize (d->ninputs ());
d_input_done.resize(d->ninputs());
d_output_items.resize (d->noutputs ());
+ d_start_nitems_read.resize(d->ninputs());
max_items_avail = 0;
for (int i = 0; i < d->ninputs (); i++){
@@ -294,12 +369,21 @@ gr_block_executor::run_one_iteration()
for (int i = 0; i < d->noutputs (); i++)
d_output_items[i] = d->output(i)->write_pointer();
+ // determine where to start looking for new tags
+ for (int i = 0; i < d->ninputs(); i++)
+ d_start_nitems_read[i] = d->nitems_read(i);
+
// Do the actual work of the block
int n = m->general_work (noutput_items, d_ninput_items,
d_input_items, d_output_items);
LOG(*d_log << " general_work: noutput_items = " << noutput_items
<< " result = " << n << std::endl);
+ if(!propagate_tags(m->tag_propagation_policy(), d,
+ d_start_nitems_read, m->relative_rate(),
+ d_returned_tags))
+ goto were_done;
+
if (n == gr_block::WORK_DONE)
goto were_done;
diff --git a/gnuradio-core/src/lib/runtime/gr_block_executor.h b/gnuradio-core/src/lib/runtime/gr_block_executor.h
index 41b5ede7c..77ace5522 100644
--- a/gnuradio-core/src/lib/runtime/gr_block_executor.h
+++ b/gnuradio-core/src/lib/runtime/gr_block_executor.h
@@ -25,6 +25,7 @@
#include <gr_runtime_types.h>
#include <fstream>
+#include <gruel/pmt.h>
//class gr_block_executor;
//typedef boost::shared_ptr<gr_block_executor> gr_block_executor_sptr;
@@ -47,6 +48,8 @@ protected:
gr_vector_const_void_star d_input_items;
std::vector<bool> d_input_done;
gr_vector_void_star d_output_items;
+ std::vector<uint64_t> d_start_nitems_read; //stores where tag counts are before work
+ std::vector<pmt::pmt_t> d_returned_tags;
public:
gr_block_executor(gr_block_sptr block);
diff --git a/gnuradio-core/src/lib/runtime/gr_buffer.cc b/gnuradio-core/src/lib/runtime/gr_buffer.cc
index db2db5d6d..fa3722714 100644
--- a/gnuradio-core/src/lib/runtime/gr_buffer.cc
+++ b/gnuradio-core/src/lib/runtime/gr_buffer.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2009 Free Software Foundation, Inc.
+ * Copyright 2004,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -31,6 +31,7 @@
#include <iostream>
#include <assert.h>
#include <algorithm>
+#include <boost/math/common_factor_rt.hpp>
static long s_buffer_count = 0; // counts for debugging storage mgmt
static long s_buffer_reader_count = 0;
@@ -73,14 +74,15 @@ static long s_buffer_reader_count = 0;
static long
minimum_buffer_items (long type_size, long page_size)
{
- return page_size / gr_gcd (type_size, page_size);
+ return page_size / boost::math::gcd (type_size, page_size);
}
gr_buffer::gr_buffer (int nitems, size_t sizeof_item, gr_block_sptr link)
: d_base (0), d_bufsize (0), d_vmcircbuf (0),
d_sizeof_item (sizeof_item), d_link(link),
- d_write_index (0), d_done (false)
+ d_write_index (0), d_abs_write_offset(0), d_done (false),
+ d_last_min_items_read(0)
{
if (!allocate_buffer (nitems, sizeof_item))
throw std::bad_alloc ();
@@ -156,8 +158,16 @@ gr_buffer::space_available ()
// Find out the maximum amount of data available to our readers
int most_data = d_readers[0]->items_available ();
- for (unsigned int i = 1; i < d_readers.size (); i++)
+ uint64_t min_items_read = d_readers[0]->nitems_read();
+ for (size_t i = 1; i < d_readers.size (); i++) {
most_data = std::max (most_data, d_readers[i]->items_available ());
+ min_items_read = std::min(min_items_read, d_readers[i]->nitems_read());
+ }
+
+ if(min_items_read != d_last_min_items_read) {
+ prune_tags(d_last_min_items_read);
+ d_last_min_items_read = min_items_read;
+ }
// The -1 ensures that the case d_write_index == d_read_index is
// unambiguous. It indicates that there is no data for the reader
@@ -177,6 +187,7 @@ gr_buffer::update_write_pointer (int nitems)
{
gruel::scoped_lock guard(*mutex());
d_write_index = index_add (d_write_index, nitems);
+ d_abs_write_offset += nitems;
}
void
@@ -215,6 +226,45 @@ gr_buffer::drop_reader (gr_buffer_reader *reader)
d_readers.erase (result);
}
+void
+gr_buffer::add_item_tag(const pmt::pmt_t &tag)
+{
+ gruel::scoped_lock guard(*mutex());
+ d_item_tags.push_back(tag);
+}
+
+void
+gr_buffer::prune_tags(uint64_t max_time)
+{
+ /* NOTE: this function _should_ lock the mutex before editing
+ d_item_tags. In practice, this function is only called at
+ runtime by min_available_space in gr_block_executor.cc,
+ which locks the mutex itself.
+
+ If this function is used elsewhere, remember to lock the
+ buffer's mutex al la the scoped_lock line below.
+ */
+ //gruel::scoped_lock guard(*mutex());
+ std::deque<pmt::pmt_t>::iterator itr = d_item_tags.begin();
+
+ uint64_t item_time;
+
+ // Since tags are not guarenteed to be in any particular order,
+ // we need to erase here instead of pop_front. An erase in the
+ // middle invalidates all iterators; so this resets the iterator
+ // to find more. Mostly, we wil be erasing from the front and
+ // therefore lose little time this way.
+ while(itr != d_item_tags.end()) {
+ item_time = pmt::pmt_to_uint64(pmt::pmt_tuple_ref(*itr, 0));
+ if(item_time < max_time) {
+ d_item_tags.erase(itr);
+ itr = d_item_tags.begin();
+ }
+ else
+ itr++;
+ }
+}
+
long
gr_buffer_ncurrently_allocated ()
{
@@ -225,7 +275,7 @@ gr_buffer_ncurrently_allocated ()
gr_buffer_reader::gr_buffer_reader(gr_buffer_sptr buffer, unsigned int read_index,
gr_block_sptr link)
- : d_buffer(buffer), d_read_index(read_index), d_link(link)
+ : d_buffer(buffer), d_read_index(read_index), d_abs_read_offset(0), d_link(link)
{
s_buffer_reader_count++;
}
@@ -253,6 +303,29 @@ gr_buffer_reader::update_read_pointer (int nitems)
{
gruel::scoped_lock guard(*mutex());
d_read_index = d_buffer->index_add (d_read_index, nitems);
+ d_abs_read_offset += nitems;
+}
+
+void
+gr_buffer_reader::get_tags_in_range(std::vector<pmt::pmt_t> &v,
+ uint64_t abs_start,
+ uint64_t abs_end)
+{
+ gruel::scoped_lock guard(*mutex());
+
+ v.resize(0);
+ std::deque<pmt::pmt_t>::iterator itr = d_buffer->get_tags_begin();
+
+ uint64_t item_time;
+ while(itr != d_buffer->get_tags_end()) {
+ item_time = pmt::pmt_to_uint64(pmt::pmt_tuple_ref(*itr, 0));
+
+ if((item_time >= abs_start) && (item_time < abs_end)) {
+ v.push_back(*itr);
+ }
+
+ itr++;
+ }
}
long
diff --git a/gnuradio-core/src/lib/runtime/gr_buffer.h b/gnuradio-core/src/lib/runtime/gr_buffer.h
index 207bfe7c5..e5725d386 100644
--- a/gnuradio-core/src/lib/runtime/gr_buffer.h
+++ b/gnuradio-core/src/lib/runtime/gr_buffer.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2004,2009 Free Software Foundation, Inc.
+ * Copyright 2004,2009,2010,2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -26,6 +26,8 @@
#include <gr_runtime_types.h>
#include <boost/weak_ptr.hpp>
#include <gruel/thread.h>
+#include <gruel/pmt.h>
+#include <deque>
class gr_vmcircbuf;
@@ -88,6 +90,26 @@ class gr_buffer {
gruel::mutex *mutex() { return &d_mutex; }
+ uint64_t nitems_written() { return d_abs_write_offset; }
+
+
+ /*!
+ * \brief Adds a new tag to the buffer.
+ *
+ * \param tag a PMT tuple containing the new tag
+ */
+ void add_item_tag(const pmt::pmt_t &tag);
+
+ /*!
+ * \brief Removes all tags before \p max_time from buffer
+ *
+ * \param max_time the time (item number) to trim up until.
+ */
+ void prune_tags(uint64_t max_time);
+
+ std::deque<pmt::pmt_t>::iterator get_tags_begin() { return d_item_tags.begin(); }
+ std::deque<pmt::pmt_t>::iterator get_tags_end() { return d_item_tags.end(); }
+
// -------------------------------------------------------------------------
private:
@@ -106,11 +128,15 @@ class gr_buffer {
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.
+ // The mutex protects d_write_index, d_abs_write_offset, d_done, d_item_tags
+ // and the d_read_index's and d_abs_read_offset's in the buffer readers.
//
gruel::mutex d_mutex;
unsigned int d_write_index; // in items [0,d_bufsize)
+ uint64_t d_abs_write_offset; // num items written since the start
bool d_done;
+ std::deque<pmt::pmt_t> d_item_tags;
+ uint64_t d_last_min_items_read;
unsigned
index_add (unsigned a, unsigned b)
@@ -220,11 +246,31 @@ class gr_buffer_reader {
gruel::mutex *mutex() { return d_buffer->mutex(); }
+ uint64_t nitems_read() { return d_abs_read_offset; }
+
/*!
* \brief Return the block that reads via this reader.
+ *
*/
gr_block_sptr link() { return gr_block_sptr(d_link); }
+
+ /*!
+ * \brief Given a [start,end), returns a vector all tags in the range.
+ *
+ * Get a vector of tags in given range. Range of counts is from start to end-1.
+ *
+ * Tags are tuples of:
+ * (item count, source id, key, value)
+ *
+ * \param v a vector reference to return tags into
+ * \param abs_start a uint64 count of the start of the range of interest
+ * \param abs_end a uint64 count of the end of the range of interest
+ */
+ void get_tags_in_range(std::vector<pmt::pmt_t> &v,
+ uint64_t abs_start,
+ uint64_t abs_end);
+
// -------------------------------------------------------------------------
private:
@@ -236,6 +282,7 @@ class gr_buffer_reader {
gr_buffer_sptr d_buffer;
unsigned int d_read_index; // in items [0,d->buffer.d_bufsize)
+ uint64_t d_abs_read_offset; // num items seen since the start
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
diff --git a/gnuradio-core/src/lib/runtime/gr_error_handler.cc b/gnuradio-core/src/lib/runtime/gr_error_handler.cc
index 6dbb0a5d2..4b4cdacef 100644
--- a/gnuradio-core/src/lib/runtime/gr_error_handler.cc
+++ b/gnuradio-core/src/lib/runtime/gr_error_handler.cc
@@ -48,7 +48,6 @@
#include <assert.h>
#include <stdexcept>
#include <unistd.h>
-#include <stdio.h>
#ifdef HAVE_IO_H
#include <io.h>
diff --git a/gnuradio-core/src/lib/runtime/gr_error_handler.h b/gnuradio-core/src/lib/runtime/gr_error_handler.h
index 530a2c23c..aedb6f41f 100644
--- a/gnuradio-core/src/lib/runtime/gr_error_handler.h
+++ b/gnuradio-core/src/lib/runtime/gr_error_handler.h
@@ -45,6 +45,7 @@
#include <stdarg.h>
#include <string>
+#include <cstdio> // for FILE
/*!
* \brief abstract error handler
diff --git a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc
index 031eb6dfd..5d1057e0f 100644
--- a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc
+++ b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc
@@ -264,16 +264,13 @@ void gr_flat_flowgraph::dump()
int no = detail->noutputs();
for (int i = 0; i < no; i++) {
gr_buffer_sptr buffer = detail->output(i);
- std::cout << " output " << i << ": " << buffer
- << " space=" << buffer->space_available() << std::endl;
+ std::cout << " output " << i << ": " << buffer << std::endl;
}
for (int i = 0; i < ni; i++) {
gr_buffer_reader_sptr reader = detail->input(i);
std::cout << " reader " << i << ": " << reader
- << " reading from buffer=" << reader->buffer()
- << " avail=" << reader->items_available() << " items"
- << std::endl;
+ << " reading from buffer=" << reader->buffer() << std::endl;
}
}
diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc
index 27f6257cc..0d3bbb011 100644
--- a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc
+++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2007 Free Software Foundation, Inc.
+ * Copyright 2007,2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -28,6 +28,7 @@
#include <gr_io_signature.h>
#include <stdexcept>
#include <sstream>
+#include <iterator>
#define GR_FLOWGRAPH_DEBUG 0
diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc
index e3a25e1a8..d6e317136 100644
--- a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc
+++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc
@@ -61,6 +61,11 @@ gr_hier_block2::self()
return shared_from_this();
}
+gr_hier_block2_sptr
+gr_hier_block2::to_hier_block2()
+{
+ return cast_to_hier_block2_sptr(shared_from_this());
+}
void
gr_hier_block2::connect(gr_basic_block_sptr block)
diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.h b/gnuradio-core/src/lib/runtime/gr_hier_block2.h
index f50b1cb94..0a40c36b7 100644
--- a/gnuradio-core/src/lib/runtime/gr_hier_block2.h
+++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.h
@@ -147,6 +147,8 @@ public:
// This is a public method for ease of code organization, but should be
// ignored by the user.
gr_flat_flowgraph_sptr flatten() const;
+
+ gr_hier_block2_sptr to_hier_block2(); // Needed for Python/Guile type coercion
};
inline gr_hier_block2_sptr cast_to_hier_block2_sptr(gr_basic_block_sptr block) {
diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.i b/gnuradio-core/src/lib/runtime/gr_hier_block2.i
index a62f50e84..32b656e24 100644
--- a/gnuradio-core/src/lib/runtime/gr_hier_block2.i
+++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.i
@@ -34,6 +34,11 @@ gr_hier_block2_sptr gr_make_hier_block2(const std::string name,
gr_io_signature_sptr output_signature)
throw (std::runtime_error);
+// Rename connect and disconnect so that we can more easily build a
+// better interface in scripting land.
+%rename(primitive_connect) gr_hier_block2::connect;
+%rename(primitive_disconnect) gr_hier_block2::disconnect;
+
class gr_hier_block2 : public gr_basic_block
{
private:
@@ -57,4 +62,6 @@ public:
void disconnect_all();
void lock();
void unlock();
+
+ gr_hier_block2_sptr to_hier_block2(); // Needed for Python/Guile type coercion
};
diff --git a/gnuradio-core/src/lib/runtime/gr_msg_queue.i b/gnuradio-core/src/lib/runtime/gr_msg_queue.i
index 9ca92b6ec..c9214bef3 100644
--- a/gnuradio-core/src/lib/runtime/gr_msg_queue.i
+++ b/gnuradio-core/src/lib/runtime/gr_msg_queue.i
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2005,2009 Free Software Foundation, Inc.
+ * Copyright 2005,2009,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -81,6 +81,7 @@ public:
* functions into the gr.msg_queue wrapper class, so that everything
* appears normal. (An evil laugh is heard in the distance...)
*/
+#ifdef SWIGPYTHON
%inline %{
gr_message_sptr gr_py_msg_queue__delete_head(gr_msg_queue_sptr q) {
gr_message_sptr msg;
@@ -103,3 +104,65 @@ gr_msg_queue_sptr.delete_head = gr_py_msg_queue__delete_head
gr_msg_queue_sptr.insert_tail = gr_py_msg_queue__insert_tail
gr_msg_queue_sptr.handle = gr_py_msg_queue__insert_tail
%}
+#endif // SWIGPYTHON
+
+/*
+ * Similar trickery as above, only this time for Guile
+ */
+#ifdef SWIGGUILE
+
+%{
+ struct arg_holder {
+ gr_msg_queue_sptr q;
+ gr_message_sptr msg;
+ };
+
+ static void *
+ insert_tail_shim(void *arg)
+ {
+ arg_holder *a = (arg_holder *)arg;
+ a->q->insert_tail(a->msg);
+ return 0;
+ }
+
+ static void *
+ delete_head_shim(void *arg)
+ {
+ arg_holder *a = (arg_holder *)arg;
+ a->msg = a->q->delete_head();
+ return 0;
+ }
+%}
+
+%inline %{
+
+ // handle and insert_tail are equivalent
+ static void
+ handle(gr_msg_queue_sptr q, gr_message_sptr msg)
+ {
+ arg_holder a;
+ a.q = q;
+ a.msg = msg;
+ scm_without_guile(insert_tail_shim, (void *) &a);
+ }
+
+ static void
+ insert_tail(gr_msg_queue_sptr q, gr_message_sptr msg)
+ {
+ arg_holder a;
+ a.q = q;
+ a.msg = msg;
+ scm_without_guile(insert_tail_shim, (void *) &a);
+ }
+
+ static gr_message_sptr
+ delete_head(gr_msg_queue_sptr q)
+ {
+ arg_holder a;
+ a.q = q;
+ scm_without_guile(delete_head_shim, (void *) &a);
+ return a.msg;
+ }
+%}
+
+#endif // SWIGGUILE
diff --git a/gnuradio-core/src/lib/runtime/gr_preferences.cc b/gnuradio-core/src/lib/runtime/gr_preferences.cc
index 5f7412248..c2ca047a8 100644
--- a/gnuradio-core/src/lib/runtime/gr_preferences.cc
+++ b/gnuradio-core/src/lib/runtime/gr_preferences.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2003,2010 Free Software Foundation, Inc.
+ * Copyright 2003,2010,2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -25,6 +25,7 @@
#endif
#include <gr_preferences.h>
+#include <gr_sys_paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -33,12 +34,9 @@
#include <unistd.h>
#include <string.h>
-
-#ifdef MKDIR_TAKES_ONE_ARG
-#define gr_mkdir(pathname, mode) mkdir(pathname)
-#else
-#define gr_mkdir(pathname, mode) mkdir((pathname), (mode))
-#endif
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
+namespace fs = boost::filesystem;
/*
* The simplest thing that could possibly work:
@@ -48,27 +46,19 @@
static const char *
pathname (const char *key)
{
- static char buf[200];
- snprintf (buf, sizeof (buf), "%s/.gnuradio/prefs/%s", getenv ("HOME"), key);
- return buf;
+ static fs::path path;
+ path = fs::path(gr_appdata_path()) / ".gnuradio" / "prefs" / key;
+ return path.string().c_str();
}
static void
ensure_dir_path ()
{
- char path[200];
- struct stat statbuf;
-
- snprintf (path, sizeof (path), "%s/.gnuradio/prefs", getenv ("HOME"));
- if (stat (path, &statbuf) == 0 && S_ISDIR (statbuf.st_mode))
- return;
-
- // blindly try to make it // FIXME make this robust. C++ SUCKS!
+ fs::path path = fs::path(gr_appdata_path()) / ".gnuradio";
+ if (!fs::is_directory(path)) fs::create_directory(path);
- snprintf (path, sizeof (path), "%s/.gnuradio", getenv ("HOME"));
- gr_mkdir (path, 0750);
- snprintf (path, sizeof (path), "%s/.gnuradio/prefs", getenv ("HOME"));
- gr_mkdir (path, 0750);
+ path = path / "prefs";
+ if (!fs::is_directory(path)) fs::create_directory(path);
}
const char *
diff --git a/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.i b/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.i
index 5e9032449..2378a1880 100644
--- a/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.i
+++ b/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.i
@@ -42,6 +42,7 @@ class gr_single_threaded_scheduler {
gr_single_threaded_scheduler (const std::vector<gr_block_sptr> &modules);
};
+#ifdef SWIGPYTHON
%inline %{
void sts_pyrun (gr_single_threaded_scheduler_sptr s) {
Py_BEGIN_ALLOW_THREADS; // release global interpreter lock
@@ -49,3 +50,5 @@ class gr_single_threaded_scheduler {
Py_END_ALLOW_THREADS; // acquire global interpreter lock
}
%}
+#endif
+
diff --git a/gnuradio-core/src/lib/runtime/gr_sync_block.h b/gnuradio-core/src/lib/runtime/gr_sync_block.h
index 3a5d89d19..c5a6a50f1 100644
--- a/gnuradio-core/src/lib/runtime/gr_sync_block.h
+++ b/gnuradio-core/src/lib/runtime/gr_sync_block.h
@@ -34,7 +34,7 @@
class gr_sync_block : public gr_block
{
protected:
-
+ gr_sync_block (void){} //allows pure virtual interface sub-classes
gr_sync_block (const std::string &name,
gr_io_signature_sptr input_signature,
gr_io_signature_sptr output_signature);
diff --git a/gnuradio-core/src/lib/runtime/gr_sys_paths.cc b/gnuradio-core/src/lib/runtime/gr_sys_paths.cc
new file mode 100644
index 000000000..9d10a3ccd
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/gr_sys_paths.cc
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <gr_sys_paths.h>
+#include <cstdlib> //getenv
+#include <cstdio> //P_tmpdir (maybe)
+
+const char *gr_tmp_path(){
+ const char *path;
+
+ //first case, try TMP environment variable
+ path = getenv("TMP");
+ if (path) return path;
+
+ //second case, try P_tmpdir when its defined
+ #ifdef P_tmpdir
+ if (P_tmpdir) return P_tmpdir;
+ #endif /*P_tmpdir*/
+
+ //fall-through case, nothing worked
+ return "/tmp";
+}
+
+const char *gr_appdata_path(){
+ const char *path;
+
+ //first case, try HOME environment variable (unix)
+ path = getenv("HOME");
+ if (path) return path;
+
+ //second case, try APPDATA environment variable (windows)
+ path = getenv("APPDATA");
+ if (path) return path;
+
+ //fall-through case, nothing worked
+ return gr_tmp_path();
+}
diff --git a/gnuradio-core/src/lib/runtime/gr_tmp_path.h b/gnuradio-core/src/lib/runtime/gr_sys_paths.h
index 3d02043c7..aa8249775 100644
--- a/gnuradio-core/src/lib/runtime/gr_tmp_path.h
+++ b/gnuradio-core/src/lib/runtime/gr_sys_paths.h
@@ -1,6 +1,5 @@
-/* -*- c++ -*- */
/*
- * Copyright 2003 Free Software Foundation, Inc.
+ * Copyright 2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -20,12 +19,13 @@
* Boston, MA 02110-1301, USA.
*/
-#ifndef _GR_TMP_PATH_H_
-#define _GR_TMP_PATH_H_
+#ifndef _GR_SYS_PATHS_H_
+#define _GR_SYS_PATHS_H_
-/*!
- * \brief return directory portion of pathname used for temporary files.
- */
-const char *gr_tmp_path ();
+//! directory to create temporary files
+const char *gr_tmp_path();
+
+//! directory to store application data
+const char *gr_appdata_path();
-#endif /* _GR_TMP_PATH_H_ */
+#endif /* _GR_SYS_PATHS_H_ */
diff --git a/gnuradio-core/src/lib/runtime/gr_tag_info.cc b/gnuradio-core/src/lib/runtime/gr_tag_info.cc
new file mode 100644
index 000000000..f15329f9b
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/gr_tag_info.cc
@@ -0,0 +1,38 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gr_tag_info.h>
+#include <gruel/pmt.h>
+
+namespace gr_tags {
+/*
+ const pmt::pmt_t key_time = pmt::pmt_string_to_symbol("time");
+ const pmt::pmt_t key_sample_rate = pmt::pmt_string_to_symbol("sample_rate");
+ const pmt::pmt_t key_frequency = pmt::pmt_string_to_symbol("frequency");
+ const pmt::pmt_t key_rssi = pmt::pmt_string_to_symbol("rssi");
+ const pmt::pmt_t key_rx_gain = pmt::pmt_string_to_symbol("gain");
+*/
+}
diff --git a/gnuradio-core/src/lib/runtime/gr_tag_info.h b/gnuradio-core/src/lib/runtime/gr_tag_info.h
new file mode 100644
index 000000000..5a1e1555a
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/gr_tag_info.h
@@ -0,0 +1,87 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GR_TAG_INFO_H
+#define INCLUDED_GR_TAG_INFO_H
+
+#include <gruel/pmt.h>
+
+namespace gr_tags {
+
+ enum {
+ TAG_NITEM_REF = 0,
+ TAG_SRCID_REF,
+ TAG_KEY_REF,
+ TAG_VALUE_REF
+ };
+
+ /*
+ extern const pmt::pmt_t key_time;
+ extern const pmt::pmt_t key_sample_rate;
+ extern const pmt::pmt_t key_frequency;
+ extern const pmt::pmt_t key_rssi;
+ extern const pmt::pmt_t key_gain;
+ */
+
+ /*!
+ * \brief Returns the item \p tag occurred at (as a uint64_t)
+ */
+ static inline uint64_t
+ get_nitems(const pmt::pmt_t &tag) {
+ return pmt::pmt_to_uint64(pmt::pmt_tuple_ref(tag, TAG_NITEM_REF));
+ }
+
+ /*!
+ * \brief Returns the source ID of \p tag (as a PMT)
+ */
+ static inline pmt::pmt_t
+ get_srcid(const pmt::pmt_t &tag) {
+ return pmt::pmt_tuple_ref(tag, TAG_SRCID_REF);
+ }
+
+ /*!
+ * \brief Returns the key of \p tag (as a PMT symbol)
+ */
+ static inline pmt::pmt_t
+ get_key(const pmt::pmt_t &tag) {
+ return pmt::pmt_tuple_ref(tag, TAG_KEY_REF);
+ }
+
+ /*!
+ * \brief Returns the value of \p tag (as a PMT)
+ */
+ static inline pmt::pmt_t
+ get_value(const pmt::pmt_t &tag) {
+ return pmt::pmt_tuple_ref(tag, TAG_VALUE_REF);
+ }
+
+ /*!
+ * \brief Comparison function to test which tag, \p x or \p y, came first in time
+ */
+ static inline bool
+ nitems_compare(pmt::pmt_t x, pmt::pmt_t y) {
+ return get_nitems(x) < get_nitems(y);
+ }
+
+}; /* namespace tags */
+
+#endif /* GR_TAG_INFO */
diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.cc b/gnuradio-core/src/lib/runtime/gr_top_block.cc
index 09e46dfbb..f341525c0 100644
--- a/gnuradio-core/src/lib/runtime/gr_top_block.cc
+++ b/gnuradio-core/src/lib/runtime/gr_top_block.cc
@@ -95,3 +95,9 @@ gr_top_block::dump()
{
d_impl->dump();
}
+
+gr_top_block_sptr
+gr_top_block::to_top_block()
+{
+ return cast_to_top_block_sptr(shared_from_this());
+}
diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.h b/gnuradio-core/src/lib/runtime/gr_top_block.h
index 8052954e3..ed244cb7c 100644
--- a/gnuradio-core/src/lib/runtime/gr_top_block.h
+++ b/gnuradio-core/src/lib/runtime/gr_top_block.h
@@ -105,6 +105,13 @@ public:
* Displays flattened flowgraph edges and block connectivity
*/
void dump();
+
+ gr_top_block_sptr to_top_block(); // Needed for Python/Guile type coercion
};
+inline gr_top_block_sptr cast_to_top_block_sptr(gr_basic_block_sptr block) {
+ return boost::dynamic_pointer_cast<gr_top_block, gr_basic_block>(block);
+}
+
+
#endif /* INCLUDED_GR_TOP_BLOCK_H */
diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.i b/gnuradio-core/src/lib/runtime/gr_top_block.i
index 670e5b5e5..90fa18b94 100644
--- a/gnuradio-core/src/lib/runtime/gr_top_block.i
+++ b/gnuradio-core/src/lib/runtime/gr_top_block.i
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2007,2008 Free Software Foundation, Inc.
+ * Copyright 2007,2008,2010 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -42,13 +42,17 @@ public:
void start() throw (std::runtime_error);
void stop();
- void wait();
- void run();
+ //void wait();
+ //void run() throw (std::runtime_error);
void lock();
void unlock() throw (std::runtime_error);
void dump();
+
+ gr_top_block_sptr to_top_block(); // Needed for Python/Guile type coercion
};
+#ifdef SWIGPYTHON
+
%inline %{
void top_block_run_unlocked(gr_top_block_sptr r) throw (std::runtime_error)
{
@@ -64,3 +68,36 @@ void top_block_wait_unlocked(gr_top_block_sptr r) throw (std::runtime_error)
Py_END_ALLOW_THREADS; // acquire global interpreter lock
}
%}
+
+#endif
+
+#ifdef SWIGGUILE
+
+%{
+ struct tb_arg_holder {
+ gr_top_block_sptr tb;
+ };
+
+ static void *
+ tb_wait_shim(void *arg)
+ {
+ tb_arg_holder *a = (tb_arg_holder *)arg;
+ a->tb->wait();
+ return 0;
+ }
+
+%}
+
+%inline %{
+
+ static void
+ top_block_wait_unlocked(gr_top_block_sptr r) throw (std::runtime_error)
+ {
+ tb_arg_holder a;
+ a.tb = r;
+ scm_without_guile(tb_wait_shim, (void *) &a);
+ }
+
+%}
+
+#endif
diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc
index 03eef17d9..faa888697 100644
--- a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc
+++ b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2008,2009 Free Software Foundation, Inc.
+ * Copyright 2008,2009,2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -43,7 +43,7 @@ gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block)
// handle any queued up messages
while ((msg = d->d_tpb.delete_head_nowait()))
- block->handle_msg(msg);
+ block->dispatch_msg(msg);
d->d_tpb.clear_changed();
s = d_exec.run_one_iteration();
@@ -73,7 +73,7 @@ gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block)
// handle all pending messages
while ((msg = d->d_tpb.delete_head_nowait_already_holding_mutex())){
guard.unlock(); // release lock while processing msg
- block->handle_msg(msg);
+ block->dispatch_msg(msg);
guard.lock();
}
}
@@ -93,7 +93,7 @@ gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block)
// handle all pending messages
while ((msg = d->d_tpb.delete_head_nowait_already_holding_mutex())){
guard.unlock(); // release lock while processing msg
- block->handle_msg(msg);
+ block->dispatch_msg(msg);
guard.lock();
}
}
diff --git a/gnuradio-core/src/lib/runtime/gr_unittests.h b/gnuradio-core/src/lib/runtime/gr_unittests.h
index 70aa6f294..59149bb2e 100644
--- a/gnuradio-core/src/lib/runtime/gr_unittests.h
+++ b/gnuradio-core/src/lib/runtime/gr_unittests.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2010 Free Software Foundation, Inc.
+ * Copyright 2010,2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -31,37 +31,11 @@
#include <sys/stat.h>
#include <unistd.h>
+#include <boost/filesystem/operations.hpp>
+#include <boost/filesystem/path.hpp>
-#ifdef MKDIR_TAKES_ONE_ARG
-#define gr_mkdir(pathname, mode) mkdir(pathname)
-#else
-#define gr_mkdir(pathname, mode) mkdir((pathname), (mode))
-#endif
-
-/*
- * Mostly taken from gr_preferences.cc/h
- * The simplest thing that could possibly work:
- * the key is the filename; the value is the file contents.
- */
-
-static void
-ensure_unittest_path (const char *path)
-{
- struct stat statbuf;
- if (stat (path, &statbuf) == 0 && S_ISDIR (statbuf.st_mode))
- return;
-
- // blindly try to make it // FIXME make this robust. C++ SUCKS!
- gr_mkdir (path, 0750);
+static std::string get_unittest_path(const std::string &filename){
+ boost::filesystem::path path = boost::filesystem::current_path() / ".unittests";
+ if (!boost::filesystem::is_directory(path)) boost::filesystem::create_directory(path);
+ return (path / filename).string();
}
-
-static void
-get_unittest_path (const char *filename, char *fullpath, size_t pathsize)
-{
- char path[200];
- snprintf (path, sizeof(path), "./.unittests");
- snprintf (fullpath, pathsize, "%s/%s", path, filename);
-
- ensure_unittest_path(path);
-}
-
diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.cc b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.cc
index 65fe0c488..42c459484 100644
--- a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.cc
+++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2003,2005 Free Software Foundation, Inc.
+ * Copyright 2003,2005,2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -36,7 +36,6 @@
#include <errno.h>
#include <stdio.h>
#include <gr_pagesize.h>
-#include <gr_tmp_path.h>
#include <gr_vmcircbuf_createfilemapping.h>
#ifdef HAVE_CREATEFILEMAPPING
diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.cc b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.cc
index 3017036ef..4f7ae39cd 100644
--- a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.cc
+++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2003 Free Software Foundation, Inc.
+ * Copyright 2003,2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -37,7 +37,7 @@
#include <errno.h>
#include <stdio.h>
#include <gr_pagesize.h>
-#include <gr_tmp_path.h>
+#include <gr_sys_paths.h>
gr_vmcircbuf_mmap_shm_open::gr_vmcircbuf_mmap_shm_open (int size)
diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc
index faae4b396..ee8b0c485 100644
--- a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc
+++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2003 Free Software Foundation, Inc.
+ * Copyright 2003,2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -39,7 +39,7 @@
#include <stdio.h>
#include <string.h>
#include <gr_pagesize.h>
-#include <gr_tmp_path.h>
+#include <gr_sys_paths.h>
gr_vmcircbuf_mmap_tmpfile::gr_vmcircbuf_mmap_tmpfile (int size)
: gr_vmcircbuf (size)
diff --git a/gnuradio-core/src/lib/runtime/qa_block_tags.cc b/gnuradio-core/src/lib/runtime/qa_block_tags.cc
new file mode 100644
index 000000000..07ce5c276
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/qa_block_tags.cc
@@ -0,0 +1,450 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <qa_block_tags.h>
+#include <gr_block.h>
+#include <gr_top_block.h>
+#include <gr_null_source.h>
+#include <gr_null_sink.h>
+#include <gr_head.h>
+#include <gr_annotator_alltoall.h>
+#include <gr_annotator_1to1.h>
+#include <gr_keep_one_in_n.h>
+#include <gr_firdes.h>
+#include <gruel/pmt.h>
+
+
+// ----------------------------------------------------------------
+
+using namespace pmt;
+
+// set to 1 to turn on debug output
+// The debug output fully checks that the tags seen are what are expected. While
+// this behavior currently works with our implementation, there is no guarentee
+// that the tags will be coming in this specific order, so it's dangerous to
+// rely on this as a test of the tag system working. We would really want to
+// tags we know we should see and then test that they all occur once, but in no
+// particular order.
+#define QA_TAGS_DEBUG 0
+
+void
+qa_block_tags::t0 ()
+{
+ unsigned int N = 1000;
+ gr_top_block_sptr tb = gr_make_top_block("top");
+ gr_block_sptr src (gr_make_null_source(sizeof(int)));
+ gr_block_sptr head (gr_make_head(sizeof(int), N));
+ gr_block_sptr snk (gr_make_null_sink(sizeof(int)));
+
+ tb->connect(src, 0, head, 0);
+ tb->connect(head, 0, snk, 0);
+
+ //CPPUNIT_ASSERT_THROW(src->nitems_read(0), std::runtime_error);
+ //CPPUNIT_ASSERT_THROW(src->nitems_written(0), std::runtime_error);
+ CPPUNIT_ASSERT_EQUAL(src->nitems_read(0), (uint64_t)0);
+ CPPUNIT_ASSERT_EQUAL(src->nitems_written(0), (uint64_t)0);
+
+ tb->run();
+
+ CPPUNIT_ASSERT_THROW(src->nitems_read(0), std::invalid_argument);
+ CPPUNIT_ASSERT(src->nitems_written(0) >= N);
+ CPPUNIT_ASSERT_EQUAL(snk->nitems_read(0), (uint64_t)1000);
+ CPPUNIT_ASSERT_THROW(snk->nitems_written(0), std::invalid_argument);
+}
+
+
+void
+qa_block_tags::t1 ()
+{
+ int N = 40000;
+ gr_top_block_sptr tb = gr_make_top_block("top");
+ gr_block_sptr src (gr_make_null_source(sizeof(int)));
+ gr_block_sptr head (gr_make_head(sizeof(int), N));
+ gr_annotator_alltoall_sptr ann0 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann1 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann2 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann3 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann4 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_block_sptr snk0 (gr_make_null_sink(sizeof(int)));
+ gr_block_sptr snk1 (gr_make_null_sink(sizeof(int)));
+
+ tb->connect(src, 0, head, 0);
+ tb->connect(head, 0, ann0, 0);
+
+ tb->connect(ann0, 0, ann1, 0);
+ tb->connect(ann0, 1, ann2, 0);
+ tb->connect(ann1, 0, ann3, 0);
+ tb->connect(ann2, 0, ann4, 0);
+
+ tb->connect(ann3, 0, snk0, 0);
+ tb->connect(ann4, 0, snk1, 0);
+
+ tb->run();
+
+ std::vector<pmt::pmt_t> tags0 = ann0->data();
+ std::vector<pmt::pmt_t> tags3 = ann3->data();
+ std::vector<pmt::pmt_t> tags4 = ann4->data();
+
+ // The first annotator does not receive any tags from the null sink upstream
+ CPPUNIT_ASSERT_EQUAL(tags0.size(), (size_t)0);
+ CPPUNIT_ASSERT_EQUAL(tags3.size(), (size_t)8);
+ CPPUNIT_ASSERT_EQUAL(tags4.size(), (size_t)8);
+
+#if QA_TAGS_DEBUG
+ // Kludge together the tags that we know should result from the above graph
+ std::stringstream str0, str1, str2;
+ str0 << ann0->name() << ann0->unique_id();
+ str1 << ann1->name() << ann1->unique_id();
+ str2 << ann2->name() << ann2->unique_id();
+
+ pmt_t expected_tags3[8];
+ expected_tags3[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0));
+ expected_tags3[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0));
+ expected_tags3[2] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(1));
+ expected_tags3[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2));
+ expected_tags3[4] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(2));
+ expected_tags3[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4));
+ expected_tags3[6] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(3));
+ expected_tags3[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6));
+
+ pmt_t expected_tags4[8];
+ expected_tags4[0] = mp(pmt_from_uint64(0), mp(str2.str()), mp("seq"), mp(0));
+ expected_tags4[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1));
+ expected_tags4[2] = mp(pmt_from_uint64(10000), mp(str2.str()), mp("seq"), mp(1));
+ expected_tags4[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3));
+ expected_tags4[4] = mp(pmt_from_uint64(20000), mp(str2.str()), mp("seq"), mp(2));
+ expected_tags4[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5));
+ expected_tags4[6] = mp(pmt_from_uint64(30000), mp(str2.str()), mp("seq"), mp(3));
+ expected_tags4[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7));
+
+ std::cout << std::endl << "qa_block_tags::t1" << std::endl;
+
+ // For annotator 3, we know it gets tags from ann0 and ann1, test this
+ for(size_t i = 0; i < tags3.size(); i++) {
+ std::cout << "tags3[" << i << "] = " << tags3[i] << "\t\t" << expected_tags3[i] << std::endl;
+ CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags3[i]), pmt_write_string(expected_tags3[i]));
+ }
+
+ // For annotator 4, we know it gets tags from ann0 and ann2, test this
+ std::cout << std::endl;
+ for(size_t i = 0; i < tags4.size(); i++) {
+ std::cout << "tags4[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl;
+ CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags4[i]), pmt_write_string(expected_tags4[i]));
+ }
+#endif
+}
+
+void
+qa_block_tags::t2 ()
+{
+ int N = 40000;
+ gr_top_block_sptr tb = gr_make_top_block("top");
+ gr_block_sptr src (gr_make_null_source(sizeof(int)));
+ gr_block_sptr head (gr_make_head(sizeof(int), N));
+ gr_annotator_alltoall_sptr ann0 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann1 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann2 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann3 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann4 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_block_sptr snk0 (gr_make_null_sink(sizeof(int)));
+ gr_block_sptr snk1 (gr_make_null_sink(sizeof(int)));
+ gr_block_sptr snk2 (gr_make_null_sink(sizeof(int)));
+
+ tb->connect(src, 0, head, 0);
+ tb->connect(head, 0, ann0, 0);
+
+ tb->connect(ann0, 0, ann1, 0);
+ tb->connect(ann0, 1, ann1, 1);
+ tb->connect(ann1, 0, ann2, 0);
+ tb->connect(ann1, 1, ann3, 0);
+ tb->connect(ann1, 2, ann4, 0);
+
+ tb->connect(ann2, 0, snk0, 0);
+ tb->connect(ann3, 0, snk1, 0);
+ tb->connect(ann4, 0, snk2, 0);
+
+ tb->run();
+
+ std::vector<pmt::pmt_t> tags0 = ann0->data();
+ std::vector<pmt::pmt_t> tags1 = ann1->data();
+ std::vector<pmt::pmt_t> tags2 = ann2->data();
+ std::vector<pmt::pmt_t> tags3 = ann4->data();
+ std::vector<pmt::pmt_t> tags4 = ann4->data();
+
+ // The first annotator does not receive any tags from the null sink upstream
+ CPPUNIT_ASSERT_EQUAL(tags0.size(), (size_t)0);
+ CPPUNIT_ASSERT_EQUAL(tags1.size(), (size_t)8);
+
+ // Make sure the rest all have 12 tags
+ CPPUNIT_ASSERT_EQUAL(tags2.size(), (size_t)12);
+ CPPUNIT_ASSERT_EQUAL(tags3.size(), (size_t)12);
+ CPPUNIT_ASSERT_EQUAL(tags4.size(), (size_t)12);
+
+
+#if QA_TAGS_DEBUG
+ // Kludge together the tags that we know should result from the above graph
+ std::stringstream str0, str1;
+ str0 << ann0->name() << ann0->unique_id();
+ str1 << ann1->name() << ann1->unique_id();
+
+ pmt_t expected_tags2[12];
+ expected_tags2[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0));
+ expected_tags2[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0));
+ expected_tags2[2] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1));
+ expected_tags2[3] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(3));
+ expected_tags2[4] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2));
+ expected_tags2[5] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3));
+ expected_tags2[6] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(6));
+ expected_tags2[7] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4));
+ expected_tags2[8] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5));
+ expected_tags2[9] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(9));
+ expected_tags2[10] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6));
+ expected_tags2[11] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7));
+
+ pmt_t expected_tags4[12];
+ expected_tags4[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(2));
+ expected_tags4[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0));
+ expected_tags4[2] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1));
+ expected_tags4[3] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(5));
+ expected_tags4[4] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2));
+ expected_tags4[5] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3));
+ expected_tags4[6] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(8));
+ expected_tags4[7] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4));
+ expected_tags4[8] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5));
+ expected_tags4[9] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(11));
+ expected_tags4[10] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6));
+ expected_tags4[11] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7));
+
+ std::cout << std::endl << "qa_block_tags::t2" << std::endl;
+
+ // For annotator[2-4], we know it gets tags from ann0 and ann1
+ // but the tags from the different outputs of ann1 are different for each.
+ // Just testing ann2 and ann4; if they are correct it would be
+ // inconceivable for ann3 to have it wrong.
+ for(size_t i = 0; i < tags2.size(); i++) {
+ std::cout << "tags2[" << i << "] = " << tags2[i] << "\t\t" << expected_tags2[i] << std::endl;
+ CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags2[i]), pmt_write_string(expected_tags2[i]));
+ }
+
+ std::cout << std::endl;
+ for(size_t i = 0; i < tags4.size(); i++) {
+ std::cout << "tags2[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl;
+ CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags4[i]), pmt_write_string(expected_tags4[i]));
+ }
+#endif
+}
+
+
+void
+qa_block_tags::t3 ()
+{
+ int N = 40000;
+ gr_top_block_sptr tb = gr_make_top_block("top");
+ gr_block_sptr src (gr_make_null_source(sizeof(int)));
+ gr_block_sptr head (gr_make_head(sizeof(int), N));
+ gr_annotator_1to1_sptr ann0 (gr_make_annotator_1to1(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann1 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_alltoall_sptr ann2 (gr_make_annotator_alltoall(10000, sizeof(int)));
+ gr_annotator_1to1_sptr ann3 (gr_make_annotator_1to1(10000, sizeof(int)));
+ gr_annotator_1to1_sptr ann4 (gr_make_annotator_1to1(10000, sizeof(int)));
+ gr_block_sptr snk0 (gr_make_null_sink(sizeof(int)));
+ gr_block_sptr snk1 (gr_make_null_sink(sizeof(int)));
+
+ tb->connect(src, 0, head, 0);
+ tb->connect(head, 0, ann0, 0);
+ tb->connect(head, 0, ann0, 1);
+
+ tb->connect(ann0, 0, ann1, 0);
+ tb->connect(ann0, 1, ann2, 0);
+ tb->connect(ann1, 0, ann3, 0);
+ tb->connect(ann2, 0, ann4, 0);
+
+ tb->connect(ann3, 0, snk0, 0);
+ tb->connect(ann4, 0, snk1, 0);
+
+ tb->run();
+
+
+ std::vector<pmt::pmt_t> tags0 = ann0->data();
+ std::vector<pmt::pmt_t> tags3 = ann3->data();
+ std::vector<pmt::pmt_t> tags4 = ann4->data();
+
+ // The first annotator does not receive any tags from the null sink upstream
+ CPPUNIT_ASSERT_EQUAL(tags0.size(), (size_t)0);
+ CPPUNIT_ASSERT_EQUAL(tags3.size(), (size_t)8);
+ CPPUNIT_ASSERT_EQUAL(tags4.size(), (size_t)8);
+
+#if QA_TAGS_DEBUG
+ // Kludge together the tags that we know should result from the above graph
+ std::stringstream str0, str1, str2;
+ str0 << ann0->name() << ann0->unique_id();
+ str1 << ann1->name() << ann1->unique_id();
+ str2 << ann2->name() << ann2->unique_id();
+
+ pmt_t expected_tags3[8];
+ expected_tags3[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0));
+ expected_tags3[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0));
+ expected_tags3[2] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(1));
+ expected_tags3[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2));
+ expected_tags3[4] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(2));
+ expected_tags3[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4));
+ expected_tags3[6] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(3));
+ expected_tags3[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6));
+
+ pmt_t expected_tags4[8];
+ expected_tags4[0] = mp(pmt_from_uint64(0), mp(str2.str()), mp("seq"), mp(0));
+ expected_tags4[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1));
+ expected_tags4[2] = mp(pmt_from_uint64(10000), mp(str2.str()), mp("seq"), mp(1));
+ expected_tags4[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3));
+ expected_tags4[4] = mp(pmt_from_uint64(20000), mp(str2.str()), mp("seq"), mp(2));
+ expected_tags4[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5));
+ expected_tags4[6] = mp(pmt_from_uint64(30000), mp(str2.str()), mp("seq"), mp(3));
+ expected_tags4[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7));
+
+ std::cout << std::endl << "qa_block_tags::t3" << std::endl;
+
+ // For annotator 3, we know it gets tags from ann0 and ann1, test this
+ for(size_t i = 0; i < tags3.size(); i++) {
+ std::cout << "tags3[" << i << "] = " << tags3[i] << "\t\t" << expected_tags3[i] << std::endl;
+ CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags3[i]), pmt_write_string(expected_tags3[i]));
+ }
+
+ // For annotator 4, we know it gets tags from ann0 and ann2, test this
+ std::cout << std::endl;
+ for(size_t i = 0; i < tags4.size(); i++) {
+ std::cout << "tags4[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl;
+ CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags4[i]), pmt_write_string(expected_tags4[i]));
+ }
+#endif
+}
+
+
+void
+qa_block_tags::t4 ()
+{
+ int N = 40000;
+ gr_top_block_sptr tb = gr_make_top_block("top");
+ gr_block_sptr src (gr_make_null_source(sizeof(int)));
+ gr_block_sptr head (gr_make_head(sizeof(int), N));
+ gr_annotator_1to1_sptr ann0 (gr_make_annotator_1to1(10000, sizeof(int)));
+ gr_annotator_1to1_sptr ann1 (gr_make_annotator_1to1(10000, sizeof(int)));
+ gr_annotator_1to1_sptr ann2 (gr_make_annotator_1to1(10000, sizeof(int)));
+ gr_block_sptr snk0 (gr_make_null_sink(sizeof(int)));
+ gr_block_sptr snk1 (gr_make_null_sink(sizeof(int)));
+
+ // using 1-to-1 tag propagation without having equal number of
+ // ins and outs. Make sure this works; will just exit run early.
+ tb->connect(src, 0, head, 0);
+ tb->connect(head, 0, ann0, 0);
+ tb->connect(ann0, 0, ann1, 0);
+ tb->connect(ann0, 1, ann2, 0);
+ tb->connect(ann1, 0, snk0, 0);
+ tb->connect(ann2, 0, snk1, 0);
+
+ std::cerr << std::endl
+ << "NOTE: This is supposed to produce an error from gr_block_executor"
+ << std::endl;
+ tb->run();
+}
+
+
+void
+qa_block_tags::t5 ()
+{
+ int N = 40000;
+ gr_top_block_sptr tb = gr_make_top_block("top");
+ gr_block_sptr src (gr_make_null_source(sizeof(float)));
+ gr_block_sptr head (gr_make_head(sizeof(float), N));
+ gr_annotator_alltoall_sptr ann0 (gr_make_annotator_alltoall(10000, sizeof(float)));
+ gr_annotator_alltoall_sptr ann1 (gr_make_annotator_alltoall(10000, sizeof(float)));
+ gr_annotator_alltoall_sptr ann2 (gr_make_annotator_alltoall(1000, sizeof(float)));
+ gr_block_sptr snk0 (gr_make_null_sink(sizeof(float)));
+
+ // Rate change blocks
+ gr_keep_one_in_n_sptr dec10 (gr_make_keep_one_in_n(sizeof(float), 10));
+
+ tb->connect(src, 0, head, 0);
+ tb->connect(head, 0, ann0, 0);
+ tb->connect(ann0, 0, ann1, 0);
+ tb->connect(ann1, 0, dec10, 0);
+ tb->connect(dec10, 0, ann2, 0);
+ tb->connect(ann2, 0, snk0, 0);
+
+ tb->run();
+
+ std::vector<pmt::pmt_t> tags0 = ann0->data();
+ std::vector<pmt::pmt_t> tags1 = ann1->data();
+ std::vector<pmt::pmt_t> tags2 = ann2->data();
+
+ // The first annotator does not receive any tags from the null sink upstream
+ CPPUNIT_ASSERT_EQUAL(tags0.size(), (size_t)0);
+ CPPUNIT_ASSERT_EQUAL(tags1.size(), (size_t)4);
+ CPPUNIT_ASSERT_EQUAL(tags2.size(), (size_t)8);
+
+
+#if QA_TAGS_DEBUG
+ // Kludge together the tags that we know should result from the above graph
+ std::stringstream str0, str1, str2;
+ str0 << ann0->name() << ann0->unique_id();
+ str1 << ann1->name() << ann1->unique_id();
+ str2 << ann2->name() << ann2->unique_id();
+
+ pmt_t expected_tags1[5];
+ expected_tags1[0] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0));
+ expected_tags1[1] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(1));
+ expected_tags1[2] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(2));
+ expected_tags1[3] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(3));
+
+ pmt_t expected_tags2[10];
+ expected_tags2[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0));
+ expected_tags2[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0));
+ expected_tags2[2] = mp(pmt_from_uint64(1000), mp(str1.str()), mp("seq"), mp(1));
+ expected_tags2[3] = mp(pmt_from_uint64(1000), mp(str0.str()), mp("seq"), mp(1));
+ expected_tags2[4] = mp(pmt_from_uint64(2000), mp(str1.str()), mp("seq"), mp(2));
+ expected_tags2[5] = mp(pmt_from_uint64(2000), mp(str0.str()), mp("seq"), mp(2));
+ expected_tags2[6] = mp(pmt_from_uint64(3000), mp(str1.str()), mp("seq"), mp(3));
+ expected_tags2[7] = mp(pmt_from_uint64(3000), mp(str0.str()), mp("seq"), mp(3));
+ expected_tags2[8] = mp(pmt_from_uint64(4000), mp(str1.str()), mp("seq"), mp(4));
+ expected_tags2[9] = mp(pmt_from_uint64(4000), mp(str0.str()), mp("seq"), mp(4));
+
+ std::cout << std::endl << "qa_block_tags::t5" << std::endl;
+
+ // annotator 1 gets tags from annotator 0
+ std::cout << "tags1.size(): " << tags1.size() << std::endl;
+ for(size_t i = 0; i < tags1.size(); i++) {
+ std::cout << "tags1[" << i << "] = " << tags1[i] << "\t\t" << expected_tags1[i] << std::endl;
+ CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags1[i]), pmt_write_string(expected_tags1[i]));
+ }
+
+ // annotator 2 gets tags from annotators 0 and 1
+ std::cout << std::endl;
+ std::cout << "tags2.size(): " << tags2.size() << std::endl;
+ for(size_t i = 0; i < tags2.size(); i++) {
+ std::cout << "tags2[" << i << "] = " << tags2[i] << "\t\t" << expected_tags2[i] << std::endl;
+ CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags2[i]), pmt_write_string(expected_tags2[i]));
+ }
+#endif
+}
+
diff --git a/gnuradio-core/src/lib/runtime/qa_block_tags.h b/gnuradio-core/src/lib/runtime/qa_block_tags.h
new file mode 100644
index 000000000..b0d211390
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/qa_block_tags.h
@@ -0,0 +1,52 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2010 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_QA_BLOCK_TAGS_H
+#define INCLUDED_QA_BLOCK_TAGS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+#include <stdexcept>
+
+class qa_block_tags : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE (qa_block_tags);
+ CPPUNIT_TEST (t0);
+ CPPUNIT_TEST (t1);
+ CPPUNIT_TEST (t2);
+ CPPUNIT_TEST (t3);
+ CPPUNIT_TEST (t4);
+ CPPUNIT_TEST (t5);
+ CPPUNIT_TEST_SUITE_END ();
+
+ private:
+ void t0 ();
+ void t1 ();
+ void t2 ();
+ void t3 ();
+ void t4 ();
+ void t5 ();
+
+};
+
+
+#endif /* INCLUDED_QA_BLOCK_TAGS_H */
diff --git a/gnuradio-core/src/lib/runtime/qa_runtime.cc b/gnuradio-core/src/lib/runtime/qa_runtime.cc
index 31e3a82d6..c0bee8ea0 100644
--- a/gnuradio-core/src/lib/runtime/qa_runtime.cc
+++ b/gnuradio-core/src/lib/runtime/qa_runtime.cc
@@ -1,5 +1,5 @@
/*
- * Copyright 2002,2007 Free Software Foundation, Inc.
+ * Copyright 2002,2007,2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -38,6 +38,8 @@
#include <qa_gr_hier_block2.h>
#include <qa_gr_hier_block2_derived.h>
#include <qa_gr_buffer.h>
+#include <qa_block_tags.h>
+#include <qa_set_msg_handler.h>
CppUnit::TestSuite *
qa_runtime::suite ()
@@ -52,6 +54,8 @@ qa_runtime::suite ()
s->addTest (qa_gr_hier_block2::suite ());
s->addTest (qa_gr_hier_block2_derived::suite ());
s->addTest (qa_gr_buffer::suite ());
+ s->addTest (qa_block_tags::suite ());
+ s->addTest (qa_set_msg_handler::suite ());
return s;
}
diff --git a/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc b/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc
new file mode 100644
index 000000000..35ef5527e
--- /dev/null
+++ b/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc
@@ -0,0 +1,85 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007,2011 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qa_set_msg_handler.h>
+#include <gr_top_block.h>
+#include <gr_head.h>
+#include <gr_null_source.h>
+#include <gr_null_sink.h>
+#include <gr_nop.h>
+#include <gruel/msg_passing.h>
+#include <iostream>
+#include <boost/thread/thread.hpp>
+
+
+#define VERBOSE 0
+
+using namespace pmt;
+
+/*
+ * The gr_nop block has been instrumented so that it counts
+ * the number of messages sent to it. We use this feature
+ * to confirm that gr_nop's call to set_msg_handler is working
+ * correctly.
+ */
+
+void qa_set_msg_handler::t0()
+{
+ static const int NMSGS = 10;
+
+ if (VERBOSE) std::cout << "qa_set_msg_handler::t0()\n";
+
+ gr_top_block_sptr tb = gr_make_top_block("top");
+
+ gr_block_sptr src = gr_make_null_source(sizeof(int));
+ gr_nop_sptr nop = gr_make_nop(sizeof(int));
+ gr_block_sptr dst = gr_make_null_sink(sizeof(int));
+
+ tb->connect(src, 0, nop, 0);
+ tb->connect(nop, 0, dst, 0);
+
+ // Must start graph before sending messages
+ tb->start();
+
+ // Send them...
+ for (int i = 0; i < NMSGS; i++){
+ send(nop, mp(mp("example-msg"), mp(i)));
+ }
+
+ // And send a message to null_source to confirm that the default
+ // message handling action (which should be a nop) doesn't dump
+ // core.
+ send(src, mp(mp("example-msg"), mp(0)));
+
+ // Give the messages a chance to be processed
+ boost::this_thread::sleep(boost::posix_time::milliseconds(100));
+
+ tb->stop();
+ tb->wait();
+
+ // Confirm that the nop block received the right number of messages.
+ CPPUNIT_ASSERT_EQUAL(NMSGS, nop->nmsgs_received());
+}
diff --git a/gnuradio-core/src/lib/runtime/gr_tmp_path.cc b/gnuradio-core/src/lib/runtime/qa_set_msg_handler.h
index 1f0c830cd..e73fffbcd 100644
--- a/gnuradio-core/src/lib/runtime/gr_tmp_path.cc
+++ b/gnuradio-core/src/lib/runtime/qa_set_msg_handler.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2003 Free Software Foundation, Inc.
+ * Copyright 2007,2011 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -20,33 +20,24 @@
* Boston, MA 02110-1301, USA.
*/
-#include <gr_tmp_path.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#ifndef INCLUDED_QA_SET_MSG_HANDLER_H
+#define INCLUDED_QA_SET_MSG_HANDLER_H
-const char *
-gr_tmp_path ()
-{
- static char *pp = 0;
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+#include <stdexcept>
- if (pp)
- return pp;
+class qa_set_msg_handler : public CppUnit::TestCase
+{
+ CPPUNIT_TEST_SUITE(qa_set_msg_handler);
+
+ CPPUNIT_TEST(t0);
- char *s = getenv ("TMP");
- if (s){
- pp = strdup (s);
- return pp;
- }
+ CPPUNIT_TEST_SUITE_END();
-#ifdef P_tmpdir
- if (P_tmpdir){
- pp = strdup (P_tmpdir);
- return pp;
- }
-#endif
+private:
- pp = strdup ("/tmp");
- return pp;
-}
+ void t0();
+};
+#endif /* INCLUDED_QA_SET_MSG_HANDLER_H */
diff --git a/gnuradio-core/src/lib/runtime/runtime.i b/gnuradio-core/src/lib/runtime/runtime.i
index 20cf68a03..ca89b8fbd 100644
--- a/gnuradio-core/src/lib/runtime/runtime.i
+++ b/gnuradio-core/src/lib/runtime/runtime.i
@@ -40,6 +40,13 @@
#include <gr_top_block.h>
%}
+%constant int sizeof_char = sizeof(char);
+%constant int sizeof_short = sizeof(short);
+%constant int sizeof_int = sizeof(int);
+%constant int sizeof_float = sizeof(float);
+%constant int sizeof_double = sizeof(double);
+%constant int sizeof_gr_complex = sizeof(gr_complex);
+
%include <gr_io_signature.i>
%include <gr_buffer.i>
%include <gr_basic_block.i>