commit-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Commit-gnuradio] r4927 - in gnuradio/branches/features/inband-usb: mblo


From: eb
Subject: [Commit-gnuradio] r4927 - in gnuradio/branches/features/inband-usb: mblock/src/lib omnithread pmt/src/lib usrp/host/lib/inband
Date: Sun, 8 Apr 2007 10:03:14 -0600 (MDT)

Author: eb
Date: 2007-04-08 10:03:13 -0600 (Sun, 08 Apr 2007)
New Revision: 4927

Added:
   gnuradio/branches/features/inband-usb/mblock/src/lib/mb_class_registry.cc
   gnuradio/branches/features/inband-usb/mblock/src/lib/mb_class_registry.h
   
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_thread_per_block.cc
   
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_thread_per_block.h
   gnuradio/branches/features/inband-usb/mblock/src/lib/mb_worker.cc
   gnuradio/branches/features/inband-usb/mblock/src/lib/mb_worker.h
   gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock_sys.cc
   gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock_sys.h
Removed:
   
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_thread_per_mblock.cc
   
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_thread_per_mblock.h
Modified:
   gnuradio/branches/features/inband-usb/mblock/src/lib/Makefile.am
   gnuradio/branches/features/inband-usb/mblock/src/lib/mb_exception.cc
   gnuradio/branches/features/inband-usb/mblock/src/lib/mb_exception.h
   gnuradio/branches/features/inband-usb/mblock/src/lib/mb_mblock.cc
   gnuradio/branches/features/inband-usb/mblock/src/lib/mb_mblock.h
   gnuradio/branches/features/inband-usb/mblock/src/lib/mb_mblock_impl.cc
   gnuradio/branches/features/inband-usb/mblock/src/lib/mb_mblock_impl.h
   gnuradio/branches/features/inband-usb/mblock/src/lib/mb_protocol_class.cc
   gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime.cc
   gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime.h
   gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_nop.cc
   gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_nop.h
   gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock.cc
   gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock_prims.cc
   gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock_send.cc
   gnuradio/branches/features/inband-usb/omnithread/omnithread.h
   gnuradio/branches/features/inband-usb/omnithread/posix.cc
   gnuradio/branches/features/inband-usb/pmt/src/lib/pmt.h
   gnuradio/branches/features/inband-usb/usrp/host/lib/inband/usrp_server.cc
   gnuradio/branches/features/inband-usb/usrp/host/lib/inband/usrp_server.h
Log:
Merged eb/ibu -r4870:4926 into features/inband-usb.  There are some
API changes for mb_runtime and mb_mblock, and it's all closer to
working.



Modified: gnuradio/branches/features/inband-usb/mblock/src/lib/Makefile.am
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/Makefile.am    
2007-04-08 06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/Makefile.am    
2007-04-08 16:03:13 UTC (rev 4927)
@@ -33,6 +33,7 @@
 
 # These are the source files that go into the mblock shared library
 libmblock_la_SOURCES =                 \
+       mb_class_registry.cc            \
        mb_connection.cc                \
        mb_endpoint.cc                  \
        mb_exception.cc                 \
@@ -47,9 +48,9 @@
        mb_protocol_class.cc            \
        mb_runtime.cc                   \
        mb_runtime_nop.cc               \
-       mb_runtime_placeholder.cc       \
-       mb_runtime_thread_per_mblock.cc \
-       mb_util.cc                      
+       mb_runtime_thread_per_block.cc  \
+       mb_util.cc                      \
+       mb_worker.cc                    
 
 
 # magic flags
@@ -62,6 +63,7 @@
        -lstdc++                        
 
 include_HEADERS =                      \
+       mb_class_registry.h             \
        mb_common.h                     \
        mb_exception.h                  \
        mb_mblock.h                     \
@@ -73,8 +75,6 @@
        mb_protocol_class.h             \
        mb_runtime.h                    \
        mb_runtime_nop.h                \
-       mb_runtime_placeholder.h        \
-       mb_runtime_thread_per_mblock.h  \
        mb_util.h                       
 
 
@@ -83,10 +83,13 @@
        mb_endpoint.h                   \
        mb_mblock_impl.h                \
        mb_msg_accepter_smp.h           \
+       mb_runtime_thread_per_block.h   \
+       mb_worker.h                     \
        mbi_runtime_lock.h              \
        qa_mblock.h                     \
        qa_mblock_prims.h               \
-       qa_mblock_send.h                
+       qa_mblock_send.h                \
+       qa_mblock_sys.h                 
 
 
 # Build the qa code into its own library
@@ -94,7 +97,8 @@
 libmblock_qa_la_SOURCES =              \
        qa_mblock.cc                    \
        qa_mblock_prims.cc              \
-       qa_mblock_send.cc               
+       qa_mblock_send.cc               \
+       qa_mblock_sys.cc                
 
 
 # magic flags

Copied: 
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_class_registry.cc (from 
rev 4926, 
gnuradio/branches/developers/eb/ibu/mblock/src/lib/mb_class_registry.cc)
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/mb_class_registry.cc   
                        (rev 0)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/mb_class_registry.cc   
2007-04-08 16:03:13 UTC (rev 4927)
@@ -0,0 +1,47 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 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_class_registry.h>
+#include <map>
+
+static std::map<std::string, mb_mblock_maker_t>        s_registry;
+
+bool
+mb_class_registry::register_maker(const std::string &name, mb_mblock_maker_t 
maker)
+{
+  s_registry[name] = maker;
+  return true;
+}
+
+bool
+mb_class_registry::lookup_maker(const std::string &name, mb_mblock_maker_t 
*maker)
+{
+  if (s_registry.count(name) == 0){  // not registered
+    *maker = (mb_mblock_maker_t) 0;
+    return false;
+  }
+
+  *maker = s_registry[name];
+  return true;
+}

Copied: 
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_class_registry.h (from 
rev 4926, 
gnuradio/branches/developers/eb/ibu/mblock/src/lib/mb_class_registry.h)
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/mb_class_registry.h    
                        (rev 0)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/mb_class_registry.h    
2007-04-08 16:03:13 UTC (rev 4927)
@@ -0,0 +1,51 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 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_CLASS_REGISTRY_H
+#define INCLUDED_MB_CLASS_REGISTRY_H
+
+#include <mb_common.h>
+
+//! conceptually, pointer to constructor
+typedef mb_mblock_sptr (*mb_mblock_maker_t)(mb_runtime *runtime,
+                                           const std::string &instance_name,
+                                           pmt_t user_arg);
+
+/*
+ * \brief Maintain mapping between mblock class_name and factory (maker)
+ */
+class mb_class_registry : public boost::noncopyable {
+public:
+  static bool register_maker(const std::string &name, mb_mblock_maker_t maker);
+  static bool lookup_maker(const std::string &name, mb_mblock_maker_t *maker);
+};
+
+template<class mblock>
+mb_mblock_sptr mb_mblock_maker(mb_runtime *runtime,
+                              const std::string &instance_name,
+                              pmt_t user_arg)
+{
+  return mb_mblock_sptr(new mblock(runtime, instance_name, user_arg));
+}
+
+#define REGISTER_MBLOCK_CLASS(name) \
+  bool __RBC__ ## name = mb_class_registry::register_maker(#name, 
&mb_mblock_maker<name>)
+
+#endif /* INCLUDED_MB_CLASS_REGISTRY_H */

Modified: gnuradio/branches/features/inband-usb/mblock/src/lib/mb_exception.cc
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/mb_exception.cc        
2007-04-08 06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/mb_exception.cc        
2007-04-08 16:03:13 UTC (rev 4927)
@@ -38,6 +38,11 @@
 {
 }
 
+mbe_no_such_class::mbe_no_such_class(mb_mblock *mb, const std::string 
&class_name)
+  : mbe_base(mb, "No such class: " + class_name)
+{
+}
+
 mbe_no_such_component::mbe_no_such_component(mb_mblock *mb, const std::string 
&component_name)
   : mbe_base(mb, "No such component: " + component_name)
 {
@@ -85,3 +90,17 @@
   : mbe_base(mb, "Invalid port type for connection: " + 
mb_util::join_names(comp_name, port_name))
 {
 }
+
+mbe_mblock_failed::mbe_mblock_failed(mb_mblock *mb,
+                                    const std::string &msg)
+  : mbe_base(mb, "Message block failed: " + msg)
+{
+}
+
+mbe_terminate::mbe_terminate()
+{
+}
+
+mbe_exit::mbe_exit()
+{
+}

Modified: gnuradio/branches/features/inband-usb/mblock/src/lib/mb_exception.h
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/mb_exception.h 
2007-04-08 06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/mb_exception.h 
2007-04-08 16:03:13 UTC (rev 4927)
@@ -38,6 +38,11 @@
   mbe_not_implemented(mb_mblock *mb, const std::string &msg);
 };
 
+class mbe_no_such_class : public mbe_base
+{
+public:
+  mbe_no_such_class(mb_mblock *, const std::string &class_name);
+};
 
 class mbe_no_such_component : public mbe_base
 {
@@ -57,6 +62,7 @@
   mbe_no_such_port(mb_mblock *, const std::string &port_name);
 };
 
+
 class mbe_duplicate_port : public mbe_base
 {
 public:
@@ -87,6 +93,26 @@
                        const std::string &port_name);
 };
 
+class mbe_mblock_failed : public mbe_base
+{
+public:
+  mbe_mblock_failed(mb_mblock *, const std::string &msg);
+};
 
 
+
+// not derived from mbe_base to simplify try/catch
+class mbe_terminate
+{
+public:
+  mbe_terminate();
+};
+
+// not derived from mbe_base to simplify try/catch
+class mbe_exit
+{
+public:
+  mbe_exit();
+};
+
 #endif /* INCLUDED_MB_EXCEPTION_H */

Modified: gnuradio/branches/features/inband-usb/mblock/src/lib/mb_mblock.cc
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/mb_mblock.cc   
2007-04-08 06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/mb_mblock.cc   
2007-04-08 16:03:13 UTC (rev 4927)
@@ -25,16 +25,24 @@
 
 #include <mb_mblock.h>
 #include <mb_mblock_impl.h>
+#include <mb_runtime.h>
+#include <mb_exception.h>
+#include <iostream>
 
 
+static pmt_t s_sys_port = pmt_intern("%sys-port");
+static pmt_t s_halt = pmt_intern("%halt");
+
 mb_visitor::~mb_visitor()
 {
   // nop base case for virtual destructor.
 }
 
 
-mb_mblock::mb_mblock()
-  : d_impl(mb_mblock_impl_sptr(new mb_mblock_impl(this)))
+mb_mblock::mb_mblock(mb_runtime *runtime,
+                    const std::string &instance_name,
+                    pmt_t user_arg)
+  : d_impl(mb_mblock_impl_sptr(new mb_mblock_impl(runtime, this, 
instance_name)))
 {
 }
 
@@ -47,7 +55,7 @@
 
 
 void
-mb_mblock::init_fsm()
+mb_mblock::initial_transition()
 {
   // default implementation does nothing
 }
@@ -58,6 +66,31 @@
   // default implementation does nothing
 }
 
+
+void
+mb_mblock::main_loop()
+{
+  while (1){
+    mb_message_sptr msg;
+    try {
+      while (1){
+       msg = impl()->msgq().get_highest_pri_msg();
+
+       // check for %halt from %sys-port
+       if (pmt_eq(msg->port_id(), s_sys_port) && pmt_eq(msg->signal(), s_halt))
+         exit();
+
+       handle_message(msg);
+      }
+    }
+    catch (pmt_exception e){
+      std::cerr << std::endl << instance_name()
+               << "::main_loop: ignoring pmt_exception: "
+               << e.what() << std::endl;
+    }
+  }
+}
+
 ////////////////////////////////////////////////////////////////////////
 //           Forward other methods to implementation class            //
 ////////////////////////////////////////////////////////////////////////
@@ -74,9 +107,11 @@
 
 void
 mb_mblock::define_component(const std::string &component_name,
-                           mb_mblock_sptr component)
+                           const std::string &class_name,
+                           pmt_t user_arg)
+               
 {
-  d_impl->define_component(component_name, component);
+  d_impl->define_component(component_name, class_name, user_arg);
 }
 
 void
@@ -97,7 +132,7 @@
 }
 
 void
-mb_mblock::disconnect_component(const std::string component_name)
+mb_mblock::disconnect_component(const std::string &component_name)
 {
   d_impl->disconnect_component(component_name);
 }
@@ -115,9 +150,9 @@
 }
 
 bool
-mb_mblock::walk_tree(mb_visitor *visitor, const std::string &path)
+mb_mblock::walk_tree(mb_visitor *visitor)
 {
-  return d_impl->walk_tree(visitor, path);
+  return d_impl->walk_tree(visitor);
 }
 
 std::string
@@ -127,7 +162,7 @@
 }
 
 void
-mb_mblock::set_instance_name(const std::string name)
+mb_mblock::set_instance_name(const std::string &name)
 {
   d_impl->set_instance_name(name);
 }
@@ -139,7 +174,7 @@
 }
 
 void
-mb_mblock::set_class_name(const std::string name)
+mb_mblock::set_class_name(const std::string &name)
 {
   d_impl->set_class_name(name);
 }
@@ -149,3 +184,15 @@
 {
   return d_impl->mblock_parent();
 }
+
+void
+mb_mblock::exit()
+{
+  throw mbe_exit();    // adios...
+}
+
+void
+mb_mblock::shutdown_all(pmt_t result)
+{
+  d_impl->runtime()->request_shutdown(result);
+}

Modified: gnuradio/branches/features/inband-usb/mblock/src/lib/mb_mblock.h
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/mb_mblock.h    
2007-04-08 06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/mb_mblock.h    
2007-04-08 16:03:13 UTC (rev 4927)
@@ -34,7 +34,7 @@
 {
 public:
   virtual ~mb_visitor();
-  virtual bool operator()(mb_mblock *mblock, const std::string &path) = 0;
+  virtual bool operator()(mb_mblock *mblock) = 0;
 };
 
 // ----------------------------------------------------------------------
@@ -52,6 +52,7 @@
 
   friend class mb_runtime;
   friend class mb_mblock_impl;
+  friend class mb_worker;
 
 protected:
   /*!
@@ -59,22 +60,29 @@
    *
    * 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.
+   * The top level mblock's constructor is run.  That constructor 
+   * (a) registers all of its ports using define_port, (b) registers any
+   * subcomponents it may have via the define_component method, and
+   * then (c) issues connect calls to wire its subcomponents together.
+   *
+   * \param runtime the runtime associated with this mblock
+   * \param instance_name specify the name of this instance
+   *        (for debugging, NUMA mapping, etc)
+   * \param user_arg argument passed by user to constructor
+   *        (ignored by the mb_mblock base class)
    */
-  mb_mblock();
+  mb_mblock(mb_runtime *runtime, const std::string &instance_name, pmt_t 
user_arg);
 
 public:
   /*!
    * \brief Called by the runtime system to execute the initial
    * transition of the finite state machine.
    *
-   * Override this to initialize your finite state machine.
+   * This method is called by the runtime after all blocks are
+   * constructed and before the first message is delivered.  Override
+   * this to initialize your finite state machine.
    */
-  virtual void init_fsm();
+  virtual void initial_transition();
 
 protected:
   /*!
@@ -113,11 +121,13 @@
    * 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.
+   * \param class_name      The class of the instance that is to be created.
+   * \param user_arg The argument to pass to the constructor of the component.
    */
   void
   define_component(const std::string &component_name,
-                  mb_mblock_sptr component);
+                  const std::string &class_name,
+                  pmt_t user_arg = PMT_NIL);
 
   /*!
    * \brief connect endpoint_1 to endpoint_2
@@ -160,7 +170,7 @@
    * \param component_name component to disconnect
    */
   void
-  disconnect_component(const std::string component_name);
+  disconnect_component(const std::string &component_name);
 
   /*!
    * \brief disconnect all connections to all components
@@ -175,8 +185,47 @@
   nconnections() const;
 
   //! Set the class name
-  void set_class_name(const std::string name);
+  void set_class_name(const std::string &name);
 
+  /*!
+   * \brief Tell runtime that we are done.
+   *
+   * This method does not return.
+   */
+  void exit();
+
+  /*!
+   * \brief Ask runtime to execute the shutdown procedure for all blocks.
+   * 
+   * \param result sets value of \p result output argument of runtime->run(...)
+   *
+   * The runtime first sends a maximum priority %shutdown message to
+   * all blocks.  All blocks should handle the %shutdown message,
+   * perform whatever clean up is required, and call this->exit();
+   *
+   * After a period of time (~100ms), any blocks which haven't yet
+   * called this->exit() are sent a maximum priority %halt message.
+   * %halt is detected in main_loop, and this->exit() is called.
+   *
+   * After an additional period of time (~100ms), any blocks which
+   * still haven't yet called this->exit() are sent a SIG<FOO> (TBD)
+   * signal, which will blow them out of any blocking system calls and
+   * raise an mbe_terminate exception.  The default top-level
+   * runtime-provided exception handler will call this->exit() to
+   * finish the process.
+   *
+   * runtime->run(...) returns when all blocks have called exit.
+   */
+  void shutdown_all(pmt_t result);
+
+  /*!
+   * \brief main event dispatching loop
+   *
+   * Although it is possible to override this, the default implementation
+   * should work for virtually all cases.
+   */
+  virtual void main_loop();
+  
 public:
   virtual ~mb_mblock();
 
@@ -187,7 +236,7 @@
   std::string class_name() const;
 
   //! Set the instance name of this block.
-  void set_instance_name(const std::string name);
+  void set_instance_name(const std::string &name);
   
   //! Return the parent of this mblock, or 0 if we're the top-level block.
   mb_mblock *parent() const;
@@ -198,7 +247,7 @@
    * The traversal stops and returns false if any call to visitor returns 
false.
    */
   bool
-  walk_tree(mb_visitor *visitor, const std::string &path="top");
+  walk_tree(mb_visitor *visitor);
 
 
   //! \implementation

Modified: gnuradio/branches/features/inband-usb/mblock/src/lib/mb_mblock_impl.cc
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/mb_mblock_impl.cc      
2007-04-08 06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/mb_mblock_impl.cc      
2007-04-08 16:03:13 UTC (rev 4927)
@@ -30,7 +30,7 @@
 #include <mb_exception.h>
 #include <mb_util.h>
 #include <mb_msg_accepter_smp.h>
-#include <mb_runtime_placeholder.h>
+//#include <mb_runtime_placeholder.h>
 #include <mbi_runtime_lock.h>
 
 
@@ -52,9 +52,10 @@
 
 ////////////////////////////////////////////////////////////////////////
 
-mb_mblock_impl::mb_mblock_impl(mb_mblock *mb)
-  : d_mb(mb), d_mb_parent(0), d_runtime(mb_runtime_placeholder::singleton()),
-    d_instance_name("<unknown>"), d_class_name("mblock")
+mb_mblock_impl::mb_mblock_impl(mb_runtime *runtime, mb_mblock *mb,
+                              const std::string &instance_name)
+  : d_runtime(runtime), d_mb(mb), d_mb_parent(0), 
+    d_instance_name(instance_name), d_class_name("mblock")
 {
 }
 
@@ -85,15 +86,28 @@
 
 void
 mb_mblock_impl::define_component(const std::string &name,
-                                mb_mblock_sptr component)
+                                const std::string &class_name,
+                                pmt_t user_arg)
 {
-  mbi_runtime_lock     l(this);
+  {
+    mbi_runtime_lock   l(this);
 
-  if (comp_is_defined(name))   // check for duplicate name
-    throw mbe_duplicate_component(d_mb, name);
+    if (comp_is_defined(name)) // check for duplicate name
+      throw mbe_duplicate_component(d_mb, name);
+  }
 
-  component->d_impl->d_mb_parent = d_mb;     // set component's parent link
-  d_comp_map[name] = component;
+  // We ask the runtime to create the component so that it can worry about
+  // mblock placement on a NUMA machine or on a distributed multicomputer
+
+  mb_mblock_sptr component =
+    d_runtime->create_component(instance_name() + "/" + name,
+                               class_name, user_arg);
+  {
+    mbi_runtime_lock   l(this);
+
+    component->d_impl->d_mb_parent = d_mb;     // set component's parent link
+    d_comp_map[name] = component;
+  }
 }
 
 void
@@ -220,14 +234,14 @@
 }
 
 bool
-mb_mblock_impl::walk_tree(mb_visitor *visitor, const std::string &path)
+mb_mblock_impl::walk_tree(mb_visitor *visitor)
 {
-  if (!(*visitor)(d_mb, path))
+  if (!(*visitor)(d_mb))
     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)))
+    if (!(it->second->walk_tree(visitor)))
       return false;
 
   return true;
@@ -280,4 +294,3 @@
 {
   d_class_name = name;
 }
-

Modified: gnuradio/branches/features/inband-usb/mblock/src/lib/mb_mblock_impl.h
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/mb_mblock_impl.h       
2007-04-08 06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/mb_mblock_impl.h       
2007-04-08 16:03:13 UTC (rev 4927)
@@ -37,9 +37,9 @@
  */
 class mb_mblock_impl : boost::noncopyable
 {
+  mb_runtime                  *d_runtime;      // pointer to runtime
   mb_mblock                   *d_mb;           // pointer to our associated 
mblock
   mb_mblock                   *d_mb_parent;    // pointer to our parent
-  mb_runtime                  *d_runtime;      // pointer to runtime
 
   std::string                  d_instance_name;    // hierarchical name
   std::string                  d_class_name;       // name of this (derived) 
class
@@ -51,7 +51,7 @@
   mb_msg_queue                 d_msgq;         // incoming messages for us
 
 public:
-  mb_mblock_impl(mb_mblock *mb);
+  mb_mblock_impl(mb_runtime *runtime, mb_mblock *mb, const std::string 
&instance_name);
   ~mb_mblock_impl();
 
   /*!
@@ -79,11 +79,13 @@
    * 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.
+   * \param class_name      The class of the instance that is to be created.
+   * \param user_arg The argument to pass to the constructor of the component.
    */
   void
   define_component(const std::string &component_name,
-                  mb_mblock_sptr component);
+                  const std::string &class_name,
+                  pmt_t user_arg);
 
   /*!
    * \brief connect endpoint_1 to endpoint_2
@@ -141,7 +143,7 @@
   nconnections();
 
   bool
-  walk_tree(mb_visitor *visitor, const std::string &path="");
+  walk_tree(mb_visitor *visitor);
   
   mb_msg_accepter_sptr
   make_accepter(const std::string port_name);

Modified: 
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_protocol_class.cc
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/mb_protocol_class.cc   
2007-04-08 06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/mb_protocol_class.cc   
2007-04-08 16:03:13 UTC (rev 4927)
@@ -24,6 +24,7 @@
 #endif
 
 #include <mb_protocol_class.h>
+#include <iostream>
 
 static pmt_t s_ALL_PROTOCOL_CLASSES = PMT_NIL;
 

Modified: gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime.cc
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime.cc  
2007-04-08 06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime.cc  
2007-04-08 16:03:13 UTC (rev 4927)
@@ -24,15 +24,21 @@
 #endif
 
 #include <mb_runtime.h>
-#include <mb_runtime_thread_per_mblock.h>
+#include <mb_runtime_thread_per_block.h>
 
 mb_runtime_sptr
 mb_make_runtime()
 {
-  return mb_runtime_sptr(new mb_runtime_thread_per_mblock());
+  return mb_runtime_sptr(new mb_runtime_thread_per_block());
 }
 
 mb_runtime::~mb_runtime()
 {
   // nop
 }
+
+void
+mb_runtime::request_shutdown(pmt_t result)
+{
+  // nop
+}

Modified: gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime.h
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime.h   
2007-04-08 06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime.h   
2007-04-08 16:03:13 UTC (rev 4927)
@@ -37,6 +37,8 @@
 class mb_runtime : boost::noncopyable,
                   public boost::enable_shared_from_this<mb_runtime>
 {
+  friend class mb_mblock_impl;
+
   omni_mutex   d_brl;          // big runtime lock (avoid using this if 
possible...)
 
 public:
@@ -44,15 +46,21 @@
   virtual ~mb_runtime();
 
   /*!
-   * \brief Run the mblock hierarchy rooted at \p top
+   * \brief Construct and run the specified mblock hierarchy.
    *
    * This routine turns into the m-block scheduler, and
    * blocks until the system is shutdown.
    *
-   * \param top top-level mblock
+   * \param name name of the top-level mblock (conventionally "top")
+   * \param class_name The class of the top-level mblock to create.
+   * \param user_arg The argument to pass to the top-level mblock constructor
+   *
    * \returns true if the system ran successfully.
    */
-  virtual bool run(mb_mblock_sptr top) = 0;
+  virtual bool run(const std::string &instance_name,
+                  const std::string &class_name,
+                  pmt_t user_arg,
+                  pmt_t *result = 0) = 0;
 
 
   // ----------------------------------------------------------------
@@ -71,6 +79,13 @@
    */
   inline void unlock() { d_brl.unlock(); }
 
+  virtual void request_shutdown(pmt_t result);
+
+protected:
+  virtual mb_mblock_sptr
+  create_component(const std::string &instance_name,
+                  const std::string &class_name,
+                  pmt_t user_arg) = 0;
 };
 
 #endif /* INCLUDED_MB_RUNTIME_H */

Modified: gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_nop.cc
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_nop.cc      
2007-04-08 06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_nop.cc      
2007-04-08 16:03:13 UTC (rev 4927)
@@ -24,6 +24,8 @@
 #endif
 #include <mb_runtime_nop.h>
 #include <mb_mblock.h>
+#include <mb_class_registry.h>
+#include <mb_exception.h>
 
 mb_runtime_sptr 
 mb_make_runtime_nop()
@@ -42,23 +44,41 @@
   // nop for now
 }
 
+
 bool
-mb_runtime_nop::run(mb_mblock_sptr top)
+mb_runtime_nop::run(const std::string &instance_name,
+                   const std::string &class_name,
+                   pmt_t user_arg, pmt_t *result)
 {
   class initial_visitor : public mb_visitor
   {
   public:
-    bool operator()(mb_mblock *mblock, const std::string &path)
+    bool operator()(mb_mblock *mblock)
     {
-      mblock->set_instance_name(path);
-      mblock->init_fsm();
+      mblock->initial_transition();
       return true;
     }
   };
 
-  initial_visitor      visitor;
+  initial_visitor visitor;
 
-  top->walk_tree(&visitor);
+  if (result)
+    *result = PMT_T;
 
+  d_top = create_component(instance_name, class_name, user_arg);
+  d_top->walk_tree(&visitor);
+
   return true;
 }
+
+mb_mblock_sptr
+mb_runtime_nop::create_component(const std::string &instance_name,
+                                const std::string &class_name,
+                                pmt_t user_arg)
+{
+  mb_mblock_maker_t maker;
+  if (!mb_class_registry::lookup_maker(class_name, &maker))
+    throw mbe_no_such_class(0, class_name + " (in " + instance_name + ")");
+
+  return maker(this, instance_name, user_arg);
+}

Modified: gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_nop.h
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_nop.h       
2007-04-08 06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_nop.h       
2007-04-08 16:03:13 UTC (rev 4927)
@@ -33,12 +33,25 @@
  */
 class mb_runtime_nop : public mb_runtime
 {
-
+  mb_mblock_sptr       d_top;
+  
 public:
   mb_runtime_nop();
   ~mb_runtime_nop();
 
-  bool run(mb_mblock_sptr top);
+  bool run(const std::string &instance_name,
+          const std::string &class_name,
+          pmt_t user_arg,
+          pmt_t *result);
+
+  // QA only
+  mb_mblock_sptr top() { return d_top; }
+
+protected:
+  mb_mblock_sptr
+  create_component(const std::string &instance_name,
+                  const std::string &class_name,
+                  pmt_t user_arg);
 };
 
 #endif /* INCLUDED_MB_RUNTIME_NOP_H */

Copied: 
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_thread_per_block.cc
 (from rev 4926, 
gnuradio/branches/developers/eb/ibu/mblock/src/lib/mb_runtime_thread_per_block.cc)
===================================================================
--- 
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_thread_per_block.cc
                         (rev 0)
+++ 
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_thread_per_block.cc
 2007-04-08 16:03:13 UTC (rev 4927)
@@ -0,0 +1,238 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 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_thread_per_block.h>
+#include <mb_mblock.h>
+#include <mb_mblock_impl.h>
+#include <mb_class_registry.h>
+#include <mb_exception.h>
+#include <mb_worker.h>
+#include <omnithread.h>
+#include <iostream>
+
+static pmt_t s_sys_port = pmt_intern("%sys-port");
+static pmt_t s_shutdown = pmt_intern("%shutdown");
+static pmt_t s_halt = pmt_intern("%halt");
+
+
+static void
+send_sys_msg(mb_msg_queue &msgq, pmt_t signal,
+            pmt_t data = PMT_F, pmt_t metadata = PMT_F,
+            mb_pri_t priority = MB_PRI_BEST)
+{
+  mb_message_sptr msg = mb_make_message(signal, data, metadata, priority);
+  msg->set_port_id(s_sys_port);
+  msgq.insert(msg);
+}
+
+
+mb_runtime_thread_per_block::mb_runtime_thread_per_block()
+  : d_runtime_cond(&d_mutex),
+    d_shutdown_requested(false), d_shutdown_in_progress(false),
+    d_shutdown_result(PMT_T)
+{
+}
+
+mb_runtime_thread_per_block::~mb_runtime_thread_per_block()
+{
+  // FIXME iterate over workers and ensure that they are dead.
+
+  std::cerr << "\nmb_runtime_thread_per_block: dtor (# workers = "
+           << d_workers.size() << ")\n";
+}
+
+void
+mb_runtime_thread_per_block::request_shutdown(pmt_t result)
+{
+  omni_mutex_lock l1(d_mutex);
+
+  if (!d_shutdown_requested){
+    d_shutdown_result = result;
+    d_shutdown_requested = true;
+    d_runtime_cond.broadcast();
+  }
+}
+
+bool
+mb_runtime_thread_per_block::run(const std::string &instance_name,
+                                const std::string &class_name,
+                                pmt_t user_arg, pmt_t *result)
+{
+  if (result)          // set it to something now, in case we throw
+    *result = PMT_F;
+  
+  // reset the shutdown state
+  d_shutdown_requested = false;
+  d_shutdown_in_progress = false;
+  d_shutdown_result = PMT_T;
+
+  assert(d_workers.empty());
+
+  /*
+   * Create the top-level component, and recursively all of its
+   * subcomponents.
+   */
+  mb_mblock_sptr top = create_component(instance_name, class_name, user_arg);
+
+  run_loop();
+
+  if (result)
+    *result = d_shutdown_result;
+  
+  return true;
+}
+
+void
+mb_runtime_thread_per_block::run_loop()
+{
+  /*
+   * FIXME probably ought to recode this to use a message queue
+   * and state machine like the rest of the world ;)
+   */
+  while (1){
+    reap_dead_workers();
+    {
+      omni_mutex_lock l1(d_mutex);
+      if (d_workers.empty())   // no work left to do...
+       return;         
+
+      if (d_shutdown_requested && !d_shutdown_in_progress){
+       d_shutdown_in_progress = true;
+
+       // FIXME state machine, delay before sending %halt
+       send_all_sys_msg(s_shutdown);
+       send_all_sys_msg(s_halt);
+
+       continue;
+      }
+
+      d_runtime_cond.wait();   // wait for something to do.
+    }
+  }
+}
+
+void
+mb_runtime_thread_per_block::reap_dead_workers()
+{
+  omni_mutex_lock l1(d_mutex);
+
+  for (worker_iter_t wi = d_workers.begin(); wi != d_workers.end(); ){
+    bool is_dead;
+
+    // We can't join while holding the worker mutex, since that would
+    // attempt to destroy the mutex we're holding (omnithread's join
+    // deletes the omni_thread object after the pthread_join
+    // completes) Instead, we lock just long enough to figure out if
+    // the worker is dead.
+    {
+      omni_mutex_lock l2((*wi)->d_mutex);
+      is_dead = (*wi)->d_state == mb_worker::TS_DEAD;
+    }
+      
+    if (is_dead){
+      std::cerr << "\nruntime: "
+               << (*wi)->d_mblock->instance_name() << " is TS_DEAD\n";
+      void *ignore;
+      (*wi)->join(&ignore);
+      wi = d_workers.erase(wi);
+      continue;
+    }
+    ++wi;
+  }
+}
+
+//
+// Create the thread, then create the component in the thread.
+// Return a pointer to the created mblock.
+//
+mb_mblock_sptr
+mb_runtime_thread_per_block::create_component(const std::string &instance_name,
+                                             const std::string &class_name,
+                                             pmt_t user_arg)
+{
+  mb_mblock_maker_t maker;
+  if (!mb_class_registry::lookup_maker(class_name, &maker))
+    throw mbe_no_such_class(0, class_name + " (in " + instance_name + ")");
+
+  // FIXME here's where we'd lookup NUMA placement requests & mblock
+  // priorities and communicate them to the worker we're creating...
+
+  // Create the worker thread
+  mb_worker *w =
+    new mb_worker(this, maker, instance_name, user_arg);
+
+  w->start_undetached();  // start it
+
+  // Wait for it to reach TS_RUNNING or TS_DEAD
+
+  bool                                 is_dead;
+  mb_worker::cause_of_death_t  why_dead;
+  {
+    omni_mutex_lock l(w->d_mutex);
+    while (!(w->d_state == mb_worker::TS_RUNNING
+            || w->d_state == mb_worker::TS_DEAD))
+      w->d_state_cond.wait();
+
+    is_dead = w->d_state == mb_worker::TS_DEAD;
+    why_dead = w->d_why_dead;
+  }
+
+  // If the worker failed to init (constructor or initial_transition
+  // raised an exception), reap the worker now and raise an exception.
+
+  if (is_dead && why_dead != mb_worker::RIP_EXIT){
+
+    void *ignore;
+    w->join(&ignore);
+
+    // FIXME with some work we ought to be able to propagate the
+    // exception from the worker.
+    throw mbe_mblock_failed(0, instance_name);
+  }
+
+  assert(w->d_mblock);
+
+  // Add w to the vector of workers, and return the mblock.
+  {
+    omni_mutex_lock l(d_mutex);
+    d_workers.push_back(w);
+  }
+
+  return w->d_mblock;
+}
+
+void
+mb_runtime_thread_per_block::send_all_sys_msg(pmt_t signal,
+                                             pmt_t data,
+                                             pmt_t metadata,
+                                             mb_pri_t priority)
+{
+  // Already holding lock
+  // omni_mutex_lock l1(d_mutex);
+
+  for (worker_iter_t wi = d_workers.begin(); wi != d_workers.end(); ++wi){
+    send_sys_msg((*wi)->d_mblock->impl()->msgq(),
+                signal, data, metadata, priority);
+  }
+}

Copied: 
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_thread_per_block.h
 (from rev 4926, 
gnuradio/branches/developers/eb/ibu/mblock/src/lib/mb_runtime_thread_per_block.h)
===================================================================
--- 
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_thread_per_block.h
                          (rev 0)
+++ 
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_thread_per_block.h
  2007-04-08 16:03:13 UTC (rev 4927)
@@ -0,0 +1,72 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 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_THREAD_PER_BLOCK_H
+#define INCLUDED_MB_RUNTIME_THREAD_PER_BLOCK_H
+
+#include <mb_runtime.h>
+#include <mb_worker.h>
+
+/*!
+ * \brief Concrete runtime that uses a thread per mblock
+ * \implementation
+ *
+ * These are all implementation details.
+ */
+class mb_runtime_thread_per_block : public mb_runtime
+{
+public:
+  omni_mutex                 d_mutex;
+  omni_condition             d_runtime_cond;  // runtime waits here
+  //std::vector<mb_worker_sptr> d_workers;
+  std::vector<mb_worker*>     d_workers;
+  bool                       d_shutdown_requested;
+  bool                       d_shutdown_in_progress;
+  pmt_t                              d_shutdown_result;
+
+  //typedef std::vector<mb_worker_sptr>::iterator  worker_iter_t;
+  typedef std::vector<mb_worker*>::iterator  worker_iter_t;
+
+  mb_runtime_thread_per_block();
+  ~mb_runtime_thread_per_block();
+
+  bool run(const std::string &instance_name,
+          const std::string &class_name,
+          pmt_t user_arg,
+          pmt_t *result);
+
+  void request_shutdown(pmt_t result);
+
+protected:
+  mb_mblock_sptr
+  create_component(const std::string &instance_name,
+                  const std::string &class_name,
+                  pmt_t user_arg);
+
+  void reap_dead_workers();
+  void run_loop();
+
+  void send_all_sys_msg(pmt_t signal, pmt_t data = PMT_F,
+                       pmt_t metadata = PMT_F,
+                       mb_pri_t priority = MB_PRI_BEST);
+
+};
+
+#endif /* INCLUDED_MB_RUNTIME_THREAD_PER_BLOCK_H */

Deleted: 
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_thread_per_mblock.cc

Deleted: 
gnuradio/branches/features/inband-usb/mblock/src/lib/mb_runtime_thread_per_mblock.h

Copied: gnuradio/branches/features/inband-usb/mblock/src/lib/mb_worker.cc (from 
rev 4926, gnuradio/branches/developers/eb/ibu/mblock/src/lib/mb_worker.cc)
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/mb_worker.cc           
                (rev 0)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/mb_worker.cc   
2007-04-08 16:03:13 UTC (rev 4927)
@@ -0,0 +1,146 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 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_worker.h>
+#include <mb_runtime_thread_per_block.h>
+#include <mb_exception.h>
+#include <mb_mblock.h>
+#include <iostream>
+
+#define VERBOSE 0              // define to 0 or 1
+
+#include <sys/syscall.h>       // Move this somewhere else and autoconf
+#include <unistd.h>
+
+#ifdef SYS_gettid
+int mb_gettid()
+{
+  return syscall(SYS_gettid);
+}
+#else
+int mb_gettid()
+{
+  return -1;
+}
+#endif
+
+
+mb_worker::mb_worker(mb_runtime_thread_per_block *runtime,
+                    mb_mblock_maker_t maker,
+                    const std::string &instance_name,
+                    pmt_t user_arg)
+  : omni_thread((void *) 0, PRIORITY_NORMAL),
+    d_runtime(runtime), d_maker(maker),
+    d_instance_name(instance_name), d_user_arg(user_arg),
+    d_state_cond(&d_mutex), d_state(TS_UNINITIALIZED),
+    d_why_dead(RIP_NOT_DEAD_YET)
+{
+}
+
+#if 0
+mb_worker::~mb_worker()
+{
+}
+#endif
+
+void
+mb_worker::set_state(worker_state_t state)
+{
+  omni_mutex_lock  l1(d_runtime->d_mutex);     // lock runtime first, then 
worker
+  omni_mutex_lock  l2(d_mutex);
+
+  d_state = state;                       // update our state
+  d_state_cond.broadcast();              // Notify everybody who cares...
+  d_runtime->d_runtime_cond.broadcast();
+}
+
+void *
+mb_worker::run_undetached(void *ignored)
+{
+  // FIXME add pthread_sigmask stuff
+
+  try {
+    worker_thread_top_level();
+    d_why_dead = RIP_EXIT;
+  }
+  catch (mbe_terminate){
+    d_why_dead = RIP_TERMINATE;
+  }
+  catch (mbe_exit){
+    d_why_dead = RIP_EXIT;
+  }
+  catch (...){
+    if (d_why_dead == RIP_NOT_DEAD_YET)
+      d_why_dead = RIP_UNHANDLED_EXCEPTION;
+  }
+
+  if (VERBOSE)
+    std::cerr << "\nrun_undetached: about to return, d_why_dead = "
+             << d_why_dead << std::endl;
+
+  set_state(TS_DEAD);
+  return 0;
+}
+
+void
+mb_worker::worker_thread_top_level()
+{
+  if (VERBOSE)
+    std::cerr << "worker_thread_top_level (enter):" << std::endl
+             << "  instance_name: " << d_instance_name << std::endl
+             << "  omnithread id: " << id() << std::endl
+             << "  gettid:        " << mb_gettid() << std::endl
+             << "  getpid:        " << getpid() << std::endl;
+
+  cause_of_death_t pending_cause_of_death = RIP_NOT_DEAD_YET;
+  
+  try {
+    pending_cause_of_death = RIP_CTOR_EXCEPTION;
+    d_mblock = d_maker(d_runtime, d_instance_name, d_user_arg);
+
+    if (VERBOSE)
+      std::cerr << "worker_thread_top_level (post-construction):" << std::endl
+               << "  instance_name: " << d_instance_name << std::endl;
+
+    pending_cause_of_death = RIP_INIT_EXCEPTION;
+    d_mblock->initial_transition();
+
+    if (VERBOSE)
+      std::cerr << "worker_thread_top_level (post-initial-transition):" << 
std::endl
+               << "  instance_name: " << d_instance_name << std::endl;
+
+    set_state(TS_RUNNING);
+
+    pending_cause_of_death = RIP_UNHANDLED_EXCEPTION;
+    d_mblock->main_loop();
+  }
+  catch (...){
+    d_why_dead = pending_cause_of_death;
+    throw;
+  }
+
+  if (VERBOSE)
+    std::cerr << "worker_thread_top_level (exit):" << std::endl
+             << "  instance_name: " << d_instance_name << std::endl;
+}

Copied: gnuradio/branches/features/inband-usb/mblock/src/lib/mb_worker.h (from 
rev 4926, gnuradio/branches/developers/eb/ibu/mblock/src/lib/mb_worker.h)
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/mb_worker.h            
                (rev 0)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/mb_worker.h    
2007-04-08 16:03:13 UTC (rev 4927)
@@ -0,0 +1,106 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2007 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_WORKER_H
+#define INCLUDED_MB_WORKER_H
+
+#include <omnithread.h>
+#include <mb_common.h>
+#include <mb_class_registry.h>
+
+
+class mb_worker;
+//typedef boost::shared_ptr<mb_worker> mb_worker_sptr;
+
+class mb_runtime_thread_per_block;
+
+/*!
+ * \brief Worker thread for thread_per_block runtime
+ * \implementation
+ */
+class mb_worker : public omni_thread
+{
+public:
+  //! worker thread states
+  enum worker_state_t {
+    TS_UNINITIALIZED,  // new, uninitialized
+    TS_RUNNING,                // normal steady-state condition.
+    TS_DEAD            // thread is dead
+  };
+
+  //! why we're dead
+  enum cause_of_death_t {
+    RIP_NOT_DEAD_YET,          // not dead
+    RIP_EXIT,                  // normal exit
+    RIP_TERMINATE,             // caught terminate exception
+    RIP_CTOR_EXCEPTION,                // constructor raised an exception
+    RIP_INIT_EXCEPTION,                // initial_transition rasised an 
exception
+    RIP_UNHANDLED_EXCEPTION    // somebody (most likely handle_message) raised 
an exception
+  };
+
+  /*
+   * Args used by new thread to create mb_mblock
+   */
+  mb_runtime_thread_per_block  *d_runtime;
+  mb_mblock_maker_t            d_maker;
+  std::string                  d_instance_name;
+  pmt_t                                d_user_arg;
+
+  mb_mblock_sptr               d_mblock;       //< holds pointer to created 
mblock
+
+  /*!
+   * \brief General mutex for all these fields.
+   *
+   * They are accessed by both the main runtime thread and the newly
+   * created thread that runs the mblock's main loop.
+   */
+  omni_mutex                   d_mutex; 
+  omni_condition               d_state_cond;   //< state change notifications
+  worker_state_t               d_state;
+  cause_of_death_t             d_why_dead;
+
+  mb_worker(mb_runtime_thread_per_block *runtime,
+           mb_mblock_maker_t maker,
+           const std::string &instance_name,
+           pmt_t user_arg);
+
+  // ~mb_worker();
+
+
+  /*!
+   * \brief This code runs as the top-level of the new thread
+   */
+  void worker_thread_top_level();
+  
+  /*!
+   * \brief Invokes the top-level of the new thread (name kind of sucks)
+   */
+  void *run_undetached(void *arg);
+
+private:
+  // Neither d_mutex nor runtime->d_mutex may be held while calling this.
+  // It locks and unlocks them itself.
+  void set_state(worker_state_t state);
+};
+
+
+
+#endif /* INCLUDED_MB_WORKER_H */

Modified: gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock.cc
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock.cc   
2007-04-08 06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock.cc   
2007-04-08 16:03:13 UTC (rev 4927)
@@ -27,6 +27,7 @@
 #include <qa_mblock.h>
 #include <qa_mblock_prims.h>
 #include <qa_mblock_send.h>
+#include <qa_mblock_sys.h>
 
 CppUnit::TestSuite *
 qa_mblock::suite()
@@ -35,6 +36,7 @@
 
   s->addTest (qa_mblock_prims::suite());
   s->addTest (qa_mblock_send::suite());
+  s->addTest (qa_mblock_sys::suite());
   
   return s;
 }

Modified: 
gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock_prims.cc
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock_prims.cc     
2007-04-08 06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock_prims.cc     
2007-04-08 16:03:13 UTC (rev 4927)
@@ -34,6 +34,7 @@
 #include <mb_message.h>
 #include <mb_mblock_impl.h>
 #include <mb_msg_accepter.h>
+#include <mb_class_registry.h>
 #include <stdio.h>
 
 static pmt_t s_cs = pmt_intern("cs");
@@ -47,42 +48,49 @@
 class dp_1 : public mb_mblock
 {
 public:
-  dp_1();
+  dp_1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~dp_1();
 };
 
-dp_1::dp_1()
+dp_1::dp_1(mb_runtime *runtime, const std::string &instance_name, pmt_t 
user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
 }
 
 dp_1::~dp_1(){}
 
+REGISTER_MBLOCK_CLASS(dp_1);
+
 // ----------------------------------------------------------------
 
 class dp_2 : public mb_mblock
 {
 public:
-  dp_2();
+  dp_2(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~dp_2();
 };
 
-dp_2::dp_2()
+dp_2::dp_2(mb_runtime *runtime, const std::string &instance_name, pmt_t 
user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
   define_port("cs", "cs-protocol", false, mb_port::EXTERNAL);
 }
 
 dp_2::~dp_2(){}
 
+REGISTER_MBLOCK_CLASS(dp_2);
+
 // ----------------------------------------------------------------
 
 class dp_3 : public mb_mblock
 {
 public:
-  dp_3();
+  dp_3(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~dp_3();
 };
 
-dp_3::dp_3()
+dp_3::dp_3(mb_runtime *runtime, const std::string &instance_name, pmt_t 
user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
   define_port("cs", "cs-protocol", false, mb_port::EXTERNAL);
   define_port("cs", "cs-protocol", false, mb_port::EXTERNAL);  // duplicate def
@@ -90,19 +98,23 @@
 
 dp_3::~dp_3(){}
 
+REGISTER_MBLOCK_CLASS(dp_3);
+
 // ----------------------------------------------------------------
 
 void
 qa_mblock_prims::test_define_ports()
 {
-  // std::vector<mb_port_sptr> intf;
+  
+  mb_runtime_sptr rts = mb_make_runtime();
+  mb_runtime *rt = rts.get();
+  
+  // Should work
+  mb_mblock_sptr  mb1 = mb_mblock_sptr(new dp_1(rt, "top", PMT_F));
 
-  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);
+  CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dp_2(rt, "top", PMT_F)),
+                      std::runtime_error);
 
   // define the protocol class
   pmt_t pc = mb_make_protocol_class(pmt_intern("cs-protocol"),
@@ -112,10 +124,11 @@
 
   // std::cout << "pc = " << pc << '\n';
 
-  mb_mblock_sptr mb2 = mb_mblock_sptr(new dp_2());
+  mb_mblock_sptr mb2 = mb_mblock_sptr(new dp_2(rt, "top", PMT_F));
 
   // raises pmt_exception because of duplicate port definition of "cs"
-  CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dp_3()), mbe_duplicate_port);
+  CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dp_3(rt, "top", PMT_F)),
+                      mbe_duplicate_port);
 }
 
 // ================================================================
@@ -123,61 +136,74 @@
 class dc_0 : public mb_mblock
 {
 public:
-  dc_0();
+  dc_0(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~dc_0();
 };
 
-dc_0::dc_0()
+dc_0::dc_0(mb_runtime *runtime, const std::string &instance_name, pmt_t 
user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
 }
 
 dc_0::~dc_0() {}
 
+REGISTER_MBLOCK_CLASS(dc_0);
+
 // ----------------------------------------------------------------
 
 class dc_ok : public mb_mblock
 {
 public:
-  dc_ok();
+  dc_ok(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~dc_ok();
 };
 
-dc_ok::dc_ok()
+dc_ok::dc_ok(mb_runtime *runtime, const std::string &instance_name, pmt_t 
user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
-  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()));
+  define_component("c0", "dc_0");
+  define_component("c1", "dc_0");
+  define_component("c2", "dc_0");
 }
 
 dc_ok::~dc_ok(){}
 
+REGISTER_MBLOCK_CLASS(dc_ok);
+
 // ----------------------------------------------------------------
 
 class dc_not_ok : public mb_mblock
 {
 public:
-  dc_not_ok();
+  dc_not_ok(mb_runtime *runtime, const std::string &instance_name, pmt_t 
user_arg);
   ~dc_not_ok();
 };
 
-dc_not_ok::dc_not_ok()
-  : mb_mblock()
+dc_not_ok::dc_not_ok(mb_runtime *runtime, const std::string &instance_name, 
pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
-  define_component("c0", mb_mblock_sptr(new dc_0()));
-  define_component("c0", mb_mblock_sptr(new dc_0()));  // duplicate name
+  define_component("c0", "dc_0");
+  define_component("c0", "dc_0");      // duplicate name
 }
 
 dc_not_ok::~dc_not_ok(){}
 
+REGISTER_MBLOCK_CLASS(dc_not_ok);
+
 // ----------------------------------------------------------------
 
 void
 qa_mblock_prims::test_define_components()
 {
-  mb_mblock_sptr       mb1 = mb_mblock_sptr(new dc_ok());      // OK
+  mb_runtime_sptr rts = mb_make_runtime();
+  mb_runtime *rt = rts.get();
+  
+  // Should work
+  mb_mblock_sptr  mb1 = mb_mblock_sptr(new dc_ok(rt, "top", PMT_F));
 
   // raises pmt_exception because of duplicate component definition of "c0"
-  CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dc_not_ok()), 
mbe_duplicate_component);
+  CPPUNIT_ASSERT_THROW(mb_mblock_sptr(new dc_not_ok(rt, "top", PMT_F)),
+                      mbe_duplicate_component);
 }
 
 // ================================================================
@@ -185,7 +211,9 @@
 class tc_norm : public mb_mblock
 {
 public:
-  tc_norm(){
+  tc_norm(mb_runtime *runtime, const std::string &instance_name, pmt_t 
user_arg)
+    : mb_mblock(runtime, instance_name, user_arg)
+  {
     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);
@@ -197,22 +225,26 @@
 
 tc_norm::~tc_norm(){}
 
+REGISTER_MBLOCK_CLASS(tc_norm);
+
 ////////////////////////////////////////////////////////////////
 
 class tc_0 : public mb_mblock
 {
 public:
-  tc_0(){
+  tc_0(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+    : mb_mblock(runtime, instance_name, user_arg)
+  {
     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()));
+    define_component("c0", "tc_norm");
+    define_component("c1", "tc_norm");
+    define_component("c2", "tc_norm");
+    define_component("c3", "tc_norm");
+    define_component("c4", "tc_norm");
+    define_component("c5", "tc_norm");
 
     // OK
     connect("c0", "norm", "c1", "conj");
@@ -284,14 +316,18 @@
 
 tc_0::~tc_0(){}
 
+REGISTER_MBLOCK_CLASS(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()));
+  tc_1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+    : mb_mblock(runtime, instance_name, user_arg)
+  {
+    define_component("c0", "tc_norm");
+    define_component("c1", "tc_norm");
 
     connect("c0", "norm", "c1", "conj");
   }
@@ -301,6 +337,8 @@
 
 tc_1::~tc_1(){}
 
+REGISTER_MBLOCK_CLASS(tc_1);
+
 ////////////////////////////////////////////////////////////////
 
 void
@@ -315,7 +353,10 @@
                         pmt_list1(pmt_intern("in")),           // in
                         pmt_list1(pmt_intern("out")));         // out
 
-  mb_mblock_sptr       mb0 = mb_mblock_sptr(new tc_0());
+  mb_runtime_sptr rts = mb_make_runtime();
+  mb_runtime *rt = rts.get();
+
+  mb_mblock_sptr       mb0 = mb_mblock_sptr(new tc_0(rt, "top", PMT_F));
 }
 
 ////////////////////////////////////////////////////////////////
@@ -377,8 +418,11 @@
 void
 qa_mblock_prims::test_make_accepter()
 {
+  mb_runtime_sptr rts = mb_make_runtime();
+  mb_runtime *rt = rts.get();
+
   // create a block
-  mb_mblock_sptr mb = mb_mblock_sptr(new dp_2());
+  mb_mblock_sptr mb = mb_mblock_sptr(new dp_2(rt, "top", PMT_F));
 
   // use "internal use only" method...
   mb_msg_accepter_sptr accepter = mb->impl()->make_accepter("cs");

Modified: gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock_send.cc
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock_send.cc      
2007-04-08 06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock_send.cc      
2007-04-08 16:03:13 UTC (rev 4927)
@@ -35,6 +35,7 @@
 #include <mb_message.h>
 #include <mb_mblock_impl.h>
 #include <mb_msg_accepter.h>
+#include <mb_class_registry.h>
 #include <stdio.h>
 
 static pmt_t s_data    = pmt_intern("data");
@@ -57,6 +58,12 @@
 
 }
 
+mb_mblock_sptr
+get_top(mb_runtime_sptr rts)
+{
+  return dynamic_cast<mb_runtime_nop *>(rts.get())->top();
+}
+
 // ================================================================
 //                    test_simple_routing
 // ================================================================
@@ -70,12 +77,13 @@
   mb_port_sptr d_p3;
 
 public:
-  sr1();
+  sr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~sr1();
-  void init_fsm();
+  void initial_transition();
 };
 
-sr1::sr1()
+sr1::sr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
   d_p1 = define_port("p1", "qa-send-cs", true, mb_port::EXTERNAL);
   d_p2 = define_port("p2", "qa-send-cs", true, mb_port::EXTERNAL);
@@ -85,9 +93,9 @@
 sr1::~sr1(){}
   
 void
-sr1::init_fsm()
+sr1::initial_transition()
 {
-  // std::cout << instance_name() << "[sr1]: init_fsm\n";
+  // std::cout << instance_name() << "[sr1]: initial_transition\n";
 
   // send two messages to each port
   pmt_t our_name = pmt_intern(instance_name());
@@ -98,6 +106,8 @@
   d_p2->send(s_status, pmt_list3(our_name, s_p2, pmt_from_long(1)));
 }
 
+REGISTER_MBLOCK_CLASS(sr1);
+
 // ----------------------------------------------------------------
 
 // top-level container block for test_simple_routing
@@ -106,17 +116,18 @@
   mb_port_sptr d_p0;
   
 public:
-  sr0();
+  sr0(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~sr0();
-  void init_fsm();
+  void initial_transition();
 };
 
-sr0::sr0()
+sr0::sr0(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
   d_p0 = define_port("p0", "qa-send-cs", false, mb_port::INTERNAL);
 
-  define_component("mb1", mb_mblock_sptr(new sr1()));
-  define_component("mb2", mb_mblock_sptr(new sr1()));
+  define_component("mb1", "sr1");
+  define_component("mb2", "sr1");
 
   connect("self", "p0", "mb1", "p1");
   connect("mb1", "p2", "mb2", "p3");
@@ -126,9 +137,9 @@
 sr0::~sr0(){}
 
 void
-sr0::init_fsm()
+sr0::initial_transition()
 {
-  // std::cout << instance_name() << "[sr0]: init_fsm\n";
+  // std::cout << instance_name() << "[sr0]: initial_transition\n";
 
   // send two messages to p0
   pmt_t our_name = pmt_intern(instance_name());
@@ -136,6 +147,8 @@
   d_p0->send(s_control, pmt_list3(our_name, s_p0, pmt_from_long(1)));
 }
   
+REGISTER_MBLOCK_CLASS(sr0);
+
 // ----------------------------------------------------------------
 
 /*
@@ -151,9 +164,10 @@
   mb_message_sptr msg;
 
   mb_runtime_sptr rt = mb_make_runtime_nop();
-  mb_mblock_sptr mb0 = mb_mblock_sptr(new sr0());
-  rt->run(mb0);
+  rt->run("top", "sr0", PMT_F);
 
+  mb_mblock_sptr mb0 = get_top(rt);
+  
   // Reach into the guts and see if the messages ended up where they should 
have
 
   // mb0 should have received two messages sent from mb1 via its p1
@@ -238,12 +252,13 @@
   mb_port_sptr d_p2;
 
 public:
-  rr2();
+  rr2(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~rr2();
-  void init_fsm();
+  void initial_transition();
 };
 
-rr2::rr2()
+rr2::rr2(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
   d_p1 = define_port("p1", "qa-send-cs", true,  mb_port::EXTERNAL);
   d_p2 = define_port("p2", "qa-send-cs", false, mb_port::EXTERNAL);
@@ -252,9 +267,9 @@
 rr2::~rr2(){}
   
 void
-rr2::init_fsm()
+rr2::initial_transition()
 {
-  // std::cout << instance_name() << "[rr2]: init_fsm\n";
+  // std::cout << instance_name() << "[rr2]: initial_transition\n";
 
   // send two messages via p1
   pmt_t our_name = pmt_intern(instance_name());
@@ -262,6 +277,8 @@
   d_p1->send(s_status, pmt_list3(our_name, s_p1, pmt_from_long(1)));
 }
 
+REGISTER_MBLOCK_CLASS(rr2);
+
 // ----------------------------------------------------------------
 
 // intermediate block for test_relay_routing
@@ -272,16 +289,17 @@
   mb_port_sptr d_p2;
 
 public:
-  rr1();
+  rr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~rr1();
 };
 
-rr1::rr1()
+rr1::rr1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
   d_p1 = define_port("p1", "qa-send-cs", true,  mb_port::RELAY);
   d_p2 = define_port("p2", "qa-send-cs", false, mb_port::RELAY);
 
-  define_component("c0", mb_mblock_sptr(new rr2()));
+  define_component("c0", "rr2");
 
   connect("self", "p1", "c0", "p1");
   connect("self", "p2", "c0", "p2");
@@ -289,6 +307,8 @@
 
 rr1::~rr1(){}
 
+REGISTER_MBLOCK_CLASS(rr1);
+
 // ----------------------------------------------------------------
 
 // top-level container for test_relay_routing
@@ -296,14 +316,15 @@
 class rr0_a : public mb_mblock
 {
 public:
-  rr0_a();
+  rr0_a(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~rr0_a();
 };
 
-rr0_a::rr0_a()
+rr0_a::rr0_a(mb_runtime *runtime, const std::string &instance_name, pmt_t 
user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
-  define_component("c0", mb_mblock_sptr(new rr1()));
-  define_component("c1", mb_mblock_sptr(new rr2()));
+  define_component("c0", "rr1");
+  define_component("c1", "rr2");
 
   connect("c0", "p1", "c1", "p2");
   connect("c0", "p2", "c1", "p1");
@@ -311,6 +332,7 @@
 
 rr0_a::~rr0_a(){}
 
+REGISTER_MBLOCK_CLASS(rr0_a);
 
 /*
  * This tests basic message routing using RELAY and EXTERNAL ports.
@@ -323,8 +345,8 @@
   mb_message_sptr msg;
 
   mb_runtime_sptr rt = mb_make_runtime_nop();
-  mb_mblock_sptr  top = mb_mblock_sptr(new rr0_a());
-  rt->run(top);
+  rt->run("top", "rr0_a", PMT_F);
+  mb_mblock_sptr top = get_top(rt);
 
   // Reach into the guts and see if the messages ended up where they should 
have
 
@@ -377,14 +399,15 @@
 class rr0_b : public mb_mblock
 {
 public:
-  rr0_b();
+  rr0_b(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
   ~rr0_b();
 };
 
-rr0_b::rr0_b()
+rr0_b::rr0_b(mb_runtime *runtime, const std::string &instance_name, pmt_t 
user_arg)
+  : mb_mblock(runtime, instance_name, user_arg)
 {
-  define_component("c0", mb_mblock_sptr(new rr1()));
-  define_component("c1", mb_mblock_sptr(new rr1()));
+  define_component("c0", "rr1");
+  define_component("c1", "rr1");
 
   connect("c0", "p1", "c1", "p2");
   connect("c0", "p2", "c1", "p1");
@@ -392,6 +415,7 @@
 
 rr0_b::~rr0_b(){}
 
+REGISTER_MBLOCK_CLASS(rr0_b);
 
 /*
  * This tests basic message routing using RELAY and EXTERNAL ports.
@@ -404,8 +428,8 @@
   mb_message_sptr msg;
 
   mb_runtime_sptr rt = mb_make_runtime_nop();
-  mb_mblock_sptr  top = mb_mblock_sptr(new rr0_b());
-  rt->run(top);
+  rt->run("top", "rr0_b", PMT_F);
+  mb_mblock_sptr top = get_top(rt);
 
   // Reach into the guts and see if the messages ended up where they should 
have
 

Copied: gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock_sys.cc 
(from rev 4926, 
gnuradio/branches/developers/eb/ibu/mblock/src/lib/qa_mblock_sys.cc)
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock_sys.cc       
                        (rev 0)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock_sys.cc       
2007-04-08 16:03:13 UTC (rev 4927)
@@ -0,0 +1,136 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2007 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qa_mblock_sys.h>
+#include <cppunit/TestAssert.h>
+#include <mb_mblock.h>
+#include <mb_runtime.h>
+#include <mb_runtime_nop.h>            // QA only
+#include <mb_protocol_class.h>
+#include <mb_exception.h>
+#include <mb_msg_queue.h>
+#include <mb_message.h>
+#include <mb_mblock_impl.h>
+#include <mb_msg_accepter.h>
+#include <mb_class_registry.h>
+#include <stdio.h>
+#include <string.h>
+
+
+static pmt_t s_data    = pmt_intern("data");
+static pmt_t s_status  = pmt_intern("status");
+static pmt_t s_control = pmt_intern("control");
+static pmt_t s_p0   = pmt_intern("p0");
+static pmt_t s_p1   = pmt_intern("p1");
+static pmt_t s_p2   = pmt_intern("p2");
+static pmt_t s_p3   = pmt_intern("p3");
+static pmt_t s_e1   = pmt_intern("e1");
+static pmt_t s_r1   = pmt_intern("r1");
+
+static void
+define_protocol_classes()
+{
+  mb_make_protocol_class(s_data,               // name
+                        pmt_list1(s_data),     // incoming
+                        pmt_list1(s_data));    // outgoing
+}
+
+
+// ================================================================
+//                       test_sys_1
+// ================================================================
+
+class sys_1 : public mb_mblock
+{
+  pmt_t                d_user_arg;
+  mb_port_sptr p_data;
+
+public:
+  sys_1(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
+  ~sys_1();
+  void initial_transition();
+};
+
+sys_1::sys_1(mb_runtime *runtime, const std::string &instance_name, pmt_t 
user_arg)
+  : mb_mblock(runtime, instance_name, user_arg),
+    d_user_arg(user_arg)
+{
+  p_data = define_port("data", "data", true, mb_port::EXTERNAL);
+}
+
+sys_1::~sys_1(){}
+  
+void
+sys_1::initial_transition()
+{
+  shutdown_all(d_user_arg);
+}
+
+REGISTER_MBLOCK_CLASS(sys_1);
+
+void
+qa_mblock_sys::test_sys_1()
+{
+  define_protocol_classes();
+
+  pmt_t        result;
+  pmt_t        n1 = pmt_from_long(1);
+  pmt_t        n2 = pmt_from_long(2);
+
+  mb_runtime_sptr rt1 = mb_make_runtime();
+
+#if 0
+  try {
+    rt1->run("top-1", "sys_1", n1, &result);
+  }
+  catch (omni_thread_fatal e){
+    std::cerr << "caught omni_thread_fatal: error = " << e.error
+             << ": " << strerror(e.error) << std::endl;
+  }
+  catch (omni_thread_invalid){
+    std::cerr << "caught omni_thread_invalid\n";
+  }
+#else
+    rt1->run("top-1", "sys_1", n1, &result);
+#endif
+  CPPUNIT_ASSERT(pmt_equal(n1, result));
+  
+  // Execute run a second time, with the same rt, to ensure sanity.
+  rt1->run("top-2", "sys_1", n2, &result);
+  CPPUNIT_ASSERT(pmt_equal(n2, result));
+}
+
+
+void
+qa_mblock_sys::test_sys_2()
+{
+}
+
+void
+qa_mblock_sys::test_sys_3()
+{
+}
+

Copied: gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock_sys.h 
(from rev 4926, 
gnuradio/branches/developers/eb/ibu/mblock/src/lib/qa_mblock_sys.h)
===================================================================
--- gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock_sys.h        
                        (rev 0)
+++ gnuradio/branches/features/inband-usb/mblock/src/lib/qa_mblock_sys.h        
2007-04-08 16:03:13 UTC (rev 4927)
@@ -0,0 +1,43 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2006,2007 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_SYS_H
+#define INCLUDED_QA_MBLOCK_SYS_H
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestCase.h>
+
+class qa_mblock_sys : public CppUnit::TestCase {
+
+  CPPUNIT_TEST_SUITE(qa_mblock_sys);
+  CPPUNIT_TEST(test_sys_1);
+  CPPUNIT_TEST(test_sys_2);
+  CPPUNIT_TEST(test_sys_3);
+  CPPUNIT_TEST_SUITE_END();
+
+ private:
+  void test_sys_1();
+  void test_sys_2();
+  void test_sys_3();
+};
+
+#endif /* INCLUDED_QA_MBLOCK_SYS_H */
+

Modified: gnuradio/branches/features/inband-usb/omnithread/omnithread.h
===================================================================
--- gnuradio/branches/features/inband-usb/omnithread/omnithread.h       
2007-04-08 06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/omnithread/omnithread.h       
2007-04-08 16:03:13 UTC (rev 4927)
@@ -391,11 +391,15 @@
        // execute the run() or run_undetached() member functions depending on
        // whether start() or start_undetached() is called respectively.
 
+public:
+
     void start_undetached(void);
        // can be used with the above constructor in a derived class to cause
        // the thread to be undetached.  In this case the thread executes the
        // run_undetached member function.
 
+protected:
+
     virtual ~omni_thread(void);
        // destructor cannot be called by user (except via a derived class).
        // Use exit() or cancel() instead. This also means a thread object must

Modified: gnuradio/branches/features/inband-usb/omnithread/posix.cc
===================================================================
--- gnuradio/branches/features/inband-usb/omnithread/posix.cc   2007-04-08 
06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/omnithread/posix.cc   2007-04-08 
16:03:13 UTC (rev 4927)
@@ -51,6 +51,10 @@
 #include <time.h>
 #include <omnithread.h>
 
+#if (PthreadDraftVersion == 0)
+#error "PthreadDraftVersion not defined.  If not sure, define it to 10"
+#endif
+
 #ifdef HAVE_NANOSLEEP
 #undef NoNanoSleep
 #else
@@ -73,8 +77,14 @@
 #endif
 #endif
 
+#if 1
 #define DB(x) // x
-//#include <iostream.h> or #include <iostream> if DB is on.
+#else
+#define DB(x) x
+#include <iostream>
+using std::cerr;
+using std::endl;
+#endif
 
 #if (PthreadDraftVersion <= 6)
 #define ERRNO(x) (((x) != 0) ? (errno) : 0)

Modified: gnuradio/branches/features/inband-usb/pmt/src/lib/pmt.h
===================================================================
--- gnuradio/branches/features/inband-usb/pmt/src/lib/pmt.h     2007-04-08 
06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/pmt/src/lib/pmt.h     2007-04-08 
16:03:13 UTC (rev 4927)
@@ -27,7 +27,7 @@
 #include <complex>
 #include <string>
 #include <stdint.h>
-#include <iostream>
+#include <iosfwd>
 #include <stdexcept>
 
 /*!

Modified: 
gnuradio/branches/features/inband-usb/usrp/host/lib/inband/usrp_server.cc
===================================================================
--- gnuradio/branches/features/inband-usb/usrp/host/lib/inband/usrp_server.cc   
2007-04-08 06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/usrp/host/lib/inband/usrp_server.cc   
2007-04-08 16:03:13 UTC (rev 4927)
@@ -23,6 +23,7 @@
 #include <config.h>
 #endif
 #include <usrp_server.h>
+#include <iostream>
 
 
 // FIXME We should machine generate these by a simple preprocessor run over 
this file
@@ -49,7 +50,8 @@
 static pmt_t s_response_xmit_raw_frame = pmt_intern("response-xmit-raw-frame");
 
 
-usrp_server::usrp_server()
+usrp_server::usrp_server(mb_runtime *rt, const std::string &instance_name, 
pmt_t user_arg)
+  : mb_mblock(rt, instance_name, user_arg)
 {
   // define our ports
 
@@ -82,7 +84,7 @@
 
 
 void
-usrp_server::init_fsm()
+usrp_server::initial_transition()
 {
   // the initial transition
 }

Modified: 
gnuradio/branches/features/inband-usb/usrp/host/lib/inband/usrp_server.h
===================================================================
--- gnuradio/branches/features/inband-usb/usrp/host/lib/inband/usrp_server.h    
2007-04-08 06:16:32 UTC (rev 4926)
+++ gnuradio/branches/features/inband-usb/usrp/host/lib/inband/usrp_server.h    
2007-04-08 16:03:13 UTC (rev 4927)
@@ -42,10 +42,10 @@
   // add more stuff here...
 
 public:
-  usrp_server();
+  usrp_server(mb_runtime *rt, const std::string &instance_name, pmt_t 
user_arg);
   ~usrp_server();
 
-  void init_fsm();
+  void initial_transition();
   void handle_message(mb_message_sptr msg);
 };
 





reply via email to

[Prev in Thread] Current Thread [Next in Thread]