]> git.gag.com Git - debian/gnuradio/blob - mblock/src/lib/mb_mblock_impl.cc
Merged mblock work-in-progress from eb/mb -r4341:4633 into trunk.
[debian/gnuradio] / mblock / src / lib / mb_mblock_impl.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2006 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
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 2, or (at your option)
10  * any later version.
11  * 
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.
16  * 
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.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 #include <mb_mblock_impl.h>
26 #include <mb_mblock.h>
27 #include <mb_protocol_class.h>
28 #include <mb_port.h>
29 #include <mb_port_simple.h>
30 #include <mb_exception.h>
31 #include <mb_util.h>
32 #include <mb_msg_accepter_smp.h>
33
34
35 static pmt_t s_self = pmt_intern("self");
36
37 ////////////////////////////////////////////////////////////////////////
38
39 bool 
40 mb_mblock_impl::port_is_defined(const std::string &name)
41 {
42   return d_port_map.count(name) != 0;
43 }
44
45 bool
46 mb_mblock_impl::comp_is_defined(const std::string &name)
47 {
48   return name == "self" || d_comp_map.count(name) != 0;
49 }
50
51 ////////////////////////////////////////////////////////////////////////
52
53 mb_mblock_impl::mb_mblock_impl(mb_mblock *mb)
54   : d_mb(mb), d_mb_parent(0), d_fullname("<unknown>")
55 {
56 }
57
58 mb_mblock_impl::~mb_mblock_impl()
59 {
60   d_mb = 0;     // we don't own it
61 }
62
63
64 mb_port_sptr
65 mb_mblock_impl::define_port(const std::string &port_name,
66                             const std::string &protocol_class_name,
67                             bool conjugated,
68                             mb_port::port_type_t port_type)
69 {
70   if (port_is_defined(port_name))
71     throw mbe_duplicate_port(d_mb, port_name);
72
73   mb_port_sptr p =
74     mb_port_sptr(new mb_port_simple(d_mb,
75                                     port_name, protocol_class_name,
76                                     conjugated, port_type));
77   d_port_map[port_name] = p;
78   return p;
79 }
80
81 void
82 mb_mblock_impl::define_component(const std::string &name,
83                                  mb_mblock_sptr component)
84 {
85   if (comp_is_defined(name))    // check for duplicate name
86     throw mbe_duplicate_component(d_mb, name);
87
88   component->d_impl->d_mb_parent = d_mb;     // set component's parent link
89   d_comp_map[name] = component;
90 }
91
92 void
93 mb_mblock_impl::connect(const std::string &comp_name1,
94                         const std::string &port_name1,
95                         const std::string &comp_name2,
96                         const std::string &port_name2)
97 {
98   mb_endpoint   ep0 = check_and_resolve_endpoint(comp_name1, port_name1);
99   mb_endpoint   ep1 = check_and_resolve_endpoint(comp_name2, port_name2);
100
101   if (!endpoints_are_compatible(ep0, ep1))
102     throw mbe_incompatible_ports(d_mb,
103                                  comp_name1, port_name1,
104                                  comp_name2, port_name2);
105   // FIXME more checks?
106
107   d_conn_table.create_conn(ep0, ep1);
108 }
109
110 void
111 mb_mblock_impl::disconnect(const std::string &comp_name1,
112                            const std::string &port_name1,
113                            const std::string &comp_name2,
114                            const std::string &port_name2)
115 {
116   d_conn_table.disconnect(comp_name1, port_name1, comp_name2, port_name2);
117 }
118
119 void
120 mb_mblock_impl::disconnect_component(const std::string component_name)
121 {
122   d_conn_table.disconnect_component(component_name);
123 }
124
125 void
126 mb_mblock_impl::disconnect_all()
127 {
128   d_conn_table.disconnect_all();
129 }
130
131 int
132 mb_mblock_impl::nconnections() const
133 {
134   return d_conn_table.nconnections();
135 }
136
137 ////////////////////////////////////////////////////////////////////////
138
139 mb_endpoint
140 mb_mblock_impl::check_and_resolve_endpoint(const std::string &comp_name,
141                                            const std::string &port_name)
142 {
143   mb_conn_iter  it;
144   int           which_ep;
145   mb_port_sptr  port = resolve_port(comp_name, port_name);
146
147   // Confirm that we're not trying to connect to the inside of one of
148   // our EXTERNAL ports.  Connections that include "self" as the
149   // component name must be either INTERNAL or RELAY.
150
151   if (comp_name == "self" && port->port_type() == mb_port::EXTERNAL)
152     throw mbe_invalid_port_type(d_mb, comp_name, port_name);
153
154   // Is this endpoint already connected?
155   if (d_conn_table.lookup_conn_by_name(comp_name, port_name, &it, &which_ep))
156     throw mbe_already_connected(d_mb, comp_name, port_name);
157
158   return mb_endpoint(comp_name, port_name, port);
159 }
160
161 mb_port_sptr
162 mb_mblock_impl::resolve_port(const std::string &comp_name,
163                              const std::string &port_name)
164 {
165   if (comp_name == "self"){
166     // Look through our ports.
167     if (!port_is_defined(port_name))
168       throw mbe_no_such_port(d_mb, mb_util::join_names("self", port_name));
169     return d_port_map[port_name];
170   }
171   else {
172     // Look through the specified child's ports.
173     if (!comp_is_defined(comp_name))
174       throw mbe_no_such_component(d_mb, comp_name);
175     
176     mb_mblock_impl_sptr  c_impl = d_comp_map[comp_name]->d_impl;  // childs impl pointer
177     if (!c_impl->port_is_defined(port_name))
178       throw mbe_no_such_port(d_mb, mb_util::join_names(comp_name, port_name));
179
180     mb_port_sptr c_port = c_impl->d_port_map[port_name];
181
182     if (c_port->port_type() == mb_port::INTERNAL) // can't "see" a child's internal ports
183       throw mbe_no_such_port(d_mb, mb_util::join_names(comp_name, port_name));
184
185     return c_port;
186   }
187 }
188
189
190
191 bool
192 mb_mblock_impl::endpoints_are_compatible(const mb_endpoint &ep0,
193                                          const mb_endpoint &ep1)
194 {
195   pmt_t p0_outgoing = ep0.outgoing_message_set();
196   pmt_t p0_incoming = ep0.incoming_message_set();
197
198   pmt_t p1_outgoing = ep1.outgoing_message_set();
199   pmt_t p1_incoming = ep1.incoming_message_set();
200
201   return (pmt_subsetp(p0_outgoing, p1_incoming)
202           && pmt_subsetp(p1_outgoing, p0_incoming));
203 }
204
205 bool
206 mb_mblock_impl::walk_tree(mb_visitor *visitor, const std::string &path)
207 {
208   if (!(*visitor)(d_mb, path))
209     return false;
210
211   mb_comp_map_t::iterator it;
212   for (it = d_comp_map.begin(); it != d_comp_map.end(); ++it)
213     if (!(it->second->walk_tree(visitor, path + "/" + it->first)))
214       return false;
215
216   return true;
217 }
218
219 mb_msg_accepter_sptr
220 mb_mblock_impl::make_accepter(const std::string port_name)
221 {
222   mb_msg_accepter *ma =
223     new mb_msg_accepter_smp(d_mb->shared_from_this(),
224                             pmt_intern(port_name));
225
226   return mb_msg_accepter_sptr(ma);
227 }
228
229 bool
230 mb_mblock_impl::lookup_other_endpoint(const mb_port *port, mb_endpoint *ep)
231 {
232   mb_conn_iter  it;
233   int           which_ep = 0;
234
235   if (!d_conn_table.lookup_conn_by_port(port, &it, &which_ep))
236     return false;
237   
238   *ep = it->d_ep[which_ep^1];
239   return true;
240 }
241
242 mb_mblock_sptr
243 mb_mblock_impl::component(const std::string &comp_name)
244 {
245   if (comp_name == "self")
246     return d_mb->shared_from_this();
247
248   if (d_comp_map.count(comp_name) == 0)
249     return mb_mblock_sptr();    // null pointer
250
251   return d_comp_map[comp_name];
252 }
253
254 void
255 mb_mblock_impl::set_fullname(const std::string &name)
256 {
257   d_fullname = name;
258 }
259