From: eb Date: Mon, 29 Jan 2007 00:10:51 +0000 (+0000) Subject: Merged mblock work-in-progress (eb/mb r4273:4312) into trunk. X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=a6db1d097d7be5e562c07f60a1ff711bddc5e99c;p=debian%2Fgnuradio Merged mblock work-in-progress (eb/mb r4273:4312) into trunk. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@4313 221aa14e-8319-0410-a670-987f0aec2ac5 --- diff --git a/mblock/src/lib/Makefile.am b/mblock/src/lib/Makefile.am index 41747300..c049bd34 100644 --- a/mblock/src/lib/Makefile.am +++ b/mblock/src/lib/Makefile.am @@ -1,5 +1,5 @@ # -# Copyright 2006 Free Software Foundation, Inc. +# Copyright 2006,2007 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -37,8 +37,11 @@ libmblock_la_SOURCES = \ mb_mblock.cc \ mb_mblock_impl.cc \ mb_message.cc \ + mb_msg_accepter.cc \ + mb_msg_accepter_smp.cc \ + mb_msg_queue.cc \ mb_port.cc \ - mb_port_detail.cc \ + mb_port_simple.cc \ mb_protocol_class.cc \ mb_runtime.cc \ mb_runtime_impl.cc \ @@ -58,7 +61,10 @@ include_HEADERS = \ mb_exception.h \ mb_mblock.h \ mb_message.h \ + mb_msg_accepter.h \ + mb_msg_queue.h \ mb_port.h \ + mb_port_simple.h \ mb_protocol_class.h \ mb_runtime.h \ mb_util.h @@ -68,6 +74,7 @@ noinst_HEADERS = \ mb_connection.h \ mb_endpoint.h \ mb_mblock_impl.h \ + mb_msg_accepter_smp.h \ mb_port_detail.h \ mb_runtime_impl.h \ qa_mblock.h \ diff --git a/mblock/src/lib/mb_common.h b/mblock/src/lib/mb_common.h index f54fa56a..13837a8c 100644 --- a/mblock/src/lib/mb_common.h +++ b/mblock/src/lib/mb_common.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2006,2007 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -25,11 +25,44 @@ #include #include #include +#include +/* + * The priority type and valid range + */ typedef unsigned int mb_pri_t; -static const mb_pri_t MB_PRI_DEFAULT = 5; +static const mb_pri_t MB_PRI_BEST = 0; +static const mb_pri_t MB_PRI_DEFAULT = 4; +static const mb_pri_t MB_PRI_WORST = 7; +static const mb_pri_t MB_NPRI = MB_PRI_WORST + 1; // number of valid priorities +/*! + * \brief return true iff priority a is better than priority b + */ +inline static bool +mb_pri_better(mb_pri_t a, mb_pri_t b) +{ + return a < b; +} + +/*! + * \brief return true iff priority a is worse than priority b + */ +inline static bool +mb_pri_worse(mb_pri_t a, mb_pri_t b) +{ + return a > b; +} + +/*! + * \brief ensure that pri is valid + */ +inline static mb_pri_t +mb_pri_clamp(mb_pri_t p) +{ + return p < MB_NPRI ? p : MB_NPRI - 1; +} class mb_runtime; typedef boost::shared_ptr mb_runtime_sptr; @@ -49,5 +82,13 @@ typedef boost::shared_ptr mb_port_sptr; class mb_port_detail; typedef boost::shared_ptr mb_port_detail_sptr; +class mb_msg_accepter; +typedef boost::shared_ptr mb_msg_accepter_sptr; + +class mb_message; +typedef boost::shared_ptr mb_message_sptr; + +class mb_msg_queue; +typedef boost::shared_ptr mb_msg_queue_sptr; #endif /* INCLUDED_MB_COMMON_H */ diff --git a/mblock/src/lib/mb_mblock.h b/mblock/src/lib/mb_mblock.h index ce0065f2..c656f90f 100644 --- a/mblock/src/lib/mb_mblock.h +++ b/mblock/src/lib/mb_mblock.h @@ -24,6 +24,7 @@ #include #include #include +#include /*! @@ -45,7 +46,8 @@ public: * * Subclass this to define your mblocks. */ -class mb_mblock : boost::noncopyable +class mb_mblock : boost::noncopyable, + public boost::enable_shared_from_this { private: mb_mblock_impl_sptr d_impl; // implementation details @@ -120,9 +122,9 @@ protected: /*! * \brief connect endpoint_1 to endpoint_2 * - * \param comp_name1 component on one of the connection + * \param comp_name1 component on one end of the connection * \param port_name1 the name of the port on comp1 - * \param comp_name2 component on the other end the connection + * \param comp_name2 component on the other end of the connection * \param port_name2 the name of the port on comp2 * * An endpoint is specified by the component's local name (given as @@ -138,9 +140,9 @@ protected: /*! * \brief disconnect endpoint_1 from endpoint_2 * - * \param comp_name1 component on one of the connection + * \param comp_name1 component on one end of the connection * \param port_name1 the name of the port on comp1 - * \param comp_name2 component on the other end the connection + * \param comp_name2 component on the other end of the connection * \param port_name2 the name of the port on comp2 * * An endpoint is specified by the component's local name (given as @@ -181,7 +183,15 @@ public: * * The traversal stops and returns false if any call to visitor returns false. */ - bool walk_tree(mb_visitor *visitor, const std::string &path=""); + bool + walk_tree(mb_visitor *visitor, const std::string &path=""); + + + //! \implementation + // internal use only + mb_mblock_impl_sptr + impl() const { return d_impl; } + }; diff --git a/mblock/src/lib/mb_mblock_impl.cc b/mblock/src/lib/mb_mblock_impl.cc index 8a9efe2b..f4fa523e 100644 --- a/mblock/src/lib/mb_mblock_impl.cc +++ b/mblock/src/lib/mb_mblock_impl.cc @@ -26,8 +26,10 @@ #include #include #include +#include #include #include +#include static pmt_t s_self = pmt_intern("self"); @@ -49,7 +51,7 @@ mb_mblock_impl::comp_is_defined(const std::string &name) //////////////////////////////////////////////////////////////////////// mb_mblock_impl::mb_mblock_impl(mb_mblock *mb) - : d_mb(mb) + : d_mb(mb), d_mb_parent(0) { } @@ -66,13 +68,17 @@ mb_mblock_impl::define_port(const std::string &port_name, mb_port::port_type_t port_type) { if (port_type == mb_port::RELAY) - throw mbe_base(d_mb, "mb_block_impl::define_port: RELAY ports are not implemented: " + port_name); + throw mbe_base(d_mb, + "mb_block_impl::define_port: RELAY ports are not implemented: " + + port_name); if (port_is_defined(port_name)) throw mbe_duplicate_port(d_mb, port_name); - mb_port_sptr p = mb_port_sptr(new mb_port(port_name, protocol_class_name, - conjugated, port_type)); + mb_port_sptr p = + mb_port_sptr(new mb_port_simple(d_mb, + port_name, protocol_class_name, + conjugated, port_type)); d_port_map[port_name] = p; return p; } @@ -84,12 +90,15 @@ mb_mblock_impl::define_component(const std::string &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; } void -mb_mblock_impl::connect(const std::string &comp_name1, const std::string &port_name1, - const std::string &comp_name2, const std::string &port_name2) +mb_mblock_impl::connect(const std::string &comp_name1, + const std::string &port_name1, + const std::string &comp_name2, + const std::string &port_name2) { mb_endpoint ep0 = check_and_resolve_endpoint(comp_name1, port_name1); mb_endpoint ep1 = check_and_resolve_endpoint(comp_name2, port_name2); @@ -104,8 +113,10 @@ mb_mblock_impl::connect(const std::string &comp_name1, const std::string &port_n } void -mb_mblock_impl::disconnect(const std::string &comp_name1, const std::string &port_name1, - const std::string &comp_name2, const std::string &port_name2) +mb_mblock_impl::disconnect(const std::string &comp_name1, + const std::string &port_name1, + const std::string &comp_name2, + const std::string &port_name2) { d_conn_table.disconnect(comp_name1, port_name1, comp_name2, port_name2); } @@ -173,7 +184,7 @@ mb_mblock_impl::resolve_port(const std::string &comp_name, mb_port_sptr c_port = c_impl->d_port_map[port_name]; - if (c_port->port_type() == mb_port::INTERNAL) // can't "see" a child's internal ports + if (c_port->port_type() == mb_port::INTERNAL) // can't "see" a child's internal ports throw mbe_no_such_port(d_mb, mb_util::join_names(comp_name, port_name)); return c_port; @@ -212,3 +223,12 @@ mb_mblock_impl::walk_tree(mb_visitor *visitor, const std::string &path) return true; } +mb_msg_accepter_sptr +mb_mblock_impl::make_accepter(const std::string port_name) +{ + mb_msg_accepter *ma = + new mb_msg_accepter_smp(d_mb->shared_from_this(), + pmt_intern(port_name)); + + return mb_msg_accepter_sptr(ma); +} diff --git a/mblock/src/lib/mb_mblock_impl.h b/mblock/src/lib/mb_mblock_impl.h index c5610edd..1e62dd8d 100644 --- a/mblock/src/lib/mb_mblock_impl.h +++ b/mblock/src/lib/mb_mblock_impl.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2006,2007 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -37,11 +38,14 @@ typedef std::map mb_comp_map_t; class mb_mblock_impl : boost::noncopyable { mb_mblock *d_mb; // pointer to our associated mblock + mb_mblock *d_mb_parent; // pointer to our parent mb_port_map_t d_port_map; // our ports mb_comp_map_t d_comp_map; // our components mb_conn_table d_conn_table; // our connections + mb_msg_queue d_msgq; // incoming messages for us + public: mb_mblock_impl(mb_mblock *mb); ~mb_mblock_impl(); @@ -80,9 +84,9 @@ public: /*! * \brief connect endpoint_1 to endpoint_2 * - * \param comp_name1 component on one of the connection + * \param comp_name1 component on one end of the connection * \param port_name1 the name of the port on comp1 - * \param comp_name2 component on the other end the connection + * \param comp_name2 component on the other end of the connection * \param port_name2 the name of the port on comp2 * * An endpoint is specified by the component's local name (given as @@ -98,9 +102,9 @@ public: /*! * \brief disconnect endpoint_1 from endpoint_2 * - * \param comp_name1 component on one of the connection + * \param comp_name1 component on one end of the connection * \param port_name1 the name of the port on comp1 - * \param comp_name2 component on the other end the connection + * \param comp_name2 component on the other end of the connection * \param port_name2 the name of the port on comp2 * * An endpoint is specified by the component's local name (given as @@ -135,6 +139,12 @@ public: bool walk_tree(mb_visitor *visitor, const std::string &path=""); + mb_msg_accepter_sptr + make_accepter(const std::string port_name); + + mb_msg_queue & + msgq() { return d_msgq; } + /* * Our implementation methods */ diff --git a/mblock/src/lib/mb_message.cc b/mblock/src/lib/mb_message.cc index f494201a..23803726 100644 --- a/mblock/src/lib/mb_message.cc +++ b/mblock/src/lib/mb_message.cc @@ -31,7 +31,8 @@ mb_make_message(pmt_t signal, pmt_t data, pmt_t metadata, mb_pri_t priority) } mb_message::mb_message(pmt_t signal, pmt_t data, pmt_t metadata, mb_pri_t priority) - : d_signal(signal), d_data(data), d_metadata(metadata), d_priority(priority) + : d_signal(signal), d_data(data), d_metadata(metadata), d_priority(priority), + d_port_id(PMT_NIL) { } diff --git a/mblock/src/lib/mb_message.h b/mblock/src/lib/mb_message.h index ee88d79f..95440f8b 100644 --- a/mblock/src/lib/mb_message.h +++ b/mblock/src/lib/mb_message.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2006,2007 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -34,18 +34,21 @@ typedef boost::shared_ptr mb_message_sptr; * \param metadata information about the data * \param priority urgency */ -mb_message_sptr +mb_message_sptr mb_make_message(pmt_t signal, pmt_t data = PMT_NIL, pmt_t metadata = PMT_NIL, mb_pri_t priority = MB_PRI_DEFAULT); class mb_message { - pmt_t d_signal; - pmt_t d_data; - pmt_t d_metadata; - mb_pri_t d_priority; - // foo d_rcvd_port_id; + mb_message_sptr d_next; // link field for msg queue + pmt_t d_signal; + pmt_t d_data; + pmt_t d_metadata; + mb_pri_t d_priority; + pmt_t d_port_id; // name of port msg was rcvd on (symbol) + + friend class mb_msg_queue; friend mb_message_sptr mb_make_message(pmt_t signal, pmt_t data, pmt_t metadata, mb_pri_t priority); @@ -60,7 +63,9 @@ public: pmt_t data() const { return d_data; } pmt_t metadata() const { return d_metadata; } mb_pri_t priority() const { return d_priority; } - // foo rcvd_port_id const { return d_rcvd_port_id; } + pmt_t port_id() const { return d_port_id; } + + void set_port_id(pmt_t port_id){ d_port_id = port_id; } }; #endif /* INCLUDED_MB_MESSAGE_H */ diff --git a/mblock/src/lib/mb_msg_accepter.cc b/mblock/src/lib/mb_msg_accepter.cc new file mode 100644 index 00000000..1eded241 --- /dev/null +++ b/mblock/src/lib/mb_msg_accepter.cc @@ -0,0 +1,31 @@ +/* -*- 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 +#endif + +#include + +mb_msg_accepter::~mb_msg_accepter() +{ + // nop +} diff --git a/mblock/src/lib/mb_msg_accepter.h b/mblock/src/lib/mb_msg_accepter.h new file mode 100644 index 00000000..4f39fda6 --- /dev/null +++ b/mblock/src/lib/mb_msg_accepter.h @@ -0,0 +1,48 @@ +/* -*- 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_MSG_ACCEPTER_H +#define INCLUDED_MB_MSG_ACCEPTER_H + +#include + +/*! + * \brief Abstract class that accepts messages + * + * The mb_port::send method ultimately resolves the (local) + * destination of a send to an object of this type. The resulting + * object is called to deliver the message. + * + * Expect derived classes such as these: + * + * smp : target is visible in this address space + * mpi : target is on the other end of an MPI link + * ppe->spe : sending from Cell PPE to Cell SPE + * spe->ppe : sending from Cell SPE to Cell PPE + */ +class mb_msg_accepter { +public: + mb_msg_accepter(){}; + virtual ~mb_msg_accepter(); + + virtual void operator()(pmt_t signal, pmt_t data, pmt_t metadata, mb_pri_t priority) = 0; +}; + +#endif /* INCLUDED_MB_MSG_ACCEPTER_H */ diff --git a/mblock/src/lib/mb_msg_accepter_smp.cc b/mblock/src/lib/mb_msg_accepter_smp.cc new file mode 100644 index 00000000..9e543979 --- /dev/null +++ b/mblock/src/lib/mb_msg_accepter_smp.cc @@ -0,0 +1,50 @@ +/* -*- 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 +#endif +#include +#include +#include +#include +#include + +mb_msg_accepter_smp::mb_msg_accepter_smp(mb_mblock_sptr mblock, pmt_t port_name) + : d_mb(mblock), d_port_name(port_name) +{ +} + +mb_msg_accepter_smp::~mb_msg_accepter_smp() +{ + // nop +} + +void +mb_msg_accepter_smp::operator()(pmt_t signal, pmt_t data, + pmt_t metadata, mb_pri_t priority) +{ + mb_message_sptr msg = mb_make_message(signal, data, metadata, priority); + msg->set_port_id(d_port_name); + d_mb->impl()->msgq().insert(msg); + + // FIXME tell runtime that we're ready to run +} diff --git a/mblock/src/lib/mb_msg_accepter_smp.h b/mblock/src/lib/mb_msg_accepter_smp.h new file mode 100644 index 00000000..bc17f468 --- /dev/null +++ b/mblock/src/lib/mb_msg_accepter_smp.h @@ -0,0 +1,42 @@ +/* -*- 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_MSG_ACCEPTER_SMP_H +#define INCLUDED_MB_MSG_ACCEPTER_SMP_H + +#include + +/*! + * \brief Concrete message acceptor that does an mb_msg_queue insertion + */ +class mb_msg_accepter_smp : public mb_msg_accepter +{ + mb_mblock_sptr d_mb; + pmt_t d_port_name; + +public: + mb_msg_accepter_smp(mb_mblock_sptr mblock, pmt_t port_name); + ~mb_msg_accepter_smp(); + + void operator()(pmt_t signal, pmt_t data, pmt_t metadata, mb_pri_t priority); +}; + + +#endif /* INCLUDED_MB_MSG_ACCEPTER_SMP_H */ diff --git a/mblock/src/lib/mb_msg_queue.cc b/mblock/src/lib/mb_msg_queue.cc new file mode 100644 index 00000000..e6269492 --- /dev/null +++ b/mblock/src/lib/mb_msg_queue.cc @@ -0,0 +1,80 @@ +/* -*- 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 +#endif +#include +#include + +// FIXME turn this into a template so we can use it for the runq of mblocks too + +mb_msg_queue::mb_msg_queue() +{ +} + +mb_msg_queue::~mb_msg_queue() +{ +} + +void +mb_msg_queue::insert(mb_message_sptr msg) +{ + // omni_mutex_lock l(d_mutex); FIXME + + mb_pri_t q = mb_pri_clamp(msg->priority()); + + if (d_queue[q].empty_p()){ + d_queue[q].tail = d_queue[q].head = msg; + msg->d_next.reset(); //msg->d_next = 0; + } + else { + d_queue[q].tail->d_next = msg; + d_queue[q].tail = msg; + msg->d_next.reset(); // msg->d_next = 0; + } + // FIXME set bit in bitmap +} + +mb_message_sptr +mb_msg_queue::get_highest_pri_msg() +{ + // omni_mutex_lock l(d_mutex); FIXME + + // FIXME use bitmap and ffz to find best queue in O(1) + + for (mb_pri_t q = 0; q <= MB_PRI_WORST; q++){ + + if (!d_queue[q].empty_p()){ + mb_message_sptr msg = d_queue[q].head; + d_queue[q].head = msg->d_next; + if (d_queue[q].head == 0){ + d_queue[q].tail.reset(); // d_queue[q].tail = 0; + // FIXME clear bit in bitmap + } + + msg->d_next.reset(); // msg->d_next = 0; + return msg; + } + } + + return mb_message_sptr(); // equivalent of a zero pointer +} diff --git a/mblock/src/lib/mb_msg_queue.h b/mblock/src/lib/mb_msg_queue.h new file mode 100644 index 00000000..2749e6a5 --- /dev/null +++ b/mblock/src/lib/mb_msg_queue.h @@ -0,0 +1,59 @@ +/* -*- 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_MSG_QUEUE_H +#define INCLUDED_MB_MSG_QUEUE_H + +#include +//#include FIXME + +/*! + * \brief priority queue for mblock messages + */ +class mb_msg_queue : boost::noncopyable +{ + // When empty both head and tail are zero. + struct subq { + mb_message_sptr head; + mb_message_sptr tail; + + bool empty_p() const { return head == 0; } + }; + + // omni_mutex d_mutex; FIXME + + // FIXME add bitmap to indicate which queues are non-empty. + subq d_queue[MB_NPRI]; + +public: + mb_msg_queue(); + ~mb_msg_queue(); + + //! Insert \p msg into priority queue. + void insert(mb_message_sptr msg); + + /* + * \brief Delete highest pri message from the queue and return it. + * Returns equivalent of zero pointer if queue is empty. + */ + mb_message_sptr get_highest_pri_msg(); +}; + +#endif /* INCLUDED_MB_MSG_QUEUE_H */ diff --git a/mblock/src/lib/mb_port.cc b/mblock/src/lib/mb_port.cc index d7851126..5c9f544c 100644 --- a/mblock/src/lib/mb_port.cc +++ b/mblock/src/lib/mb_port.cc @@ -27,12 +27,13 @@ #include #include -mb_port::mb_port(const std::string &port_name, +mb_port::mb_port(mb_mblock *mblock, + const std::string &port_name, const std::string &protocol_class_name, bool conjugated, mb_port::port_type_t port_type) - : d_detail(mb_port_detail_sptr(new mb_port_detail())), - d_port_name(port_name), d_conjugated(conjugated), d_port_type(port_type) + : d_port_name(port_name), d_conjugated(conjugated), d_port_type(port_type), + d_mblock(mblock) { pmt_t pc = mb_protocol_class_lookup(pmt_intern(protocol_class_name)); if (pmt_is_null(pc)){ diff --git a/mblock/src/lib/mb_port.h b/mblock/src/lib/mb_port.h index 35ac34e2..59a508c9 100644 --- a/mblock/src/lib/mb_port.h +++ b/mblock/src/lib/mb_port.h @@ -24,7 +24,7 @@ #include /*! - * \brief Public port characteristics + * \brief Abstract port characteristics */ class mb_port : boost::noncopyable { @@ -38,20 +38,21 @@ public: }; private: - friend class mb_mblock_impl; - mb_port_detail_sptr d_detail; std::string d_port_name; pmt_t d_protocol_class; bool d_conjugated; port_type_t d_port_type; - // private constructor - mb_port(const std::string &port_name, - const std::string &protocol_class_name, - bool conjugated, - mb_port::port_type_t port_type); +protected: + mb_mblock *d_mblock; // mblock we're defined in + // protected constructor + mb_port(mb_mblock *mblock, + const std::string &port_name, + const std::string &protocol_class_name, + bool conjugated, + mb_port::port_type_t port_type); public: std::string port_name() const { return d_port_name; } @@ -62,7 +63,7 @@ public: pmt_t incoming_message_set() const; pmt_t outgoing_message_set() const; - ~mb_port(); + virtual ~mb_port(); /*! * \brief send a message @@ -72,12 +73,11 @@ public: * \param metadata optional metadata * \param priority the urgency at which the message is sent */ - void + virtual void send(pmt_t signal, pmt_t data = PMT_NIL, pmt_t metadata = PMT_NIL, - mb_pri_t priority = MB_PRI_DEFAULT); - + mb_pri_t priority = MB_PRI_DEFAULT) = 0; }; #endif /* INCLUDED_MB_PORT_H */ diff --git a/mblock/src/lib/mb_port_simple.cc b/mblock/src/lib/mb_port_simple.cc new file mode 100644 index 00000000..4896df3a --- /dev/null +++ b/mblock/src/lib/mb_port_simple.cc @@ -0,0 +1,59 @@ +/* -*- 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 +#endif + +#include +#include + +mb_port_simple::mb_port_simple(mb_mblock *mblock, + const std::string &port_name, + const std::string &protocol_class_name, + bool conjugated, + mb_port::port_type_t port_type) + : mb_port(mblock, port_name, protocol_class_name, conjugated, port_type) +{ +} + +mb_port_simple::~mb_port_simple() +{ + // nop +} + +void +mb_port_simple::send(pmt_t signal, pmt_t data, pmt_t metadata, mb_pri_t priority) +{ + mb_msg_accepter_sptr accepter = find_accepter(); + if (accepter) + (*accepter)(signal, data, metadata, priority); +} + +mb_msg_accepter_sptr +mb_port_simple::find_accepter() +{ + mb_msg_accepter_sptr r; + + // FIXME, actually do the work ;) + + return r; +} diff --git a/mblock/src/lib/mb_port_simple.h b/mblock/src/lib/mb_port_simple.h new file mode 100644 index 00000000..3ce3e3cb --- /dev/null +++ b/mblock/src/lib/mb_port_simple.h @@ -0,0 +1,59 @@ +/* -*- 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_PORT_SIMPLE_H +#define INCLUDED_MB_PORT_SIMPLE_H + +#include + +/*! + * \brief Concrete port realization + */ +class mb_port_simple : public mb_port +{ +protected: + mb_msg_accepter_sptr + find_accepter(); + +public: + mb_port_simple(mb_mblock *mblock, + const std::string &port_name, + const std::string &protocol_class_name, + bool conjugated, + mb_port::port_type_t port_type); + + ~mb_port_simple(); + + /*! + * \brief send a message + * + * \param signal the event name + * \param data optional data + * \param metadata optional metadata + * \param priority the urgency at which the message is sent + */ + void + send(pmt_t signal, + pmt_t data = PMT_NIL, + pmt_t metadata = PMT_NIL, + mb_pri_t priority = MB_PRI_DEFAULT); +}; + +#endif /* INCLUDED_MB_PORT_SIMPLE_H */ diff --git a/mblock/src/lib/qa_mblock_prims.cc b/mblock/src/lib/qa_mblock_prims.cc index 432e819a..fc3452f9 100644 --- a/mblock/src/lib/qa_mblock_prims.cc +++ b/mblock/src/lib/qa_mblock_prims.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2006,2007 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -26,6 +26,10 @@ #include #include #include +#include +#include +#include +#include #include static pmt_t s_cs = pmt_intern("cs"); @@ -329,3 +333,87 @@ qa_mblock_prims::test_connect() mb_runtime_sptr rt = mb_make_runtime(); mb_mblock_sptr mb0 = mb_mblock_sptr(new tc_0()); } + +//////////////////////////////////////////////////////////////// + +void +qa_mblock_prims::test_msg_queue() +{ + mb_msg_queue q; + + // check initial state + CPPUNIT_ASSERT(q.get_highest_pri_msg() == 0); + + CPPUNIT_ASSERT(MB_NPRI >= 5); // sanity check for this test + + // insert three messages at the same pri and ensure that they come out in order + // signal data metadata pri + q.insert(mb_make_message(PMT_NIL, pmt_from_long(0), PMT_NIL, MB_PRI_BEST + 2)); + q.insert(mb_make_message(PMT_NIL, pmt_from_long(1), PMT_NIL, MB_PRI_BEST + 2)); + q.insert(mb_make_message(PMT_NIL, pmt_from_long(2), PMT_NIL, MB_PRI_BEST + 2)); + + CPPUNIT_ASSERT_EQUAL(0L, pmt_to_long(q.get_highest_pri_msg()->data())); + CPPUNIT_ASSERT_EQUAL(1L, pmt_to_long(q.get_highest_pri_msg()->data())); + CPPUNIT_ASSERT_EQUAL(2L, pmt_to_long(q.get_highest_pri_msg()->data())); + + CPPUNIT_ASSERT(q.get_highest_pri_msg() == 0); + + + // insert messages of different priorities in pseudo-random order + // signal data metadata pri + q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 3)); + q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 2)); + q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 4)); + q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 0)); + q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 1)); + q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 3)); + q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 2)); + q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 4)); + q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 0)); + q.insert(mb_make_message(PMT_NIL, PMT_NIL, PMT_NIL, MB_PRI_BEST + 1)); + + // confirm that they come out in order + CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 0, q.get_highest_pri_msg()->priority()); + CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 0, q.get_highest_pri_msg()->priority()); + CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 1, q.get_highest_pri_msg()->priority()); + CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 1, q.get_highest_pri_msg()->priority()); + CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 2, q.get_highest_pri_msg()->priority()); + CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 2, q.get_highest_pri_msg()->priority()); + CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 3, q.get_highest_pri_msg()->priority()); + CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 3, q.get_highest_pri_msg()->priority()); + CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 4, q.get_highest_pri_msg()->priority()); + CPPUNIT_ASSERT_EQUAL(MB_PRI_BEST + 4, q.get_highest_pri_msg()->priority()); + + // check final state + CPPUNIT_ASSERT(q.get_highest_pri_msg() == 0); +} + +//////////////////////////////////////////////////////////////// + +void +qa_mblock_prims::test_make_accepter() +{ + // create a block + mb_mblock_sptr mb = mb_mblock_sptr(new dp_2()); + + // use "internal use only" method... + mb_msg_accepter_sptr accepter = mb->impl()->make_accepter("cs"); + + // Now push a few messages into it... + // signal data metadata pri + (*accepter)(PMT_NIL, pmt_from_long(0), PMT_NIL, MB_PRI_BEST + 2); + (*accepter)(PMT_NIL, pmt_from_long(1), PMT_NIL, MB_PRI_BEST + 2); + (*accepter)(PMT_NIL, pmt_from_long(2), PMT_NIL, MB_PRI_BEST + 2); + + // try to pull them out + + pmt_t cs = pmt_intern("cs"); + + mb_message_sptr msg = mb->impl()->msgq().get_highest_pri_msg(); + CPPUNIT_ASSERT(pmt_eq(cs, msg->port_id())); // confirm that port_id is set + CPPUNIT_ASSERT_EQUAL(0L, pmt_to_long(msg->data())); // and that data is correct + + CPPUNIT_ASSERT_EQUAL(1L, pmt_to_long(mb->impl()->msgq().get_highest_pri_msg()->data())); + CPPUNIT_ASSERT_EQUAL(2L, pmt_to_long(mb->impl()->msgq().get_highest_pri_msg()->data())); +} + diff --git a/mblock/src/lib/qa_mblock_prims.h b/mblock/src/lib/qa_mblock_prims.h index 36b35550..4eb6c4ea 100644 --- a/mblock/src/lib/qa_mblock_prims.h +++ b/mblock/src/lib/qa_mblock_prims.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2006,2007 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -31,12 +31,16 @@ class qa_mblock_prims : public CppUnit::TestCase { CPPUNIT_TEST(test_define_ports); CPPUNIT_TEST(test_define_components); CPPUNIT_TEST(test_connect); + CPPUNIT_TEST(test_msg_queue); + CPPUNIT_TEST(test_make_accepter); CPPUNIT_TEST_SUITE_END(); private: void test_define_ports(); void test_define_components(); void test_connect(); + void test_msg_queue(); + void test_make_accepter(); }; #endif /* INCLUDED_QA_MBLOCK_PRIMS_H */