3 * Copyright 2006,2008,2009 Free Software Foundation, Inc.
5 * This file is part of GNU Radio
7 * GNU Radio is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
12 * GNU Radio is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #ifndef INCLUDED_MB_MBLOCK_H
22 #define INCLUDED_MB_MBLOCK_H
24 #include <mblock/common.h>
25 #include <mblock/message.h>
26 #include <mblock/port.h>
27 #include <mblock/time.h>
31 * Abstract class implementing visitor pattern
37 virtual ~mb_visitor();
38 virtual bool operator()(mb_mblock *mblock) = 0;
41 // ----------------------------------------------------------------------
44 * \brief Parent class for all message passing blocks
46 * Subclass this to define your mblocks.
48 class mb_mblock : boost::noncopyable,
49 public boost::enable_shared_from_this<mb_mblock>
52 mb_mblock_impl_sptr d_impl; // implementation details
54 friend class mb_runtime;
55 friend class mb_mblock_impl;
56 friend class mb_worker;
60 * \brief mblock constructor.
62 * Initializing all mblocks in the system is a 3 step procedure.
64 * The top level mblock's constructor is run. That constructor
65 * (a) registers all of its ports using define_port, (b) registers any
66 * subcomponents it may have via the define_component method, and
67 * then (c) issues connect calls to wire its subcomponents together.
69 * \param runtime the runtime associated with this mblock
70 * \param instance_name specify the name of this instance
71 * (for debugging, NUMA mapping, etc)
72 * \param user_arg argument passed by user to constructor
73 * (ignored by the mb_mblock base class)
75 mb_mblock(mb_runtime *runtime, const std::string &instance_name, gruel::pmt_t user_arg);
79 * \brief Called by the runtime system to execute the initial
80 * transition of the finite state machine.
82 * This method is called by the runtime after all blocks are
83 * constructed and before the first message is delivered. Override
84 * this to initialize your finite state machine.
86 virtual void initial_transition();
90 * \brief Called by the runtime system when there's a message to handle.
92 * Override this to define your behavior.
94 * Do not issue any potentially blocking calls in this method. This
95 * includes things such reads or writes on sockets, pipes or slow
98 virtual void handle_message(mb_message_sptr msg);
101 * \brief Define a port.
103 * EXTERNAL and RELAY ports are part of our peer interface.
104 * INTERNAL ports are used to talk to sub-components.
106 * \param port_name The name of the port (must be unique within this mblock).
107 * \param protocol_class_name The name of the protocol class associated with
108 * this port. It must already be defined.
109 * \param conjugated Are the incoming and outgoing message sets swapped?
110 * \param port_type INTERNAL, EXTERNAL or RELAY.
113 define_port(const std::string &port_name,
114 const std::string &protocol_class_name,
116 mb_port::port_type_t port_type);
119 * \brief Define a subcomponent by name.
121 * Called within the constructor to tell the system the
122 * names and identities of our sub-component mblocks.
124 * \param component_name The name of the sub-component (must be unique with this mblock).
125 * \param class_name The class of the instance that is to be created.
126 * \param user_arg The argument to pass to the constructor of the component.
129 define_component(const std::string &component_name,
130 const std::string &class_name,
131 gruel::pmt_t user_arg = gruel::PMT_NIL);
134 * \brief connect endpoint_1 to endpoint_2
136 * \param comp_name1 component on one end of the connection
137 * \param port_name1 the name of the port on comp1
138 * \param comp_name2 component on the other end of the connection
139 * \param port_name2 the name of the port on comp2
141 * An endpoint is specified by the component's local name (given as
142 * component_name in the call to register_component) and the name of
143 * the port on that component.
145 * To connect an internal or relay port, use "self" as the component name.
148 connect(const std::string &comp_name1, const std::string &port_name1,
149 const std::string &comp_name2, const std::string &port_name2);
152 * \brief disconnect endpoint_1 from endpoint_2
154 * \param comp_name1 component on one end of the connection
155 * \param port_name1 the name of the port on comp1
156 * \param comp_name2 component on the other end of the connection
157 * \param port_name2 the name of the port on comp2
159 * An endpoint is specified by the component's local name (given as
160 * component_name in the call to register_component) and the name of
161 * the port on that component.
163 * To disconnect an internal or relay port, use "self" as the component name.
166 disconnect(const std::string &comp_name1, const std::string &port_name1,
167 const std::string &comp_name2, const std::string &port_name2);
170 * \brief disconnect all connections to specified component
171 * \param component_name component to disconnect
174 disconnect_component(const std::string &component_name);
177 * \brief disconnect all connections to all components
183 * \brief Return number of connections (QA mostly)
186 nconnections() const;
188 //! Set the class name
189 void set_class_name(const std::string &name);
192 * \brief Tell runtime that we are done.
194 * This method does not return.
199 * \brief Ask runtime to execute the shutdown procedure for all blocks.
201 * \param result sets value of \p result output argument of runtime->run(...)
203 * The runtime first sends a maximum priority %shutdown message to
204 * all blocks. All blocks should handle the %shutdown message,
205 * perform whatever clean up is required, and call this->exit();
207 * After a period of time (~100ms), any blocks which haven't yet
208 * called this->exit() are sent a maximum priority %halt message.
209 * %halt is detected in main_loop, and this->exit() is called.
211 * After an additional period of time (~100ms), any blocks which
212 * still haven't yet called this->exit() are sent a SIG<FOO> (TBD)
213 * signal, which will blow them out of any blocking system calls and
214 * raise an mbe_terminate exception. The default top-level
215 * runtime-provided exception handler will call this->exit() to
216 * finish the process.
218 * runtime->run(...) returns when all blocks have called exit.
220 void shutdown_all(gruel::pmt_t result);
223 * \brief main event dispatching loop
225 * Although it is possible to override this, the default implementation
226 * should work for virtually all cases.
228 virtual void main_loop();
231 virtual ~mb_mblock();
233 //! Return instance name of this block
234 std::string instance_name() const;
236 //! Return the class name of this block
237 std::string class_name() const;
239 //! Set the instance name of this block.
240 void set_instance_name(const std::string &name);
242 //! Return the parent of this mblock, or 0 if we're the top-level block.
243 mb_mblock *parent() const;
246 * \brief Schedule a "one shot" timeout.
248 * \param abs_time the absolute time at which the timeout should fire
249 * \param user_data the data passed in the %timeout message.
251 * When the timeout fires, a message will be sent to the mblock.
253 * The message will have port_id = %sys-port, signal = %timeout,
254 * data = user_data, metadata = the handle returned from
255 * schedule_one_shot_timeout, pri = MB_PRI_BEST.
257 * \returns a handle that can be used in cancel_timeout, and is passed
258 * as the metadata field of the generated %timeout message.
260 * To cancel a pending timeout, call cancel_timeout.
263 schedule_one_shot_timeout(const mb_time &abs_time, gruel::pmt_t user_data);
266 * \brief Schedule a periodic timeout.
268 * \param first_abs_time The absolute time at which the first timeout should fire.
269 * \param delta_time The relative delay between the first and successive timeouts.
270 * \param user_data the data passed in the %timeout message.
272 * When the timeout fires, a message will be sent to the mblock, and a
273 * new timeout will be scheduled for previous absolute time + delta_time.
275 * The message will have port_id = %sys-port, signal = %timeout,
276 * data = user_data, metadata = the handle returned from
277 * schedule_one_shot_timeout, pri = MB_PRI_BEST.
279 * \returns a handle that can be used in cancel_timeout, and is passed
280 * as the metadata field of the generated %timeout message.
282 * To cancel a pending timeout, call cancel_timeout.
285 schedule_periodic_timeout(const mb_time &first_abs_time,
286 const mb_time &delta_time,
287 gruel::pmt_t user_data);
290 * \brief Attempt to cancel a pending timeout.
292 * Note that this only stops a future timeout from firing. It is
293 * possible that a timeout may have already fired and enqueued a
294 * %timeout message, but that that message has not yet been seen by
297 * \param handle returned from schedule_one_shot_timeout or schedule_periodic_timeout.
299 void cancel_timeout(gruel::pmt_t handle);
302 * \brief Perform a pre-order depth-first traversal of the hierarchy.
304 * The traversal stops and returns false if any call to visitor returns false.
307 walk_tree(mb_visitor *visitor);
313 impl() const { return d_impl; }
318 #endif /* INCLUDED_MB_MBLOCK_H */