GNU Radio 3.2.2 C++ API
mblock.h
Go to the documentation of this file.
00001 /* -*- c++ -*- */
00002 /*
00003  * Copyright 2006,2008 Free Software Foundation, Inc.
00004  * 
00005  * This file is part of GNU Radio
00006  * 
00007  * GNU Radio is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 3, or (at your option)
00010  * any later version.
00011  * 
00012  * GNU Radio is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  * 
00017  * You should have received a copy of the GNU General Public License along
00018  * with this program; if not, write to the Free Software Foundation, Inc.,
00019  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00020  */
00021 #ifndef INCLUDED_MB_MBLOCK_H
00022 #define INCLUDED_MB_MBLOCK_H
00023 
00024 #include <mblock/common.h>
00025 #include <mblock/message.h>
00026 #include <mblock/port.h>
00027 #include <mblock/time.h>
00028 
00029 
00030 /*!
00031  * Abstract class implementing visitor pattern
00032  * \ingroup internal
00033  */
00034 class mb_visitor
00035 {
00036 public:
00037   virtual ~mb_visitor();
00038   virtual bool operator()(mb_mblock *mblock) = 0;
00039 };
00040 
00041 // ----------------------------------------------------------------------
00042 
00043 /*!
00044  * \brief Parent class for all message passing blocks
00045  *
00046  * Subclass this to define your mblocks.
00047  */
00048 class mb_mblock : boost::noncopyable,
00049                   public boost::enable_shared_from_this<mb_mblock>
00050 {
00051 private:
00052   mb_mblock_impl_sptr           d_impl;         // implementation details
00053 
00054   friend class mb_runtime;
00055   friend class mb_mblock_impl;
00056   friend class mb_worker;
00057 
00058 protected:
00059   /*!
00060    * \brief mblock constructor.
00061    *
00062    * Initializing all mblocks in the system is a 3 step procedure.
00063    *
00064    * The top level mblock's constructor is run.  That constructor 
00065    * (a) registers all of its ports using define_port, (b) registers any
00066    * subcomponents it may have via the define_component method, and
00067    * then (c) issues connect calls to wire its subcomponents together.
00068    *
00069    * \param runtime the runtime associated with this mblock
00070    * \param instance_name specify the name of this instance
00071    *        (for debugging, NUMA mapping, etc)
00072    * \param user_arg argument passed by user to constructor
00073    *        (ignored by the mb_mblock base class)
00074    */
00075   mb_mblock(mb_runtime *runtime, const std::string &instance_name, pmt_t user_arg);
00076 
00077 public:
00078   /*!
00079    * \brief Called by the runtime system to execute the initial
00080    * transition of the finite state machine.
00081    *
00082    * This method is called by the runtime after all blocks are
00083    * constructed and before the first message is delivered.  Override
00084    * this to initialize your finite state machine.
00085    */
00086   virtual void initial_transition();
00087 
00088 protected:
00089   /*!
00090    * \brief Called by the runtime system when there's a message to handle.
00091    *
00092    * Override this to define your behavior.
00093    *
00094    * Do not issue any potentially blocking calls in this method.  This
00095    * includes things such reads or writes on sockets, pipes or slow
00096    * i/o devices.
00097    */
00098   virtual void handle_message(mb_message_sptr msg);
00099 
00100   /*!
00101    * \brief Define a port.
00102    *
00103    * EXTERNAL and RELAY ports are part of our peer interface.
00104    * INTERNAL ports are used to talk to sub-components.
00105    *
00106    * \param port_name    The name of the port (must be unique within this mblock).
00107    * \param protocol_class_name The name of the protocol class associated with
00108    *                            this port.  It must already be defined.
00109    * \param conjugated   Are the incoming and outgoing message sets swapped?
00110    * \param port_type    INTERNAL, EXTERNAL or RELAY.
00111    */
00112   mb_port_sptr
00113   define_port(const std::string &port_name,
00114               const std::string &protocol_class_name,
00115               bool conjugated,
00116               mb_port::port_type_t port_type);
00117 
00118   /*!
00119    * \brief Define a subcomponent by name.
00120    *
00121    * Called within the constructor to tell the system the
00122    * names and identities of our sub-component mblocks.
00123    *
00124    * \param component_name  The name of the sub-component (must be unique with this mblock).
00125    * \param class_name      The class of the instance that is to be created.
00126    * \param user_arg The argument to pass to the constructor of the component.
00127    */
00128   void
00129   define_component(const std::string &component_name,
00130                    const std::string &class_name,
00131                    pmt_t user_arg = PMT_NIL);
00132 
00133   /*!
00134    * \brief connect endpoint_1 to endpoint_2
00135    *
00136    * \param comp_name1  component on one end of the connection
00137    * \param port_name1  the name of the port on comp1
00138    * \param comp_name2  component on the other end of the connection
00139    * \param port_name2  the name of the port on comp2
00140    *
00141    * An endpoint is specified by the component's local name (given as
00142    * component_name in the call to register_component) and the name of
00143    * the port on that component.
00144    *
00145    * To connect an internal or relay port, use "self" as the component name.
00146    */
00147   void
00148   connect(const std::string &comp_name1, const std::string &port_name1,
00149           const std::string &comp_name2, const std::string &port_name2);
00150 
00151   /*!
00152    * \brief disconnect endpoint_1 from endpoint_2
00153    *
00154    * \param comp_name1  component on one end of the connection
00155    * \param port_name1  the name of the port on comp1
00156    * \param comp_name2  component on the other end of the connection
00157    * \param port_name2  the name of the port on comp2
00158    *
00159    * An endpoint is specified by the component's local name (given as
00160    * component_name in the call to register_component) and the name of
00161    * the port on that component.
00162    *
00163    * To disconnect an internal or relay port, use "self" as the component name.
00164    */
00165   void
00166   disconnect(const std::string &comp_name1, const std::string &port_name1,
00167              const std::string &comp_name2, const std::string &port_name2);
00168 
00169   /*!
00170    * \brief disconnect all connections to specified component
00171    * \param component_name component to disconnect
00172    */
00173   void
00174   disconnect_component(const std::string &component_name);
00175 
00176   /*!
00177    * \brief disconnect all connections to all components
00178    */
00179   void
00180   disconnect_all();
00181 
00182   /*!
00183    * \brief Return number of connections (QA mostly)
00184    */
00185   int
00186   nconnections() const;
00187 
00188   //! Set the class name
00189   void set_class_name(const std::string &name);
00190 
00191   /*!
00192    * \brief Tell runtime that we are done.
00193    *
00194    * This method does not return.
00195    */
00196   void exit();
00197 
00198   /*!
00199    * \brief Ask runtime to execute the shutdown procedure for all blocks.
00200    * 
00201    * \param result sets value of \p result output argument of runtime->run(...)
00202    *
00203    * The runtime first sends a maximum priority %shutdown message to
00204    * all blocks.  All blocks should handle the %shutdown message,
00205    * perform whatever clean up is required, and call this->exit();
00206    *
00207    * After a period of time (~100ms), any blocks which haven't yet
00208    * called this->exit() are sent a maximum priority %halt message.
00209    * %halt is detected in main_loop, and this->exit() is called.
00210    *
00211    * After an additional period of time (~100ms), any blocks which
00212    * still haven't yet called this->exit() are sent a SIG<FOO> (TBD)
00213    * signal, which will blow them out of any blocking system calls and
00214    * raise an mbe_terminate exception.  The default top-level
00215    * runtime-provided exception handler will call this->exit() to
00216    * finish the process.
00217    *
00218    * runtime->run(...) returns when all blocks have called exit.
00219    */
00220   void shutdown_all(pmt_t result);
00221 
00222   /*!
00223    * \brief main event dispatching loop
00224    *
00225    * Although it is possible to override this, the default implementation
00226    * should work for virtually all cases.
00227    */
00228   virtual void main_loop();
00229   
00230 public:
00231   virtual ~mb_mblock();
00232 
00233   //! Return instance name of this block
00234   std::string instance_name() const;
00235 
00236   //! Return the class name of this block
00237   std::string class_name() const;
00238 
00239   //! Set the instance name of this block.
00240   void set_instance_name(const std::string &name);
00241   
00242   //! Return the parent of this mblock, or 0 if we're the top-level block.
00243   mb_mblock *parent() const;
00244 
00245   /*!
00246    * \brief Schedule a "one shot" timeout.
00247    *
00248    * \param abs_time the absolute time at which the timeout should fire
00249    * \param user_data the data passed in the %timeout message.
00250    *
00251    * When the timeout fires, a message will be sent to the mblock.
00252    *
00253    * The message will have port_id = %sys-port, signal = %timeout,
00254    * data = user_data, metadata = the handle returned from
00255    * schedule_one_shot_timeout, pri = MB_PRI_BEST.
00256    *
00257    * \returns a handle that can be used in cancel_timeout, and is passed
00258    * as the metadata field of the generated %timeout message.
00259    *
00260    * To cancel a pending timeout, call cancel_timeout.
00261    */
00262   pmt_t
00263   schedule_one_shot_timeout(const mb_time &abs_time, pmt_t user_data);
00264 
00265   /*!
00266    * \brief Schedule a periodic timeout.
00267    *
00268    * \param first_abs_time The absolute time at which the first timeout should fire.
00269    * \param delta_time The relative delay between the first and successive timeouts.
00270    * \param user_data the data passed in the %timeout message.
00271    *
00272    * When the timeout fires, a message will be sent to the mblock, and a
00273    * new timeout will be scheduled for previous absolute time + delta_time.
00274    *
00275    * The message will have port_id = %sys-port, signal = %timeout,
00276    * data = user_data, metadata = the handle returned from
00277    * schedule_one_shot_timeout, pri = MB_PRI_BEST.
00278    *
00279    * \returns a handle that can be used in cancel_timeout, and is passed
00280    * as the metadata field of the generated %timeout message.
00281    *
00282    * To cancel a pending timeout, call cancel_timeout.
00283    */
00284   pmt_t
00285   schedule_periodic_timeout(const mb_time &first_abs_time,
00286                             const mb_time &delta_time,
00287                             pmt_t user_data);
00288 
00289   /*!
00290    * \brief Attempt to cancel a pending timeout.
00291    *
00292    * Note that this only stops a future timeout from firing.  It is
00293    * possible that a timeout may have already fired and enqueued a
00294    * %timeout message, but that that message has not yet been seen by
00295    * handle_message.
00296    *
00297    * \param handle returned from schedule_one_shot_timeout or schedule_periodic_timeout.
00298    */
00299   void cancel_timeout(pmt_t handle);
00300 
00301   /*!
00302    * \brief Perform a pre-order depth-first traversal of the hierarchy.
00303    *
00304    * The traversal stops and returns false if any call to visitor returns false.
00305    */
00306   bool
00307   walk_tree(mb_visitor *visitor);
00308 
00309 
00310   //! \internal
00311   // internal use only
00312   mb_mblock_impl_sptr
00313   impl() const { return d_impl; }
00314 
00315 };
00316 
00317 
00318 #endif /* INCLUDED_MB_MBLOCK_H */