00001 /* -*- c++ -*- */ 00002 /* 00003 * Copyright 2006,2007,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_IMPL_H 00022 #define INCLUDED_MB_MBLOCK_IMPL_H 00023 00024 #include <mblock/mblock.h> 00025 #include <mb_runtime_base.h> 00026 #include <mb_connection.h> 00027 #include <mblock/msg_queue.h> 00028 #include <list> 00029 #include <map> 00030 00031 00032 typedef std::map<std::string, mb_port_sptr> mb_port_map_t; 00033 typedef std::map<std::string, mb_mblock_sptr> mb_comp_map_t; 00034 00035 00036 /*! 00037 * \brief The private implementation details of the mblock system. 00038 */ 00039 class mb_mblock_impl : boost::noncopyable 00040 { 00041 mb_runtime_base *d_runtime; // pointer to runtime 00042 mb_mblock *d_mb; // pointer to our associated mblock 00043 mb_mblock *d_mb_parent; // pointer to our parent 00044 00045 std::string d_instance_name; // hierarchical name 00046 std::string d_class_name; // name of this (derived) class 00047 00048 mb_port_map_t d_port_map; // our ports 00049 mb_comp_map_t d_comp_map; // our components 00050 mb_conn_table d_conn_table; // our connections 00051 00052 mb_msg_queue d_msgq; // incoming messages for us 00053 00054 public: 00055 mb_mblock_impl(mb_runtime_base *runtime, mb_mblock *mb, 00056 const std::string &instance_name); 00057 ~mb_mblock_impl(); 00058 00059 /*! 00060 * \brief Define a port. 00061 * 00062 * EXTERNAL and RELAY ports are part of our peer interface. 00063 * INTERNAL ports are used to talk to sub-components. 00064 * 00065 * \param port_name The name of the port (must be unique within this mblock). 00066 * \param protocol_class_name The name of the protocol class associated with 00067 * this port. It must already be defined. 00068 * \param conjugated Are the incoming and outgoing message sets swapped? 00069 * \param port_type INTERNAL, EXTERNAL or RELAY. 00070 */ 00071 mb_port_sptr 00072 define_port(const std::string &port_name, 00073 const std::string &protocol_class_name, 00074 bool conjugated, 00075 mb_port::port_type_t port_type); 00076 00077 /*! 00078 * \brief Define a subcomponent by name. 00079 * 00080 * Called within the constructor to tell the system the 00081 * names and identities of our sub-component mblocks. 00082 * 00083 * \param component_name The name of the sub-component (must be unique with this mblock). 00084 * \param class_name The class of the instance that is to be created. 00085 * \param user_arg The argument to pass to the constructor of the component. 00086 */ 00087 void 00088 define_component(const std::string &component_name, 00089 const std::string &class_name, 00090 pmt_t user_arg); 00091 00092 /*! 00093 * \brief connect endpoint_1 to endpoint_2 00094 * 00095 * \param comp_name1 component on one end of the connection 00096 * \param port_name1 the name of the port on comp1 00097 * \param comp_name2 component on the other end of the connection 00098 * \param port_name2 the name of the port on comp2 00099 * 00100 * An endpoint is specified by the component's local name (given as 00101 * component_name in the call to register_component) and the name of 00102 * the port on that component. 00103 * 00104 * To connect an internal or relay port, use "self" as the component name. 00105 */ 00106 void 00107 connect(const std::string &comp_name1, const std::string &port_name1, 00108 const std::string &comp_name2, const std::string &port_name2); 00109 00110 /*! 00111 * \brief disconnect endpoint_1 from endpoint_2 00112 * 00113 * \param comp_name1 component on one end of the connection 00114 * \param port_name1 the name of the port on comp1 00115 * \param comp_name2 component on the other end of the connection 00116 * \param port_name2 the name of the port on comp2 00117 * 00118 * An endpoint is specified by the component's local name (given as 00119 * component_name in the call to register_component) and the name of 00120 * the port on that component. 00121 * 00122 * To disconnect an internal or relay port, use "self" as the component name. 00123 */ 00124 void 00125 disconnect(const std::string &comp_name1, const std::string &port_name1, 00126 const std::string &comp_name2, const std::string &port_name2); 00127 00128 /*! 00129 * \brief disconnect all connections to specified component 00130 * \param component_name component to disconnect 00131 */ 00132 void 00133 disconnect_component(const std::string component_name); 00134 00135 /*! 00136 * \brief disconnect all connections to all components 00137 */ 00138 void 00139 disconnect_all(); 00140 00141 /*! 00142 * \brief Return number of connections (QA mostly) 00143 */ 00144 int 00145 nconnections(); 00146 00147 bool 00148 walk_tree(mb_visitor *visitor); 00149 00150 mb_msg_accepter_sptr 00151 make_accepter(pmt_t port_name); 00152 00153 mb_msg_queue & 00154 msgq() { return d_msgq; } 00155 00156 //! Return instance name of this block 00157 std::string instance_name() const { return d_instance_name; } 00158 00159 //! Set the instance name of this block 00160 void set_instance_name(const std::string &name); 00161 00162 //! Return the class name of this block 00163 std::string class_name() const { return d_class_name; } 00164 00165 //! Set the class name 00166 void set_class_name(const std::string &name); 00167 00168 /*! 00169 * \brief If bound, store endpoint from the other end of the connection. 00170 * 00171 * \param port [in] port the port that we're searching for. 00172 * \param ep [out] the other end point from the matching connection. 00173 * 00174 * \returns true iff there's a matching connection. 00175 */ 00176 bool 00177 lookup_other_endpoint(const mb_port *port, mb_endpoint *ep); 00178 00179 00180 //! Return point to associated mblock 00181 mb_mblock *mblock() const { return d_mb; } 00182 00183 //! Return pointer to the parent of our mblock 00184 mb_mblock *mblock_parent() const { return d_mb_parent; } 00185 00186 //! Lookup a component by name 00187 mb_mblock_sptr component(const std::string &comp_name); 00188 00189 //! Return the runtime instance 00190 mb_runtime_base *runtime() { return d_runtime; } 00191 00192 //! Set the runtime instance 00193 void set_runtime(mb_runtime_base *runtime) { d_runtime = runtime; } 00194 00195 /* 00196 * Our implementation methods 00197 */ 00198 private: 00199 //bool port_is_defined(pmt_t name); 00200 bool port_is_defined(const std::string &name); 00201 //bool comp_is_defined(pmt_t name); 00202 bool comp_is_defined(const std::string &name); 00203 00204 mb_endpoint 00205 check_and_resolve_endpoint(const std::string &comp_name, 00206 const std::string &port_name); 00207 00208 00209 mb_port_sptr 00210 resolve_port(const std::string &comp_name, 00211 const std::string &port_name); 00212 00213 static bool 00214 endpoints_are_compatible(const mb_endpoint &ep0, 00215 const mb_endpoint &ep1); 00216 00217 /*! 00218 * \brief walk mblock tree and invalidate all port resolution caches. 00219 * \internal 00220 */ 00221 void 00222 invalidate_all_port_caches(); 00223 }; 00224 00225 00226 #endif /* INCLUDED_MB_MBLOCK_IMPL_H */