summaryrefslogtreecommitdiff
path: root/mblock/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'mblock/src/lib')
-rw-r--r--mblock/src/lib/Makefile.am49
-rw-r--r--mblock/src/lib/mb_common.h24
-rw-r--r--mblock/src/lib/mb_connection.cc126
-rw-r--r--mblock/src/lib/mb_connection.h78
-rw-r--r--mblock/src/lib/mb_endpoint.h52
-rw-r--r--mblock/src/lib/mb_exception.cc82
-rw-r--r--mblock/src/lib/mb_exception.h87
-rw-r--r--mblock/src/lib/mb_mblock.cc115
-rw-r--r--mblock/src/lib/mb_mblock.h162
-rw-r--r--mblock/src/lib/mb_mblock_impl.cc214
-rw-r--r--mblock/src/lib/mb_mblock_impl.h162
-rw-r--r--mblock/src/lib/mb_port.cc66
-rw-r--r--mblock/src/lib/mb_port.h83
-rw-r--r--mblock/src/lib/mb_port_detail.cc34
-rw-r--r--mblock/src/lib/mb_port_detail.h35
-rw-r--r--mblock/src/lib/mb_protocol_class.cc50
-rw-r--r--mblock/src/lib/mb_protocol_class.h38
-rw-r--r--mblock/src/lib/mb_runtime.cc52
-rw-r--r--mblock/src/lib/mb_runtime.h63
-rw-r--r--mblock/src/lib/mb_runtime_impl.cc36
-rw-r--r--mblock/src/lib/mb_runtime_impl.h41
-rw-r--r--mblock/src/lib/mb_util.cc34
-rw-r--r--mblock/src/lib/mb_util.h35
-rw-r--r--mblock/src/lib/qa_mblock.cc38
-rw-r--r--mblock/src/lib/qa_mblock.h36
-rw-r--r--mblock/src/lib/qa_mblock_prims.cc331
-rw-r--r--mblock/src/lib/qa_mblock_prims.h43
-rw-r--r--mblock/src/lib/test_mblock.cc37
28 files changed, 2152 insertions, 51 deletions
diff --git a/mblock/src/lib/Makefile.am b/mblock/src/lib/Makefile.am
index 28304f0c4..417473007 100644
--- a/mblock/src/lib/Makefile.am
+++ b/mblock/src/lib/Makefile.am
@@ -23,7 +23,7 @@ include $(top_srcdir)/Makefile.common
INCLUDES = $(PMT_INCLUDES) $(BOOST_CFLAGS) $(CPPUNIT_INCLUDES)
-# TESTS = test_mblock
+TESTS = test_mblock
lib_LTLIBRARIES = libmblock.la libmblock-qa.la
@@ -32,8 +32,17 @@ EXTRA_DIST =
# These are the source files that go into the mblock shared library
libmblock_la_SOURCES = \
+ mb_connection.cc \
+ mb_exception.cc \
+ mb_mblock.cc \
+ mb_mblock_impl.cc \
mb_message.cc \
- mb_protocol_class.cc
+ mb_port.cc \
+ mb_port_detail.cc \
+ mb_protocol_class.cc \
+ mb_runtime.cc \
+ mb_runtime_impl.cc \
+ mb_util.cc
# magic flags
@@ -45,38 +54,52 @@ libmblock_la_LIBADD = \
-lstdc++
include_HEADERS = \
- mb_mblock.h \
mb_common.h \
+ mb_exception.h \
+ mb_mblock.h \
mb_message.h \
- mb_protocol_class.h
+ mb_port.h \
+ mb_protocol_class.h \
+ mb_runtime.h \
+ mb_util.h
+
-noinst_HEADERS =
+noinst_HEADERS = \
+ mb_connection.h \
+ mb_endpoint.h \
+ mb_mblock_impl.h \
+ mb_port_detail.h \
+ mb_runtime_impl.h \
+ qa_mblock.h \
+ qa_mblock_prims.h
# Build the qa code into its own library
-libmblock_qa_la_SOURCES =
+libmblock_qa_la_SOURCES = \
+ qa_mblock.cc \
+ qa_mblock_prims.cc
# magic flags
libmblock_qa_la_LDFLAGS = $(NO_UNDEFINED) -avoid-version
# link the library against the c++ standard library
-libmblock_qa_la_LIBADD = \
- libmblock.la \
- $(CPPUNIT_LIBS) \
+libmblock_qa_la_LIBADD = \
+ libmblock.la \
+ $(CPPUNIT_LIBS) \
-lstdc++
-#noinst_PROGRAMS = \
-# test_mblock
+noinst_PROGRAMS = \
+ test_mblock
LIBMBLOCK = libmblock.la
LIBMBLOCKQA = libmblock-qa.la $(LIBMBLOCK)
-#test_mblock_SOURCES = test_mblock.cc
-#test_mblock_LDADD = $(LIBMBLOCKQA)
+test_mblock_SOURCES = test_mblock.cc
+test_mblock_LDADD = $(LIBMBLOCKQA)
CLEANFILES = $(BUILT_SOURCES) *.pyc
diff --git a/mblock/src/lib/mb_common.h b/mblock/src/lib/mb_common.h
index abeb06579..f54fa56a2 100644
--- a/mblock/src/lib/mb_common.h
+++ b/mblock/src/lib/mb_common.h
@@ -22,8 +22,32 @@
#define INCLUDED_MB_COMMON_H
#include <pmt.h>
+#include <vector>
+#include <stdexcept>
+#include <boost/utility.hpp>
+
typedef unsigned int mb_pri_t;
static const mb_pri_t MB_PRI_DEFAULT = 5;
+
+class mb_runtime;
+typedef boost::shared_ptr<mb_runtime> mb_runtime_sptr;
+
+class mb_runtime_impl;
+typedef boost::shared_ptr<mb_runtime_impl> mb_runtime_impl_sptr;
+
+class mb_mblock;
+typedef boost::shared_ptr<mb_mblock> mb_mblock_sptr;
+
+class mb_mblock_impl;
+typedef boost::shared_ptr<mb_mblock_impl> mb_mblock_impl_sptr;
+
+class mb_port;
+typedef boost::shared_ptr<mb_port> mb_port_sptr;
+
+class mb_port_detail;
+typedef boost::shared_ptr<mb_port_detail> mb_port_detail_sptr;
+
+
#endif /* INCLUDED_MB_COMMON_H */
diff --git a/mblock/src/lib/mb_connection.cc b/mblock/src/lib/mb_connection.cc
new file mode 100644
index 000000000..526de6506
--- /dev/null
+++ b/mblock/src/lib/mb_connection.cc
@@ -0,0 +1,126 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mb_connection.h>
+
+bool
+mb_conn_table::lookup_conn_by_name(const std::string &component_name,
+ const std::string &port_name,
+ mb_conn_iter *itp, int *which_ep)
+{
+ mb_conn_iter end = d_connections.end();
+ for (mb_conn_iter it = d_connections.begin(); it != end; ++it){
+
+ if (it->d_ep[0].component_name() == component_name
+ && it->d_ep[0].port_name() == port_name){
+ *itp = it;
+ *which_ep = 0;
+ return true;
+ }
+
+ if (it->d_ep[1].component_name() == component_name
+ && it->d_ep[1].port_name() == port_name){
+ *itp = it;
+ *which_ep = 1;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool
+mb_conn_table::lookup_conn_by_port(mb_port_sptr port,
+ mb_conn_iter *itp, int *which_ep)
+{
+ mb_conn_iter end = d_connections.end();
+ for (mb_conn_iter it = d_connections.begin(); it != end; ++it){
+ if (it->d_ep[0].port() == port){
+ *itp = it;
+ *which_ep = 0;
+ return true;
+ }
+ if (it->d_ep[1].port() == port){
+ *itp = it;
+ *which_ep = 1;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void
+mb_conn_table::create_conn(const mb_endpoint &ep0, const mb_endpoint &ep1)
+{
+ d_connections.push_back(mb_connection(ep0, ep1));
+}
+
+void
+mb_conn_table::disconnect(const std::string &comp_name1, const std::string &port_name1,
+ const std::string &comp_name2, const std::string &port_name2)
+{
+ mb_conn_iter it;
+ int which_ep;
+
+ // look for comp_name1/port_name1
+ bool found = lookup_conn_by_name(comp_name1, port_name1, &it, &which_ep);
+
+ if (!found) // no error if not found
+ return;
+
+ // FIXME if/when we do replicated ports, we may have one-to-many,
+ // or many-to-many bindings. For now, be paranoid
+ assert(it->d_ep[which_ep^1].component_name() == comp_name2);
+ assert(it->d_ep[which_ep^1].port_name() == port_name2);
+
+ d_connections.erase(it); // Poof!
+}
+
+void
+mb_conn_table::disconnect_component(const std::string component_name)
+{
+ mb_conn_iter next;
+ mb_conn_iter end = d_connections.end();
+ for (mb_conn_iter it = d_connections.begin(); it != end; it = next){
+ if (it->d_ep[0].component_name() == component_name
+ || it->d_ep[1].component_name() == component_name)
+ next = d_connections.erase(it); // Poof!
+ else
+ next = ++it;
+ }
+}
+
+void
+mb_conn_table::disconnect_all()
+{
+ d_connections.clear(); // All gone!
+}
+
+int
+mb_conn_table::nconnections() const
+{
+ return d_connections.size();
+}
diff --git a/mblock/src/lib/mb_connection.h b/mblock/src/lib/mb_connection.h
new file mode 100644
index 000000000..859d84677
--- /dev/null
+++ b/mblock/src/lib/mb_connection.h
@@ -0,0 +1,78 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef INCLUDED_MB_CONNECTION_H
+#define INCLUDED_MB_CONNECTION_H
+
+#include <mb_endpoint.h>
+#include <list>
+
+/*!
+ * \brief Representation of a connection
+ */
+struct mb_connection {
+ mb_endpoint d_ep[2];
+
+ mb_connection(const mb_endpoint &ep0, const mb_endpoint &ep1){
+ d_ep[0] = ep0;
+ d_ep[1] = ep1;
+ }
+};
+
+typedef std::list<mb_connection>::iterator mb_conn_iter;
+typedef std::list<mb_connection>::const_iterator mb_conn_const_iter;
+
+/*!
+ * \brief data structure that keeps track of connections
+ */
+class mb_conn_table {
+ std::list<mb_connection> d_connections;
+
+public:
+ bool
+ lookup_conn_by_name(const std::string &component_name,
+ const std::string &port_name,
+ mb_conn_iter *it, int *which_ep);
+
+ bool
+ lookup_conn_by_port(mb_port_sptr port,
+ mb_conn_iter *it, int *which_ep);
+
+ void
+ create_conn(const mb_endpoint &ep0, const mb_endpoint &ep1);
+
+
+ void
+ disconnect(const std::string &comp_name1, const std::string &port_name1,
+ const std::string &comp_name2, const std::string &port_name2);
+
+ void
+ disconnect_component(const std::string component_name);
+
+ void
+ disconnect_all();
+
+ int
+ nconnections() const;
+
+};
+
+#endif /* INCLUDED_MB_CONNECTION_H */
diff --git a/mblock/src/lib/mb_endpoint.h b/mblock/src/lib/mb_endpoint.h
new file mode 100644
index 000000000..90ae6fe67
--- /dev/null
+++ b/mblock/src/lib/mb_endpoint.h
@@ -0,0 +1,52 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef INCLUDED_MB_ENDPOINT_H
+#define INCLUDED_MB_ENDPOINT_H
+
+#include <string>
+#include <mb_port.h>
+
+/*!
+ * \brief Endpoint specification for connection
+ */
+class mb_endpoint
+{
+ std::string d_component_name;
+ std::string d_port_name;
+ mb_port_sptr d_port; // the port object that this maps to
+
+public:
+ mb_endpoint(){}
+
+ mb_endpoint(const std::string &component_name,
+ const std::string &port_name,
+ mb_port_sptr port)
+ : d_component_name(component_name),
+ d_port_name(port_name),
+ d_port(port) {}
+
+ const std::string &component_name() const { return d_component_name; }
+ const std::string &port_name() const { return d_port_name; }
+ mb_port_sptr port() const { return d_port; }
+};
+
+#endif /* INCLUDED_MB_ENDPOINT_H */
diff --git a/mblock/src/lib/mb_exception.cc b/mblock/src/lib/mb_exception.cc
new file mode 100644
index 000000000..4282f6dd0
--- /dev/null
+++ b/mblock/src/lib/mb_exception.cc
@@ -0,0 +1,82 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mb_exception.h>
+#include <mb_mblock.h>
+#include <mb_util.h>
+
+
+mbe_base::mbe_base(mb_mblock *mb, const std::string &msg)
+ : logic_error(msg) // FIXME extract block class name and id and add to msg
+{
+}
+
+mbe_no_such_component::mbe_no_such_component(mb_mblock *mb, const std::string &component_name)
+ : mbe_base(mb, "No such component: " + component_name)
+{
+}
+
+
+mbe_duplicate_component::mbe_duplicate_component(mb_mblock *mb, const std::string &component_name)
+ : mbe_base(mb, "Duplicate component: " + component_name)
+{
+}
+
+mbe_no_such_port::mbe_no_such_port(mb_mblock *mb, const std::string &port_name)
+ : mbe_base(mb, "No such port: " + port_name)
+{
+}
+
+mbe_duplicate_port::mbe_duplicate_port(mb_mblock *mb, const std::string &port_name)
+ : mbe_base(mb, "Duplicate port: " + port_name)
+{
+}
+
+mbe_already_connected::mbe_already_connected(mb_mblock *mb,
+ const std::string &comp_name,
+ const std::string &port_name)
+ : mbe_base(mb, "Port already connected: " + mb_util::join_names(comp_name, port_name))
+{
+}
+
+
+
+mbe_incompatible_ports::mbe_incompatible_ports(mb_mblock *mb,
+ const std::string &comp1_name,
+ const std::string &port1_name,
+ const std::string &comp2_name,
+ const std::string &port2_name)
+ : mbe_base(mb, "Incompatible ports: "
+ + mb_util::join_names(comp1_name, port1_name) + " "
+ + mb_util::join_names(comp2_name, port2_name))
+{
+}
+
+mbe_invalid_port_type::mbe_invalid_port_type(mb_mblock *mb,
+ const std::string &comp_name,
+ const std::string &port_name)
+ : mbe_base(mb, "Invalid port type for connection: " + mb_util::join_names(comp_name, port_name))
+{
+}
diff --git a/mblock/src/lib/mb_exception.h b/mblock/src/lib/mb_exception.h
new file mode 100644
index 000000000..188acf48f
--- /dev/null
+++ b/mblock/src/lib/mb_exception.h
@@ -0,0 +1,87 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_MB_EXCEPTION_H
+#define INCLUDED_MB_EXCEPTION_H
+
+#include <stdexcept>
+
+class mb_mblock;
+
+
+class mbe_base : public std::logic_error
+{
+public:
+ mbe_base(mb_mblock *mb, const std::string &msg);
+};
+
+
+
+class mbe_no_such_component : public mbe_base
+{
+public:
+ mbe_no_such_component(mb_mblock *, const std::string &component_name);
+};
+
+class mbe_duplicate_component : public mbe_base
+{
+public:
+ mbe_duplicate_component(mb_mblock *, const std::string &component_name);
+};
+
+class mbe_no_such_port : public mbe_base
+{
+public:
+ mbe_no_such_port(mb_mblock *, const std::string &port_name);
+};
+
+class mbe_duplicate_port : public mbe_base
+{
+public:
+ mbe_duplicate_port(mb_mblock *, const std::string &port_name);
+};
+
+class mbe_already_connected : public mbe_base
+{
+public:
+ mbe_already_connected(mb_mblock *, const std::string &comp_name,
+ const std::string &port_name);
+};
+
+class mbe_incompatible_ports : public mbe_base
+{
+public:
+ mbe_incompatible_ports(mb_mblock *,
+ const std::string &comp1_name,
+ const std::string &port1_name,
+ const std::string &comp2_name,
+ const std::string &port2_name);
+};
+
+class mbe_invalid_port_type : public mbe_base
+{
+public:
+ mbe_invalid_port_type(mb_mblock *, const std::string &comp_name,
+ const std::string &port_name);
+};
+
+
+
+#endif /* INCLUDED_MB_EXCEPTION_H */
diff --git a/mblock/src/lib/mb_mblock.cc b/mblock/src/lib/mb_mblock.cc
new file mode 100644
index 000000000..9ab1fbbff
--- /dev/null
+++ b/mblock/src/lib/mb_mblock.cc
@@ -0,0 +1,115 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mb_mblock.h>
+#include <mb_mblock_impl.h>
+
+
+mb_mblock::mb_mblock()
+ : d_impl(mb_mblock_impl_sptr(new mb_mblock_impl(this)))
+{
+}
+
+mb_mblock::~mb_mblock()
+{
+ disconnect_all();
+
+ // FIXME more?
+}
+
+
+void
+mb_mblock::init_fsm()
+{
+ // default implementation does nothing
+}
+
+void
+mb_mblock::handle_message(mb_message_sptr msg)
+{
+ // default implementation does nothing
+}
+
+////////////////////////////////////////////////////////////////////////
+// Forward other methods to implementation class //
+////////////////////////////////////////////////////////////////////////
+
+mb_port_sptr
+mb_mblock::define_port(const std::string &port_name_string,
+ const std::string &protocol_class_name,
+ bool conjugated,
+ mb_port::port_type_t port_type)
+{
+ return d_impl->define_port(port_name_string, protocol_class_name,
+ conjugated, port_type);
+}
+
+void
+mb_mblock::define_component(const std::string &component_name,
+ mb_mblock_sptr component)
+{
+ d_impl->define_component(component_name, component);
+}
+
+void
+mb_mblock::connect(const std::string &comp_name1, const std::string &port_name1,
+ const std::string &comp_name2, const std::string &port_name2)
+{
+ d_impl->connect(comp_name1, port_name1,
+ comp_name2, port_name2);
+}
+
+
+void
+mb_mblock::disconnect(const std::string &comp_name1, const std::string &port_name1,
+ const std::string &comp_name2, const std::string &port_name2)
+{
+ d_impl->disconnect(comp_name1, port_name1,
+ comp_name2, port_name2);
+}
+
+void
+mb_mblock::disconnect_component(const std::string component_name)
+{
+ d_impl->disconnect_component(component_name);
+}
+
+void
+mb_mblock::disconnect_all()
+{
+ d_impl->disconnect_all();
+}
+
+int
+mb_mblock::nconnections() const
+{
+ return d_impl->nconnections();
+}
+
+bool
+mb_mblock::walk_tree(mb_visitor *visitor, const std::string &path)
+{
+ return d_impl->walk_tree(visitor, path);
+}
diff --git a/mblock/src/lib/mb_mblock.h b/mblock/src/lib/mb_mblock.h
index db9d0a33b..ce0065f2d 100644
--- a/mblock/src/lib/mb_mblock.h
+++ b/mblock/src/lib/mb_mblock.h
@@ -22,5 +22,167 @@
#define INCLUDED_MB_MBLOCK_H
#include <mb_common.h>
+#include <mb_message.h>
+#include <mb_port.h>
+
+
+/*!
+ * Abstract class implementing visitor pattern
+ * \ingroup internal
+ */
+class mb_visitor
+{
+public:
+ virtual ~mb_visitor();
+ bool operator()(mb_mblock *mblock, const std::string &path) { return visit(mblock, path); }
+ virtual bool visit(mb_mblock *mblock, const std::string &path) = 0;
+};
+
+// ----------------------------------------------------------------------
+
+/*!
+ * \brief Parent class for all message passing blocks
+ *
+ * Subclass this to define your mblocks.
+ */
+class mb_mblock : boost::noncopyable
+{
+private:
+ mb_mblock_impl_sptr d_impl; // implementation details
+
+ friend class mb_runtime;
+ friend class mb_mblock_impl;
+
+protected:
+ /*!
+ * \brief mblock constructor.
+ *
+ * Initializing all mblocks in the system is a 3 step procedure.
+ *
+ * The top level mblock's constructor is run. That constructor (a)
+ * registers all of its ports using define_port, (b) constructs and
+ * registers any subcomponents it may have via the define_component
+ * method, and then (c) issues connect calls to wire its
+ * subcomponents together.
+ */
+ mb_mblock();
+
+ /*!
+ * \brief Called by the runtime system to execute the initial
+ * transition of the finite state machine.
+ *
+ * Override this to initialize your finite state machine.
+ */
+ virtual void init_fsm();
+
+ /*!
+ * \brief Called by the runtime system when there's a message to handle.
+ *
+ * Override this to define your behavior.
+ *
+ * Do not issue any potentially blocking calls in this method. This
+ * includes things such reads or writes on sockets, pipes or slow
+ * i/o devices.
+ */
+ virtual void handle_message(mb_message_sptr msg);
+
+ /*!
+ * \brief Define a port.
+ *
+ * EXTERNAL and RELAY ports are part of our peer interface.
+ * INTERNAL ports are used to talk to sub-components.
+ *
+ * \param port_name The name of the port (must be unique within this mblock).
+ * \param protocol_class_name The name of the protocol class associated with
+ * this port. It must already be defined.
+ * \param conjugated Are the incoming and outgoing message sets swapped?
+ * \param port_type INTERNAL, EXTERNAL or RELAY.
+ */
+ mb_port_sptr
+ define_port(const std::string &port_name,
+ const std::string &protocol_class_name,
+ bool conjugated,
+ mb_port::port_type_t port_type);
+
+ /*!
+ * \brief Define a subcomponent by name.
+ *
+ * Called within the constructor to tell the system the
+ * names and identities of our sub-component mblocks.
+ *
+ * \param component_name The name of the sub-component (must be unique with this mblock).
+ * \param component The sub-component instance.
+ */
+ void
+ define_component(const std::string &component_name,
+ mb_mblock_sptr component);
+
+ /*!
+ * \brief connect endpoint_1 to endpoint_2
+ *
+ * \param comp_name1 component on one of the connection
+ * \param port_name1 the name of the port on comp1
+ * \param comp_name2 component on the other end the connection
+ * \param port_name2 the name of the port on comp2
+ *
+ * An endpoint is specified by the component's local name (given as
+ * component_name in the call to register_component) and the name of
+ * the port on that component.
+ *
+ * To connect an internal or relay port, use "self" as the component name.
+ */
+ void
+ connect(const std::string &comp_name1, const std::string &port_name1,
+ const std::string &comp_name2, const std::string &port_name2);
+
+ /*!
+ * \brief disconnect endpoint_1 from endpoint_2
+ *
+ * \param comp_name1 component on one of the connection
+ * \param port_name1 the name of the port on comp1
+ * \param comp_name2 component on the other end the connection
+ * \param port_name2 the name of the port on comp2
+ *
+ * An endpoint is specified by the component's local name (given as
+ * component_name in the call to register_component) and the name of
+ * the port on that component.
+ *
+ * To disconnect an internal or relay port, use "self" as the component name.
+ */
+ void
+ disconnect(const std::string &comp_name1, const std::string &port_name1,
+ const std::string &comp_name2, const std::string &port_name2);
+
+ /*!
+ * \brief disconnect all connections to specified component
+ * \param component_name component to disconnect
+ */
+ void
+ disconnect_component(const std::string component_name);
+
+ /*!
+ * \brief disconnect all connections to all components
+ */
+ void
+ disconnect_all();
+
+ /*!
+ * \brief Return number of connections (QA mostly)
+ */
+ int
+ nconnections() const;
+
+
+public:
+ virtual ~mb_mblock();
+
+ /*!
+ * \brief Perform a pre-order depth-first traversal of the hierarchy.
+ *
+ * The traversal stops and returns false if any call to visitor returns false.
+ */
+ bool walk_tree(mb_visitor *visitor, const std::string &path="");
+};
+
#endif /* INCLUDED_MB_MBLOCK_H */
diff --git a/mblock/src/lib/mb_mblock_impl.cc b/mblock/src/lib/mb_mblock_impl.cc
new file mode 100644
index 000000000..8a9efe2ba
--- /dev/null
+++ b/mblock/src/lib/mb_mblock_impl.cc
@@ -0,0 +1,214 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <mb_mblock_impl.h>
+#include <mb_mblock.h>
+#include <mb_protocol_class.h>
+#include <mb_port.h>
+#include <mb_exception.h>
+#include <mb_util.h>
+
+
+static pmt_t s_self = pmt_intern("self");
+
+////////////////////////////////////////////////////////////////////////
+
+bool
+mb_mblock_impl::port_is_defined(const std::string &name)
+{
+ return d_port_map.count(name) != 0;
+}
+
+bool
+mb_mblock_impl::comp_is_defined(const std::string &name)
+{
+ return name == "self" || d_comp_map.count(name) != 0;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+mb_mblock_impl::mb_mblock_impl(mb_mblock *mb)
+ : d_mb(mb)
+{
+}
+
+mb_mblock_impl::~mb_mblock_impl()
+{
+ d_mb = 0; // we don't own it
+}
+
+
+mb_port_sptr
+mb_mblock_impl::define_port(const std::string &port_name,
+ const std::string &protocol_class_name,
+ bool conjugated,
+ mb_port::port_type_t port_type)
+{
+ if (port_type == mb_port::RELAY)
+ throw mbe_base(d_mb, "mb_block_impl::define_port: RELAY ports are not implemented: " + port_name);
+
+ if (port_is_defined(port_name))
+ throw mbe_duplicate_port(d_mb, port_name);
+
+ mb_port_sptr p = mb_port_sptr(new mb_port(port_name, protocol_class_name,
+ conjugated, port_type));
+ d_port_map[port_name] = p;
+ return p;
+}
+
+void
+mb_mblock_impl::define_component(const std::string &name,
+ mb_mblock_sptr component)
+{
+ if (comp_is_defined(name)) // check for duplicate name
+ throw mbe_duplicate_component(d_mb, name);
+
+ d_comp_map[name] = component;
+}
+
+void
+mb_mblock_impl::connect(const std::string &comp_name1, const std::string &port_name1,
+ const std::string &comp_name2, const std::string &port_name2)
+{
+ mb_endpoint ep0 = check_and_resolve_endpoint(comp_name1, port_name1);
+ mb_endpoint ep1 = check_and_resolve_endpoint(comp_name2, port_name2);
+
+ if (!ports_are_compatible(ep0.port(), ep1.port()))
+ throw mbe_incompatible_ports(d_mb,
+ comp_name1, port_name1,
+ comp_name2, port_name2);
+ // FIXME more checks?
+
+ d_conn_table.create_conn(ep0, ep1);
+}
+
+void
+mb_mblock_impl::disconnect(const std::string &comp_name1, const std::string &port_name1,
+ const std::string &comp_name2, const std::string &port_name2)
+{
+ d_conn_table.disconnect(comp_name1, port_name1, comp_name2, port_name2);
+}
+
+void
+mb_mblock_impl::disconnect_component(const std::string component_name)
+{
+ d_conn_table.disconnect_component(component_name);
+}
+
+void
+mb_mblock_impl::disconnect_all()
+{
+ d_conn_table.disconnect_all();
+}
+
+int
+mb_mblock_impl::nconnections() const
+{
+ return d_conn_table.nconnections();
+}
+
+////////////////////////////////////////////////////////////////////////
+
+mb_endpoint
+mb_mblock_impl::check_and_resolve_endpoint(const std::string &comp_name,
+ const std::string &port_name)
+{
+ mb_conn_iter it;
+ int which_ep;
+ mb_port_sptr port = resolve_port(comp_name, port_name);
+
+ // Confirm that we're not trying to connect to the inside of one of
+ // our EXTERNAL ports. Connections that include "self" as the
+ // component name must be either INTERNAL or RELAY.
+
+ if (comp_name == "self" && port->port_type() == mb_port::EXTERNAL)
+ throw mbe_invalid_port_type(d_mb, comp_name, port_name);
+
+ // Is this endpoint already connected?
+ if (d_conn_table.lookup_conn_by_name(comp_name, port_name, &it, &which_ep))
+ throw mbe_already_connected(d_mb, comp_name, port_name);
+
+ return mb_endpoint(comp_name, port_name, port);
+}
+
+mb_port_sptr
+mb_mblock_impl::resolve_port(const std::string &comp_name,
+ const std::string &port_name)
+{
+ if (comp_name == "self"){
+ // Look through our ports.
+ if (!port_is_defined(port_name))
+ throw mbe_no_such_port(d_mb, mb_util::join_names("self", port_name));
+ return d_port_map[port_name];
+ }
+ else {
+ // Look through the specified child's ports.
+ if (!comp_is_defined(comp_name))
+ throw mbe_no_such_component(d_mb, comp_name);
+
+ mb_mblock_impl_sptr c_impl = d_comp_map[comp_name]->d_impl; // childs impl pointer
+ if (!c_impl->port_is_defined(port_name))
+ throw mbe_no_such_port(d_mb, mb_util::join_names(comp_name, port_name));
+
+ mb_port_sptr c_port = c_impl->d_port_map[port_name];
+
+ if (c_port->port_type() == mb_port::INTERNAL) // can't "see" a child's internal ports
+ throw mbe_no_such_port(d_mb, mb_util::join_names(comp_name, port_name));
+
+ return c_port;
+ }
+}
+
+
+
+bool
+mb_mblock_impl::ports_are_compatible(mb_port_sptr p0, mb_port_sptr p1)
+{
+ using std::cout;
+ using std::endl;
+
+ pmt_t p0_outgoing = p0->outgoing_message_set();
+ pmt_t p0_incoming = p0->incoming_message_set();
+
+ pmt_t p1_outgoing = p1->outgoing_message_set();
+ pmt_t p1_incoming = p1->incoming_message_set();
+
+ return (pmt_subsetp(p0_outgoing, p1_incoming)
+ && pmt_subsetp(p1_outgoing, p0_incoming));
+}
+
+bool
+mb_mblock_impl::walk_tree(mb_visitor *visitor, const std::string &path)
+{
+ if (!(*visitor)(d_mb, path))
+ return false;
+
+ mb_comp_map_t::iterator it;
+ for (it = d_comp_map.begin(); it != d_comp_map.end(); ++it)
+ if (!(it->second->walk_tree(visitor, path + "/" + it->first)))
+ return false;
+
+ return true;
+}
+
diff --git a/mblock/src/lib/mb_mblock_impl.h b/mblock/src/lib/mb_mblock_impl.h
new file mode 100644
index 000000000..c5610eddd
--- /dev/null
+++ b/mblock/src/lib/mb_mblock_impl.h
@@ -0,0 +1,162 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_MB_MBLOCK_IMPL_H
+#define INCLUDED_MB_MBLOCK_IMPL_H
+
+#include <mb_mblock.h>
+#include <mb_connection.h>
+#include <list>
+#include <map>
+
+
+typedef std::map<std::string, mb_port_sptr> mb_port_map_t;
+typedef std::map<std::string, mb_mblock_sptr> mb_comp_map_t;
+
+
+/*!
+ * \brief The private implementation details of the mblock system.
+ */
+class mb_mblock_impl : boost::noncopyable
+{
+ mb_mblock *d_mb; // pointer to our associated mblock
+
+ mb_port_map_t d_port_map; // our ports
+ mb_comp_map_t d_comp_map; // our components
+ mb_conn_table d_conn_table; // our connections
+
+public:
+ mb_mblock_impl(mb_mblock *mb);
+ ~mb_mblock_impl();
+
+ /*!
+ * \brief Define a port.
+ *
+ * EXTERNAL and RELAY ports are part of our peer interface.
+ * INTERNAL ports are used to talk to sub-components.
+ *
+ * \param port_name The name of the port (must be unique within this mblock).
+ * \param protocol_class_name The name of the protocol class associated with
+ * this port. It must already be defined.
+ * \param conjugated Are the incoming and outgoing message sets swapped?
+ * \param port_type INTERNAL, EXTERNAL or RELAY.
+ */
+ mb_port_sptr
+ define_port(const std::string &port_name,
+ const std::string &protocol_class_name,
+ bool conjugated,
+ mb_port::port_type_t port_type);
+
+ /*!
+ * \brief Define a subcomponent by name.
+ *
+ * Called within the constructor to tell the system the
+ * names and identities of our sub-component mblocks.
+ *
+ * \param component_name The name of the sub-component (must be unique with this mblock).
+ * \param component The sub-component instance.
+ */
+ void
+ define_component(const std::string &component_name,
+ mb_mblock_sptr component);
+
+ /*!
+ * \brief connect endpoint_1 to endpoint_2
+ *
+ * \param comp_name1 component on one of the connection
+ * \param port_name1 the name of the port on comp1
+ * \param comp_name2 component on the other end the connection
+ * \param port_name2 the name of the port on comp2
+ *
+ * An endpoint is specified by the component's local name (given as
+ * component_name in the call to register_component) and the name of
+ * the port on that component.
+ *
+ * To connect an internal or relay port, use "self" as the component name.
+ */
+ void
+ connect(const std::string &comp_name1, const std::string &port_name1,
+ const std::string &comp_name2, const std::string &port_name2);
+
+ /*!
+ * \brief disconnect endpoint_1 from endpoint_2
+ *
+ * \param comp_name1 component on one of the connection
+ * \param port_name1 the name of the port on comp1
+ * \param comp_name2 component on the other end the connection
+ * \param port_name2 the name of the port on comp2
+ *
+ * An endpoint is specified by the component's local name (given as
+ * component_name in the call to register_component) and the name of
+ * the port on that component.
+ *
+ * To disconnect an internal or relay port, use "self" as the component name.
+ */
+ void
+ disconnect(const std::string &comp_name1, const std::string &port_name1,
+ const std::string &comp_name2, const std::string &port_name2);
+
+ /*!
+ * \brief disconnect all connections to specified component
+ * \param component_name component to disconnect
+ */
+ void
+ disconnect_component(const std::string component_name);
+
+ /*!
+ * \brief disconnect all connections to all components
+ */
+ void
+ disconnect_all();
+
+ /*!
+ * \brief Return number of connections (QA mostly)
+ */
+ int
+ nconnections() const;
+
+ bool
+ walk_tree(mb_visitor *visitor, const std::string &path="");
+
+ /*
+ * Our implementation methods
+ */
+private:
+ //bool port_is_defined(pmt_t name);
+ bool port_is_defined(const std::string &name);
+ //bool comp_is_defined(pmt_t name);
+ bool comp_is_defined(const std::string &name);
+
+ mb_endpoint
+ check_and_resolve_endpoint(const std::string &comp_name,
+ const std::string &port_name);
+
+
+ mb_port_sptr
+ resolve_port(const std::string &comp_name,
+ const std::string &port_name);
+
+ static bool
+ ports_are_compatible(mb_port_sptr p0, mb_port_sptr p1);
+
+};
+
+
+#endif /* INCLUDED_MB_MBLOCK_IMPL_H */
diff --git a/mblock/src/lib/mb_port.cc b/mblock/src/lib/mb_port.cc
new file mode 100644
index 000000000..d7851126b
--- /dev/null
+++ b/mblock/src/lib/mb_port.cc
@@ -0,0 +1,66 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mb_port.h>
+#include <mb_port_detail.h>
+#include <mb_protocol_class.h>
+
+mb_port::mb_port(const std::string &port_name,
+ const std::string &protocol_class_name,
+ bool conjugated,
+ mb_port::port_type_t port_type)
+ : d_detail(mb_port_detail_sptr(new mb_port_detail())),
+ d_port_name(port_name), d_conjugated(conjugated), d_port_type(port_type)
+{
+ pmt_t pc = mb_protocol_class_lookup(pmt_intern(protocol_class_name));
+ if (pmt_is_null(pc)){
+ throw std::runtime_error("mb_port: unknown protocol class '"
+ + protocol_class_name + "'");
+ }
+ d_protocol_class = pc;
+}
+
+mb_port::~mb_port()
+{
+ // nop
+}
+
+pmt_t
+mb_port::incoming_message_set() const
+{
+ if (!conjugated())
+ return mb_protocol_class_incoming(protocol_class());
+ else // swap the sets
+ return mb_protocol_class_outgoing(protocol_class());
+}
+
+pmt_t
+mb_port::outgoing_message_set() const
+{
+ if (!conjugated())
+ return mb_protocol_class_outgoing(protocol_class());
+ else // swap the sets
+ return mb_protocol_class_incoming(protocol_class());
+}
diff --git a/mblock/src/lib/mb_port.h b/mblock/src/lib/mb_port.h
new file mode 100644
index 000000000..35ac34e2c
--- /dev/null
+++ b/mblock/src/lib/mb_port.h
@@ -0,0 +1,83 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_MB_PORT_H
+#define INCLUDED_MB_PORT_H
+
+#include <mb_common.h>
+
+/*!
+ * \brief Public port characteristics
+ */
+class mb_port : boost::noncopyable
+{
+public:
+
+ //! port classification
+ enum port_type_t {
+ EXTERNAL, //< Externally visible
+ RELAY, //< Externally visible but really connected to a sub-component
+ INTERNAL //< Visible to self only
+ };
+
+private:
+ friend class mb_mblock_impl;
+
+ mb_port_detail_sptr d_detail;
+ std::string d_port_name;
+ pmt_t d_protocol_class;
+ bool d_conjugated;
+ port_type_t d_port_type;
+
+ // private constructor
+ mb_port(const std::string &port_name,
+ const std::string &protocol_class_name,
+ bool conjugated,
+ mb_port::port_type_t port_type);
+
+
+public:
+ std::string port_name() const { return d_port_name; }
+ pmt_t protocol_class() const { return d_protocol_class; }
+ bool conjugated() const { return d_conjugated; }
+ port_type_t port_type() const { return d_port_type; }
+
+ pmt_t incoming_message_set() const;
+ pmt_t outgoing_message_set() const;
+
+ ~mb_port();
+
+ /*!
+ * \brief send a message
+ *
+ * \param signal the event name
+ * \param data optional data
+ * \param metadata optional metadata
+ * \param priority the urgency at which the message is sent
+ */
+ void
+ send(pmt_t signal,
+ pmt_t data = PMT_NIL,
+ pmt_t metadata = PMT_NIL,
+ mb_pri_t priority = MB_PRI_DEFAULT);
+
+};
+
+#endif /* INCLUDED_MB_PORT_H */
diff --git a/mblock/src/lib/mb_port_detail.cc b/mblock/src/lib/mb_port_detail.cc
new file mode 100644
index 000000000..3a58fa24d
--- /dev/null
+++ b/mblock/src/lib/mb_port_detail.cc
@@ -0,0 +1,34 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mb_port_detail.h>
+
+mb_port_detail::mb_port_detail()
+{
+}
+
+mb_port_detail::~mb_port_detail()
+{
+}
diff --git a/mblock/src/lib/mb_port_detail.h b/mblock/src/lib/mb_port_detail.h
new file mode 100644
index 000000000..3623a1b48
--- /dev/null
+++ b/mblock/src/lib/mb_port_detail.h
@@ -0,0 +1,35 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef INCLUDED_MB_PORT_DETAIL_H
+#define INCLUDED_MB_PORT_DETAIL_H
+
+#include <mb_port.h>
+
+class mb_port_detail : boost::noncopyable
+{
+public:
+ mb_port_detail();
+ ~mb_port_detail();
+};
+
+
+#endif /* INCLUDED_MB_PORT_DETAIL_H */
diff --git a/mblock/src/lib/mb_protocol_class.cc b/mblock/src/lib/mb_protocol_class.cc
index ffa548701..f3eeb6035 100644
--- a/mblock/src/lib/mb_protocol_class.cc
+++ b/mblock/src/lib/mb_protocol_class.cc
@@ -25,26 +25,58 @@
#include <mb_protocol_class.h>
+static pmt_t s_ALL_PROTOCOL_CLASSES = PMT_NIL;
-mb_protocol_class_sptr
+pmt_t
mb_make_protocol_class(pmt_t name, pmt_t incoming, pmt_t outgoing)
{
- return mb_protocol_class_sptr(new mb_protocol_class(name, incoming, outgoing));
+ // (protocol-class <name> <incoming> <outgoing>)
+
+ if (!pmt_is_symbol(name))
+ throw pmt_wrong_type("mb_make_protocol_class: NAME must be symbol", name);
+ if (!(pmt_is_pair(incoming) || pmt_is_null(incoming)))
+ throw pmt_wrong_type("mb_make_protocol_class: INCOMING must be a list", name);
+ if (!(pmt_is_pair(outgoing) || pmt_is_null(outgoing)))
+ throw pmt_wrong_type("mb_make_protocol_class: OUTGOING must be a list", name);
+
+ pmt_t t = pmt_cons(pmt_intern("protocol-class"),
+ pmt_cons(name,
+ pmt_cons(incoming,
+ pmt_cons(outgoing, PMT_NIL))));
+
+ // Remember this protocol class.
+ s_ALL_PROTOCOL_CLASSES = pmt_cons(t, s_ALL_PROTOCOL_CLASSES);
+ return t;
}
-mb_protocol_class::mb_protocol_class(pmt_t name, pmt_t incoming, pmt_t outgoing)
- : d_name(name), d_incoming(incoming), d_outgoing(outgoing)
+pmt_t
+mb_protocol_class_name(pmt_t pc)
{
+ return pmt_nth(1, pc);
}
-mb_protocol_class::~mb_protocol_class()
+pmt_t
+mb_protocol_class_incoming(pmt_t pc)
{
- // NOP
+ return pmt_nth(2, pc);
}
+pmt_t
+mb_protocol_class_outgoing(pmt_t pc)
+{
+ return pmt_nth(3, pc);
+}
-mb_protocol_class_sptr
-mb_protocol_class::conj() const
+pmt_t
+mb_protocol_class_lookup(pmt_t name)
{
- return mb_make_protocol_class(name(), outgoing(), incoming());
+ pmt_t lst = s_ALL_PROTOCOL_CLASSES;
+
+ while (pmt_is_pair(lst)){
+ if (pmt_eq(name, mb_protocol_class_name(pmt_car(lst))))
+ return pmt_car(lst);
+ lst = pmt_cdr(lst);
+ }
+
+ return PMT_NIL;
}
diff --git a/mblock/src/lib/mb_protocol_class.h b/mblock/src/lib/mb_protocol_class.h
index 771a63e09..f4382ada1 100644
--- a/mblock/src/lib/mb_protocol_class.h
+++ b/mblock/src/lib/mb_protocol_class.h
@@ -23,40 +23,20 @@
#include <mb_common.h>
-// FIXME maybe this should just be a pmt_t aggregate???
-
-class mb_protocol_class;
-typedef boost::shared_ptr<mb_protocol_class> mb_protocol_class_sptr;
-
/*!
- * \brief construct a protocol_class and return boost::shared_ptr
+ * \brief construct a protocol_class
*
* \param name the name of the class (symbol)
- * \param incoming incoming message set (dict: keys are message types)
- * \param outgoing outgoing message set (dict: keys are message types)
+ * \param incoming incoming message set (list of symbols)
+ * \param outgoing outgoing message set (list of symbols)
*/
-mb_protocol_class_sptr
-mb_make_protocol_class(pmt_t name, pmt_t incoming, pmt_t outgoing);
-
-class mb_protocol_class {
- pmt_t d_name;
- pmt_t d_incoming;
- pmt_t d_outgoing;
-
- friend mb_protocol_class_sptr
- mb_make_protocol_class(pmt_t name, pmt_t incoming, pmt_t outgoing);
-
- // private constructor
- mb_protocol_class(pmt_t name, pmt_t incoming, pmt_t outgoing);
-
-public:
- ~mb_protocol_class();
+pmt_t mb_make_protocol_class(pmt_t name, pmt_t incoming, pmt_t outgoing);
- pmt_t name() const { return d_name; }
- pmt_t incoming() const { return d_incoming; }
- pmt_t outgoing() const { return d_outgoing; }
+// Accessors
+pmt_t mb_protocol_class_name(pmt_t pc); //< return name of protocol class
+pmt_t mb_protocol_class_incoming(pmt_t pc); //< return incoming message set
+pmt_t mb_protocol_class_outgoing(pmt_t pc); //< return outgoing message set
- mb_protocol_class_sptr conj() const; // return the conjugate of this protocol class
-};
+pmt_t mb_protocol_class_lookup(pmt_t name); //< lookup an existing protocol class by name
#endif /* INCLUDED_MB_PROTOCOL_CLASS_H */
diff --git a/mblock/src/lib/mb_runtime.cc b/mblock/src/lib/mb_runtime.cc
new file mode 100644
index 000000000..8c396f190
--- /dev/null
+++ b/mblock/src/lib/mb_runtime.cc
@@ -0,0 +1,52 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mb_runtime.h>
+#include <mb_runtime_impl.h>
+
+mb_runtime_sptr
+mb_make_runtime()
+{
+ return mb_runtime_sptr(new mb_runtime());
+}
+
+mb_runtime::mb_runtime()
+ : d_impl(mb_runtime_impl_sptr(new mb_runtime_impl()))
+{
+ // FIXME
+
+}
+
+mb_runtime::~mb_runtime()
+{
+ // FIXME
+}
+
+bool
+mb_runtime::run()
+{
+ // FIXME
+ return true;
+}
diff --git a/mblock/src/lib/mb_runtime.h b/mblock/src/lib/mb_runtime.h
new file mode 100644
index 000000000..c4eb206bd
--- /dev/null
+++ b/mblock/src/lib/mb_runtime.h
@@ -0,0 +1,63 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_MB_RUNTIME_H
+#define INCLUDED_MB_RUNTIME_H
+
+#include <mb_common.h>
+
+/*!
+ * \brief Public constructor for mb_runtime.
+ */
+mb_runtime_sptr mb_make_runtime();
+
+/*!
+ * \brief Runtime support for m-blocks
+ *
+ * There should generally be only a single instance of this class.
+ *
+ * It should be created by the top-level initialization code,
+ * and that instance should be passed into the constructor of the
+ * top-level mblock.
+ */
+class mb_runtime : boost::noncopyable
+{
+private:
+ mb_runtime_impl_sptr d_impl; // implementation details
+
+ mb_runtime();
+
+ friend mb_runtime_sptr mb_make_runtime();
+
+public:
+ ~mb_runtime();
+
+ /*!
+ * \brief Run the mblocks...
+ *
+ * This routine turns into the m-block scheduler, and
+ * blocks until the system is shutdown.
+ *
+ * \returns true if the system ran successfully.
+ */
+ bool run();
+};
+
+#endif /* INCLUDED_MB_RUNTIME_H */
diff --git a/mblock/src/lib/mb_runtime_impl.cc b/mblock/src/lib/mb_runtime_impl.cc
new file mode 100644
index 000000000..5a354ef16
--- /dev/null
+++ b/mblock/src/lib/mb_runtime_impl.cc
@@ -0,0 +1,36 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mb_runtime_impl.h>
+
+mb_runtime_impl::mb_runtime_impl()
+{
+ // FIXME
+}
+
+mb_runtime_impl::~mb_runtime_impl()
+{
+ // FIXME
+}
diff --git a/mblock/src/lib/mb_runtime_impl.h b/mblock/src/lib/mb_runtime_impl.h
new file mode 100644
index 000000000..2325a3518
--- /dev/null
+++ b/mblock/src/lib/mb_runtime_impl.h
@@ -0,0 +1,41 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef INCLUDED_MB_RUNTIME_IMPL_H
+#define INCLUDED_MB_RUNTIME_IMPL_H
+
+#include <mb_common.h>
+
+/*!
+ * \brief The private implementation details of the runtime system.
+ */
+class mb_runtime_impl : boost::noncopyable
+{
+private:
+ friend class mb_runtime;
+
+ mb_runtime_impl();
+
+public:
+ ~mb_runtime_impl();
+};
+
+
+#endif /* INCLUDED_MB_RUNTIME_IMPL_H */
diff --git a/mblock/src/lib/mb_util.cc b/mblock/src/lib/mb_util.cc
new file mode 100644
index 000000000..8a14d4c06
--- /dev/null
+++ b/mblock/src/lib/mb_util.cc
@@ -0,0 +1,34 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <mb_util.h>
+
+
+std::string
+mb_util::join_names(const std::string &comp_name,
+ const std::string &port_name)
+{
+ return comp_name + "/" + port_name;
+}
diff --git a/mblock/src/lib/mb_util.h b/mblock/src/lib/mb_util.h
new file mode 100644
index 000000000..98ff3dd89
--- /dev/null
+++ b/mblock/src/lib/mb_util.h
@@ -0,0 +1,35 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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 this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef INCLUDED_MB_UTIL_H
+#define INCLUDED_MB_UTIL_H
+
+#include <string>
+
+class mb_util
+{
+public:
+ static std::string
+ join_names(const std::string &comp_name,
+ const std::string &port_name);
+};
+
+#endif /* INCLUDED_MB_UTIL_H */
diff --git a/mblock/src/lib/qa_mblock.cc b/mblock/src/lib/qa_mblock.cc
new file mode 100644
index 000000000..72dccc053
--- /dev/null
+++ b/mblock/src/lib/qa_mblock.cc
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2006 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 2, 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This class gathers together all the test cases for mblock into
+ * a single test suite. As you create new test cases, add them here.
+ */
+
+#include <qa_mblock.h>
+#include <qa_mblock_prims.h>
+
+CppUnit::TestSuite *
+qa_mblock::suite()
+{
+ CppUnit::TestSuite *s = new CppUnit::TestSuite("mblock");
+
+ s->addTest (qa_mblock_prims::suite());
+
+ return s;
+}
diff --git a/mblock/src/lib/qa_mblock.h b/mblock/src/lib/qa_mblock.h
new file mode 100644
index 000000000..8d8437422
--- /dev/null
+++ b/mblock/src/lib/qa_mblock.h
@@ -0,0 +1,36 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef INCLUDED_QA_MBLOCK_H
+#define INCLUDED_QA_MBLOCK_H
+
+#include <cppunit/TestSuite.h>
+
+//! collect all the tests for mblock
+
+class qa_mblock {
+ public:
+ //! return suite of tests for all of mblock
+ static CppUnit::TestSuite *suite();
+};
+
+#endif /* INCLUDED_QA_MBLOCK_H */
diff --git a/mblock/src/lib/qa_mblock_prims.cc b/mblock/src/lib/qa_mblock_prims.cc
new file mode 100644
index 000000000..432e819aa
--- /dev/null
+++ b/mblock/src/lib/qa_mblock_prims.cc
@@ -0,0 +1,331 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <qa_mblock_prims.h>
+#include <cppunit/TestAssert.h>
+#include <mb_mblock.h>
+#include <mb_runtime.h>
+#include <mb_protocol_class.h>
+#include <mb_exception.h>
+#include <stdio.h>
+
+static pmt_t s_cs = pmt_intern("cs");
+static pmt_t s_debug = pmt_intern("debug");
+static pmt_t s_in = pmt_intern("in");
+static pmt_t s_out = pmt_intern("out");
+
+
+// ================================================================
+
+class dp_1 : public mb_mblock
+{
+public:
+ dp_1();
+ ~dp_1();
+};
+
+dp_1::dp_1()
+{
+}
+
+dp_1::~dp_1(){}
+
+// ----------------------------------------------------------------
+
+class dp_2 : public mb_mblock
+{
+public:
+ dp_2();
+ ~dp_2();
+};
+
+dp_2::dp_2()
+{
+ define_port("cs", "cs-protocol", false, mb_port::EXTERNAL);
+}
+
+dp_2::~dp_2(){}
+
+// ----------------------------------------------------------------
+
+class dp_3 : public mb_mblock
+{
+public:
+ dp_3();
+ ~dp_3();
+};
+
+dp_3::dp_3()
+{
+ define_port("cs", "cs-protocol", false, mb_port::EXTERNAL);
+ define_port("cs", "cs-protocol", false, mb_port::EXTERNAL); // duplicate def
+}
+
+dp_3::~dp_3(){}
+
+// ----------------------------------------------------------------
+
+void
+qa_mblock_prims::test_define_ports()
+{
+ mb_runtime_sptr rt = mb_make_runtime();
+ // std::vector<mb_port_sptr> intf;
+
+ mb_mblock_sptr mb1 = mb_mblock_sptr(new dp_1());
+ // intf = mb1->peer_interface();
+ // CPPUNIT_ASSERT_EQUAL(size_t(0), intf.size());
+
+ // raises runtime_error because of unknown protocol "cs-protocol"
+ CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dp_2()), std::runtime_error);
+
+ // define the protocol class
+ pmt_t pc = mb_make_protocol_class(pmt_intern("cs-protocol"),
+ pmt_cons(pmt_intern("start"),
+ pmt_cons(pmt_intern("stop"),
+ PMT_NIL)),
+ PMT_NIL);
+
+ // std::cout << "pc = " << pc << '\n';
+
+ mb_mblock_sptr mb2 = mb_mblock_sptr(new dp_2());
+
+ // intf = mb2->peer_interface();
+ // CPPUNIT_ASSERT_EQUAL(size_t(1), intf.size());
+ // CPPUNIT_ASSERT(pmt_eq(s_cs, intf[0]->port_name()));
+
+
+ // raises pmt_exception because of duplicate port definition of "cs"
+ CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dp_3()), mbe_duplicate_port);
+
+#if 0
+ try {
+ mb_mblock_sptr mb2 = mb_mblock_sptr(new dp_2());
+ }
+ catch (pmt_exception &e){
+ std::cerr << e.msg() << ' ' << e.obj() << '\n';
+ }
+#endif
+
+}
+
+// ================================================================
+
+class dc_0 : public mb_mblock
+{
+public:
+ dc_0();
+ ~dc_0();
+};
+
+dc_0::dc_0()
+{
+}
+
+dc_0::~dc_0() {}
+
+// ----------------------------------------------------------------
+
+class dc_ok : public mb_mblock
+{
+public:
+ dc_ok();
+ ~dc_ok();
+};
+
+dc_ok::dc_ok()
+{
+ define_component("c0", mb_mblock_sptr(new dc_0()));
+ define_component("c1", mb_mblock_sptr(new dc_0()));
+ define_component("c2", mb_mblock_sptr(new dc_0()));
+}
+
+dc_ok::~dc_ok(){}
+
+// ----------------------------------------------------------------
+
+class dc_not_ok : public mb_mblock
+{
+public:
+ dc_not_ok();
+ ~dc_not_ok();
+};
+
+dc_not_ok::dc_not_ok()
+ : mb_mblock()
+{
+ define_component("c0", mb_mblock_sptr(new dc_0()));
+ define_component("c0", mb_mblock_sptr(new dc_0())); // duplicate name
+}
+
+dc_not_ok::~dc_not_ok(){}
+
+// ----------------------------------------------------------------
+
+void
+qa_mblock_prims::test_define_components()
+{
+ mb_runtime_sptr rt = mb_make_runtime();
+ mb_mblock_sptr mb1 = mb_mblock_sptr(new dc_ok()); // OK
+
+ // raises pmt_exception because of duplicate component definition of "c0"
+ CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dc_not_ok()), mbe_duplicate_component);
+}
+
+// ================================================================
+
+class tc_norm : public mb_mblock
+{
+public:
+ tc_norm(){
+ define_port("data", "i/o", false, mb_port::EXTERNAL);
+ define_port("norm", "i/o", false, mb_port::EXTERNAL);
+ define_port("conj", "i/o", true, mb_port::EXTERNAL);
+ define_port("int", "i/o", false, mb_port::INTERNAL);
+ }
+
+ ~tc_norm();
+};
+
+tc_norm::~tc_norm(){}
+
+////////////////////////////////////////////////////////////////
+
+class tc_0 : public mb_mblock
+{
+public:
+ tc_0(){
+ define_port("norm", "i/o", false, mb_port::EXTERNAL);
+ define_port("conj", "i/o", true, mb_port::EXTERNAL);
+ define_port("int", "i/o", false, mb_port::INTERNAL);
+
+ define_component("c0", mb_mblock_sptr(new tc_norm()));
+ define_component("c1", mb_mblock_sptr(new tc_norm()));
+ define_component("c2", mb_mblock_sptr(new tc_norm()));
+ define_component("c3", mb_mblock_sptr(new tc_norm()));
+ define_component("c4", mb_mblock_sptr(new tc_norm()));
+ define_component("c5", mb_mblock_sptr(new tc_norm()));
+
+ // OK
+ connect("c0", "norm", "c1", "conj");
+
+ // No: No such component name
+ CPPUNIT_ASSERT_THROW(connect("foo", "data", "c1", "norm"), mbe_no_such_component);
+
+ // No: No such port name
+ CPPUNIT_ASSERT_THROW(connect("c0", "data", "c1", "foo"), mbe_no_such_port);
+
+ // No: already connected
+ CPPUNIT_ASSERT_THROW(connect("c0", "norm", "c2", "data"), mbe_already_connected);
+
+ // No: already connected
+ CPPUNIT_ASSERT_THROW(connect("c2", "data", "c0", "norm"), mbe_already_connected);
+
+ // No: incompatible ports
+ CPPUNIT_ASSERT_THROW(connect("c1", "norm", "c2", "norm"), mbe_incompatible_ports);
+
+ // OK
+ connect("c1", "norm", "c2", "conj");
+
+ // No: No such port name
+ CPPUNIT_ASSERT_THROW(connect("c2", "norm", "self", "foo"), mbe_no_such_port);
+
+ // No: can't connect to child's internal port
+ CPPUNIT_ASSERT_THROW(connect("c0", "conj", "c2", "int"), mbe_no_such_port);
+
+ // No: can't connect to our own external port
+ CPPUNIT_ASSERT_THROW(connect("self", "norm", "c0", "conj"), mbe_invalid_port_type);
+
+ // OK: connecting to one of our internal ports
+ connect("self", "int", "c3", "conj");
+
+ // ===== Now test disconnecting some stuff =====
+
+ // Confirm we're already connected
+ CPPUNIT_ASSERT_THROW(connect("self", "int", "c3", "conj"), mbe_already_connected);
+
+ int nc = nconnections();
+ disconnect("self", "int", "c3", "conj"); // disconnect
+ CPPUNIT_ASSERT_EQUAL(nc-1, nconnections());
+
+ connect("self", "int", "c3", "conj"); // reconnect
+ CPPUNIT_ASSERT_EQUAL(nc, nconnections());
+
+ // confirm we're already connected
+ CPPUNIT_ASSERT_THROW(connect("self", "int", "c3", "conj"), mbe_already_connected);
+
+
+ connect("c0", "conj", "c5", "data");
+ connect("c4", "norm", "c5", "conj");
+ connect("c4", "conj", "c5", "norm");
+
+ nc = nconnections();
+ disconnect_component("c4");
+ CPPUNIT_ASSERT_EQUAL(nc-2, nconnections());
+
+ disconnect_component("c5");
+ CPPUNIT_ASSERT_EQUAL(nc-3, nconnections());
+
+ disconnect_all();
+ CPPUNIT_ASSERT_EQUAL(0, nconnections());
+
+ }
+
+ ~tc_0();
+};
+
+tc_0::~tc_0(){}
+
+////////////////////////////////////////////////////////////////
+
+class tc_1 : public mb_mblock
+{
+public:
+ tc_1(){
+ define_component("c0", mb_mblock_sptr(new tc_norm()));
+ define_component("c1", mb_mblock_sptr(new tc_norm()));
+
+ connect("c0", "norm", "c1", "conj");
+ }
+
+ ~tc_1();
+};
+
+tc_1::~tc_1(){}
+
+////////////////////////////////////////////////////////////////
+
+void
+qa_mblock_prims::test_connect()
+{
+ // define the protocol class
+ mb_make_protocol_class(pmt_intern("data"), // name of class
+ pmt_cons(pmt_intern("data"), PMT_NIL), // in
+ PMT_NIL); // out
+
+ mb_make_protocol_class(pmt_intern("i/o"), // name of class
+ pmt_cons(pmt_intern("in"), PMT_NIL), // in
+ pmt_cons(pmt_intern("out"), PMT_NIL)); // out
+
+
+ mb_runtime_sptr rt = mb_make_runtime();
+ mb_mblock_sptr mb0 = mb_mblock_sptr(new tc_0());
+}
diff --git a/mblock/src/lib/qa_mblock_prims.h b/mblock/src/lib/qa_mblock_prims.h
new file mode 100644
index 000000000..36b35550f
--- /dev/null
+++ b/mblock/src/lib/qa_mblock_prims.h
@@ -0,0 +1,43 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef INCLUDED_QA_MBLOCK_PRIMS_H
+#define INCLUDED_QA_MBLOCK_PRIMS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_mblock_prims : public CppUnit::TestCase {
+
+ CPPUNIT_TEST_SUITE(qa_mblock_prims);
+ CPPUNIT_TEST(test_define_ports);
+ CPPUNIT_TEST(test_define_components);
+ CPPUNIT_TEST(test_connect);
+ CPPUNIT_TEST_SUITE_END();
+
+ private:
+ void test_define_ports();
+ void test_define_components();
+ void test_connect();
+};
+
+#endif /* INCLUDED_QA_MBLOCK_PRIMS_H */
+
diff --git a/mblock/src/lib/test_mblock.cc b/mblock/src/lib/test_mblock.cc
new file mode 100644
index 000000000..d1abdea67
--- /dev/null
+++ b/mblock/src/lib/test_mblock.cc
@@ -0,0 +1,37 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006 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 2, 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <cppunit/TextTestRunner.h>
+#include <qa_mblock.h>
+
+int
+main(int argc, char **argv)
+{
+
+ CppUnit::TextTestRunner runner;
+
+ runner.addTest(qa_mblock::suite ());
+
+ bool was_successful = runner.run("", false);
+
+ return was_successful ? 0 : 1;
+}