diff options
author | Tom Rondeau <trondeau@vt.edu> | 2013-04-17 13:43:52 -0400 |
---|---|---|
committer | Tom Rondeau <trondeau@vt.edu> | 2013-04-29 14:52:56 -0400 |
commit | f3e2e07201c50033bf6c9d0c6a6f068557b4f17f (patch) | |
tree | 140b3c2d20a951ffd4abd564c3378ee2e2f9fc7c /gnuradio-runtime | |
parent | 35303ae975a5b1bdecc2492bc96e2b8e89b62a3d (diff) |
runtime: converting runtime core to gr namespace, gnuradio include dir.
Diffstat (limited to 'gnuradio-runtime')
354 files changed, 19707 insertions, 19140 deletions
diff --git a/gnuradio-runtime/apps/gnuradio-config-info.cc b/gnuradio-runtime/apps/gnuradio-config-info.cc index d3e6454fd8..19291f4dae 100644 --- a/gnuradio-runtime/apps/gnuradio-config-info.cc +++ b/gnuradio-runtime/apps/gnuradio-config-info.cc @@ -24,7 +24,7 @@ #include <config.h> #endif -#include <gr_constants.h> +#include <gnuradio/constants.h> #include <boost/program_options.hpp> #include <iostream> @@ -48,25 +48,25 @@ main(int argc, char **argv) po::store(po::parse_command_line(argc, argv, desc), vm); po::notify(vm); - if (vm.size() == 0 || vm.count("help")) { + if(vm.size() == 0 || vm.count("help")) { std::cout << desc << std::endl; return 1; } - if (vm.count("prefix")) - std::cout << gr_prefix() << std::endl; + if(vm.count("prefix")) + std::cout << gr::prefix() << std::endl; - if (vm.count("sysconfdir")) - std::cout << gr_sysconfdir() << std::endl; + if(vm.count("sysconfdir")) + std::cout << gr::sysconfdir() << std::endl; - if (vm.count("prefsdir")) - std::cout << gr_prefsdir() << std::endl; + if(vm.count("prefsdir")) + std::cout << gr::prefsdir() << std::endl; - if (vm.count("builddate")) - std::cout << gr_build_date() << std::endl; + if(vm.count("builddate")) + std::cout << gr::build_date() << std::endl; - if (vm.count("version")) - std::cout << gr_version() << std::endl; + if(vm.count("version")) + std::cout << gr::version() << std::endl; return 0; } diff --git a/gnuradio-runtime/include/CMakeLists.txt b/gnuradio-runtime/include/CMakeLists.txt index 832522f92c..929a673016 100644 --- a/gnuradio-runtime/include/CMakeLists.txt +++ b/gnuradio-runtime/include/CMakeLists.txt @@ -17,84 +17,5 @@ # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. -add_subdirectory(messages) add_subdirectory(pmt) -add_subdirectory(thread) - -######################################################################## -# Install header files -######################################################################## -install(FILES - gr_basic_block.h - gr_block_detail.h - gr_block.h - gr_block_registry.h - gr_buffer.h - gr_complex.h - gr_constants.h - gr_dispatcher.h - gr_endianness.h - gr_error_handler.h - gr_expj.h - gr_feval.h - gr_flowgraph.h - gr_fxpt.h - gr_fxpt_nco.h - gr_fxpt_vco.h - gr_hier_block2.h - gr_io_signature.h - gr_logger.h - gr_math.h - gr_message.h - gr_misc.h - gr_msg_accepter.h - gr_msg_handler.h - gr_msg_queue.h - gr_nco.h - gr_preferences.h - gr_prefs.h - gr_py_feval.h - gr_random.h - gr_realtime.h - gr_runtime_api.h - gr_runtime_types.h - gr_select_handler.h - gr_sincos.h - gr_single_threaded_scheduler.h - gr_sptr_magic.h - gr_sync_block.h - gr_sync_decimator.h - gr_sync_interpolator.h - gr_sys_paths.h - gr_tagged_stream_block.h - gr_tags.h - gr_timer.h - gr_top_block.h - gr_tpb_detail.h - gr_types.h - gr_unittests.h - ice_application_base.h - IcePy_Communicator.h - ice_server_template.h - pycallback_object.h - random.h - rpccallbackregister_base.h - rpcmanager_base.h - rpcmanager.h - rpcpmtconverters_ice.h - rpcregisterhelpers.h - rpcserver_aggregator.h - rpcserver_base.h - rpcserver_booter_aggregator.h - rpcserver_booter_base.h - rpcserver_booter_ice.h - rpcserver_ice.h - rpcserver_selector.h - runtime_block_gateway.h - attributes.h - high_res_timer.h - realtime.h - sys_pri.h - DESTINATION ${GR_INCLUDE_DIR}/gnuradio - COMPONENT "runtime_devel" -) +add_subdirectory(gnuradio) diff --git a/gnuradio-runtime/include/gnuradio/CMakeLists.txt b/gnuradio-runtime/include/gnuradio/CMakeLists.txt new file mode 100644 index 0000000000..aece490e45 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/CMakeLists.txt @@ -0,0 +1,105 @@ +# Copyright 2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +add_subdirectory(messages) +add_subdirectory(thread) + +######################################################################## +# Install header files +######################################################################## +install(FILES + api.h + attributes.h + basic_block.h + block.h + block_detail.h + block_gateway.h + block_registry.h + buffer.h + constants.h + dispatcher.h + endianness.h + error_handler.h + expj.h + feval.h + flowgraph.h + fxpt.h + fxpt_nco.h + fxpt_vco.h + gr_complex.h + hier_block2.h + high_res_timer.h + io_signature.h + math.h + message.h + misc.h + msg_accepter.h + msg_handler.h + msg_queue.h + nco.h + prefs.h + py_feval.h + pycallback_object.h + random.h + realtime.h + realtime_impl.h + runtime_types.h + single_threaded_scheduler.h + tags.h + tagged_stream_block.h + top_block.h + tpb_detail.h + select_handler.h + sincos.h + sptr_magic.h + sync_block.h + sync_decimator.h + sync_interpolator.h + sys_paths.h + timer.h + types.h + sys_pri.h + unittests.h + ice_application_base.h + IcePy_Communicator.h + ice_server_template.h + rpccallbackregister_base.h + rpcmanager_base.h + rpcmanager.h + rpcpmtconverters_ice.h + rpcregisterhelpers.h + rpcserver_aggregator.h + rpcserver_base.h + rpcserver_booter_aggregator.h + rpcserver_booter_base.h + rpcserver_booter_ice.h + rpcserver_ice.h + rpcserver_selector.h + ${CMAKE_CURRENT_SOURCE_DIR}/logger.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio + COMPONENT "runtime_devel" +) + +########################################################################## +# Configure logger +########################################################################## +CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/logger.h.in + ${CMAKE_CURRENT_BINARY_DIR}/logger.h +)
\ No newline at end of file diff --git a/gnuradio-runtime/include/IcePy_Communicator.h b/gnuradio-runtime/include/gnuradio/IcePy_Communicator.h index aae4378229..2dd0cc7bba 100644 --- a/gnuradio-runtime/include/IcePy_Communicator.h +++ b/gnuradio-runtime/include/gnuradio/IcePy_Communicator.h @@ -11,7 +11,7 @@ #define ICEPY_COMMUNICATOR_H #include <Ice/CommunicatorF.h> -#include <gr_runtime_api.h> +#include <gnuradio/api.h> namespace IcePy { diff --git a/gnuradio-runtime/include/gr_runtime_api.h b/gnuradio-runtime/include/gnuradio/api.h index 02ef9ccdcd..1c68b8c8b8 100644 --- a/gnuradio-runtime/include/gr_runtime_api.h +++ b/gnuradio-runtime/include/gnuradio/api.h @@ -19,10 +19,10 @@ * Boston, MA 02110-1301, USA. */ -#ifndef INCLUDED_GR_RUNTIME_API_H -#define INCLUDED_GR_RUNTIME_API_H +#ifndef INCLUDED_GR_RUNTIME_RUNTIME_API_H +#define INCLUDED_GR_RUNTIME_RUNTIME_API_H -#include <attributes.h> +#include <gnuradio/attributes.h> #ifdef gnuradio_runtime_EXPORTS # define GR_RUNTIME_API __GR_ATTR_EXPORT @@ -30,4 +30,4 @@ # define GR_RUNTIME_API __GR_ATTR_IMPORT #endif -#endif /* INCLUDED_GR_RUNTIME_API_H */ +#endif /* INCLUDED_GR_RUNTIME_RUNTIME_API_H */ diff --git a/gnuradio-runtime/include/attributes.h b/gnuradio-runtime/include/gnuradio/attributes.h index 5baa52e7d3..5baa52e7d3 100644 --- a/gnuradio-runtime/include/attributes.h +++ b/gnuradio-runtime/include/gnuradio/attributes.h diff --git a/gnuradio-runtime/include/gnuradio/basic_block.h b/gnuradio-runtime/include/gnuradio/basic_block.h new file mode 100644 index 0000000000..be385465d1 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/basic_block.h @@ -0,0 +1,354 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2008,2009,2011,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_BASIC_BLOCK_H +#define INCLUDED_GR_BASIC_BLOCK_H + +#include <gnuradio/api.h> +#include <gnuradio/sptr_magic.h> +#include <gnuradio/msg_accepter.h> +#include <gnuradio/runtime_types.h> +#include <gnuradio/io_signature.h> +#include <gnuradio/thread/thread.h> +#include <boost/enable_shared_from_this.hpp> +#include <boost/function.hpp> +#include <boost/foreach.hpp> +#include <boost/thread/condition_variable.hpp> +#include <iostream> +#include <string> +#include <deque> +#include <map> + +#ifdef GR_CTRLPORT +#include <gnuradio/rpcregisterhelpers.h> +#endif + +namespace gr { + + /*! + * \brief The abstract base class for all signal processing blocks. + * \ingroup internal + * + * Basic blocks are the bare abstraction of an entity that has a + * name, a set of inputs and outputs, and a message queue. These + * are never instantiated directly; rather, this is the abstract + * parent class of both gr_hier_block, which is a recursive + * container, and block, which implements actual signal + * processing functions. + */ + class GR_RUNTIME_API basic_block : public msg_accepter, + public boost::enable_shared_from_this<basic_block> + { + typedef boost::function<void(pmt::pmt_t)> msg_handler_t; + + private: + //msg_handler_t d_msg_handler; + typedef std::map<pmt::pmt_t , msg_handler_t, pmt::comperator> d_msg_handlers_t; + d_msg_handlers_t d_msg_handlers; + + typedef std::deque<pmt::pmt_t> msg_queue_t; + typedef std::map<pmt::pmt_t, msg_queue_t, pmt::comperator> msg_queue_map_t; + typedef std::map<pmt::pmt_t, msg_queue_t, pmt::comperator>::iterator msg_queue_map_itr; + std::map<pmt::pmt_t, boost::shared_ptr<boost::condition_variable>, pmt::comperator> msg_queue_ready; + + gr::thread::mutex mutex; //< protects all vars + + protected: + friend class flowgraph; + friend class flat_flowgraph; // TODO: will be redundant + friend class tpb_thread_body; + + enum vcolor { WHITE, GREY, BLACK }; + + std::string d_name; + gr::io_signature::sptr d_input_signature; + gr::io_signature::sptr d_output_signature; + long d_unique_id; + long d_symbolic_id; + std::string d_symbol_name; + std::string d_symbol_alias; + vcolor d_color; + bool d_rpc_set; + + msg_queue_map_t msg_queue; + std::vector<boost::any> d_rpc_vars; // container for all RPC variables + + basic_block(void) {} // allows pure virtual interface sub-classes + + //! Protected constructor prevents instantiation by non-derived classes + basic_block(const std::string &name, + gr::io_signature::sptr input_signature, + gr::io_signature::sptr output_signature); + + //! may only be called during constructor + void set_input_signature(gr::io_signature::sptr iosig) { + d_input_signature = iosig; + } + + //! may only be called during constructor + void set_output_signature(gr::io_signature::sptr iosig) { + d_output_signature = iosig; + } + + /*! + * \brief Allow the flowgraph to set for sorting and partitioning + */ + void set_color(vcolor color) { d_color = color; } + vcolor color() const { return d_color; } + + /*! + * \brief Tests if there is a handler attached to port \p which_port + */ + bool has_msg_handler(pmt::pmt_t which_port) { + return (d_msg_handlers.find(which_port) != d_msg_handlers.end()); + } + + /* + * This function is called by the runtime system to dispatch messages. + * + * The thread-safety guarantees mentioned in set_msg_handler are + * implemented by the callers of this method. + */ + virtual void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg) + { + // AA Update this + if(has_msg_handler(which_port)) { // Is there a handler? + d_msg_handlers[which_port](msg); // Yes, invoke it. + } + } + + // Message passing interface + pmt::pmt_t message_subscribers; + + public: + virtual ~basic_block(); + long unique_id() const { return d_unique_id; } + long symbolic_id() const { return d_symbolic_id; } + std::string name() const { return d_name; } + std::string symbol_name() const { return d_symbol_name; } + gr::io_signature::sptr input_signature() const { return d_input_signature; } + gr::io_signature::sptr output_signature() const { return d_output_signature; } + basic_block_sptr to_basic_block(); // Needed for Python type coercion + bool alias_set() { return !d_symbol_alias.empty(); } + std::string alias(){ return alias_set()?d_symbol_alias:symbol_name(); } + pmt::pmt_t alias_pmt(){ return pmt::intern(alias()); } + void set_block_alias(std::string name); + + // ** Message passing interface ** + void message_port_register_in(pmt::pmt_t port_id); + void message_port_register_out(pmt::pmt_t port_id); + void message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg); + void message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target); + void message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target); + + virtual bool message_port_is_hier(pmt::pmt_t port_id) { (void) port_id; std::cout << "is_hier\n"; return false; } + virtual bool message_port_is_hier_in(pmt::pmt_t port_id) { (void) port_id; std::cout << "is_hier_in\n"; return false; } + virtual bool message_port_is_hier_out(pmt::pmt_t port_id) { (void) port_id; std::cout << "is_hier_out\n"; return false; } + + /*! + * \brief Get input message port names. + * + * Returns the available input message ports for a block. The + * return object is a PMT vector that is filled with PMT symbols. + */ + pmt::pmt_t message_ports_in(); + + /*! + * \brief Get output message port names. + * + * Returns the available output message ports for a block. The + * return object is a PMT vector that is filled with PMT symbols. + */ + pmt::pmt_t message_ports_out(); + + /*! + * Accept msg, place in queue, arrange for thread to be awakened if it's not already. + */ + void _post(pmt::pmt_t which_port, pmt::pmt_t msg); + + //! is the queue empty? + //bool empty_p(const pmt::pmt_t &which_port) const { return msg_queue[which_port].empty(); } + bool empty_p(pmt::pmt_t which_port) { + if(msg_queue.find(which_port) == msg_queue.end()) + throw std::runtime_error("port does not exist!"); + return msg_queue[which_port].empty(); + } + bool empty_p() { + bool rv = true; + BOOST_FOREACH(msg_queue_map_t::value_type &i, msg_queue) { + rv &= msg_queue[i.first].empty(); + } + return rv; + } + + //! How many messages in the queue? + size_t nmsgs(pmt::pmt_t which_port) { + if(msg_queue.find(which_port) == msg_queue.end()) + throw std::runtime_error("port does not exist!"); + return msg_queue[which_port].size(); + } + + //| Acquires and release the mutex + void insert_tail( pmt::pmt_t which_port, pmt::pmt_t msg); + /*! + * \returns returns pmt at head of queue or pmt::pmt_t() if empty. + */ + pmt::pmt_t delete_head_nowait( pmt::pmt_t which_port); + + /*! + * \returns returns pmt at head of queue or pmt::pmt_t() if empty. + */ + pmt::pmt_t delete_head_blocking( pmt::pmt_t which_port); + + msg_queue_t::iterator get_iterator(pmt::pmt_t which_port) { + return msg_queue[which_port].begin(); + } + + void erase_msg(pmt::pmt_t which_port, msg_queue_t::iterator it) { + msg_queue[which_port].erase(it); + } + + virtual bool has_msg_port(pmt::pmt_t which_port) { + if(msg_queue.find(which_port) != msg_queue.end()) { + return true; + } + if(pmt::dict_has_key(message_subscribers, which_port)) { + return true; + } + return false; + } + +#ifdef GR_CTRLPORT + /*! + * \brief Add an RPC variable (get or set). + * + * Using controlport, we create new getters/setters and need to + * store them. Each block has a vector to do this, and these never + * need to be accessed again once they are registered with the RPC + * backend. This function takes a + * boost::shared_sptr<rpcbasic_base> so that when the block is + * deleted, all RPC registered variables are cleaned up. + * + * \param s an rpcbasic_sptr of the new RPC variable register to store. + */ + void add_rpc_variable(rpcbasic_sptr s) + { + d_rpc_vars.push_back(s); + } +#endif /* GR_CTRLPORT */ + + /*! + * \brief Set up the RPC registered variables. + * + * This must be overloaded by a block that wants to use + * controlport. This is where rpcbasic_register_{get,set} pointers + * are created, which then get wrapped as shared pointers + * (rpcbasic_sptr(...)) and stored using add_rpc_variable. + */ + virtual void setup_rpc() {}; + + /*! + * \brief Ask if this block has been registered to the RPC. + * + * We can only register a block once, so we use this to protect us + * from calling it multiple times. + */ + bool is_rpc_set() { return d_rpc_set; } + + /*! + * \brief When the block is registered with the RPC, set this. + */ + void rpc_set() { d_rpc_set = true; } + + /*! + * \brief Confirm that ninputs and noutputs is an acceptable combination. + * + * \param ninputs number of input streams connected + * \param noutputs number of output streams connected + * + * \returns true if this is a valid configuration for this block. + * + * This function is called by the runtime system whenever the + * topology changes. Most classes do not need to override this. + * This check is in addition to the constraints specified by the + * input and output gr::io_signatures. + */ + virtual bool check_topology(int ninputs, int noutputs) { + (void)ninputs; + (void)noutputs; + return true; + } + + /*! + * \brief Set the callback that is fired when messages are available. + * + * \p msg_handler can be any kind of function pointer or function object + * that has the signature: + * <pre> + * void msg_handler(pmt::pmt msg); + * </pre> + * + * (You may want to use boost::bind to massage your callable into + * the correct form. See gr::blocks::nop for an example that sets + * up a class method as the callback.) + * + * Blocks that desire to handle messages must call this method in + * their constructors to register the handler that will be invoked + * when messages are available. + * + * If the block inherits from block, the runtime system will + * ensure that msg_handler is called in a thread-safe manner, such + * that work and msg_handler will never be called concurrently. + * This allows msg_handler to update state variables without + * having to worry about thread-safety issues with work, + * general_work or another invocation of msg_handler. + * + * If the block inherits from hier_block2, the runtime system + * will ensure that no reentrant calls are made to msg_handler. + */ + template <typename T> void set_msg_handler(pmt::pmt_t which_port, T msg_handler) { + if(msg_queue.find(which_port) == msg_queue.end()) { + throw std::runtime_error("attempt to set_msg_handler() on bad input message port!"); + } + d_msg_handlers[which_port] = msg_handler_t(msg_handler); + } + }; + + inline bool operator<(basic_block_sptr lhs, basic_block_sptr rhs) + { + return lhs->unique_id() < rhs->unique_id(); + } + + typedef std::vector<basic_block_sptr> basic_block_vector_t; + typedef std::vector<basic_block_sptr>::iterator basic_block_viter_t; + + GR_RUNTIME_API long basic_block_ncurrently_allocated(); + + inline std::ostream &operator << (std::ostream &os, basic_block_sptr basic_block) + { + os << basic_block->name() << "(" << basic_block->unique_id() << ")"; + return os; + } + +} /* namespace gr */ + +#endif /* INCLUDED_GR_BASIC_BLOCK_H */ diff --git a/gnuradio-runtime/include/gnuradio/block.h b/gnuradio-runtime/include/gnuradio/block.h new file mode 100644 index 0000000000..fd6c48c29b --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/block.h @@ -0,0 +1,714 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,2009,2010,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_RUNTIME_BLOCK_H +#define INCLUDED_GR_RUNTIME_BLOCK_H + +#include <gnuradio/api.h> +#include <gnuradio/basic_block.h> +#include <gnuradio/tags.h> +#include <gnuradio/logger.h> + +namespace gr { + + /*! + * \brief The abstract base class for all 'terminal' processing blocks. + * \ingroup base_blk + * + * A signal processing flow is constructed by creating a tree of + * hierarchical blocks, which at any level may also contain terminal + * nodes that actually implement signal processing functions. This + * is the base class for all such leaf nodes. + * + * Blocks have a set of input streams and output streams. The + * input_signature and output_signature define the number of input + * streams and output streams respectively, and the type of the data + * items in each stream. + * + * Although blocks may consume data on each input stream at a + * different rate, all outputs streams must produce data at the same + * rate. That rate may be different from any of the input rates. + * + * User derived blocks override two methods, forecast and + * general_work, to implement their signal processing + * behavior. forecast is called by the system scheduler to determine + * how many items are required on each input stream in order to + * produce a given number of output items. + * + * general_work is called to perform the signal processing in the + * block. It reads the input items and writes the output items. + */ + class GR_RUNTIME_API block : public basic_block + { + public: + + //! Magic return values from general_work + enum { + WORK_CALLED_PRODUCE = -2, + WORK_DONE = -1 + }; + + enum tag_propagation_policy_t { + TPP_DONT = 0, + TPP_ALL_TO_ALL = 1, + TPP_ONE_TO_ONE = 2 + }; + + virtual ~block(); + + /*! + * Assume block computes y_i = f(x_i, x_i-1, x_i-2, x_i-3...) + * History is the number of x_i's that are examined to produce one y_i. + * This comes in handy for FIR filters, where we use history to + * ensure that our input contains the appropriate "history" for the + * filter. History should be equal to the number of filter taps. + */ + unsigned history() const { return d_history; } + void set_history(unsigned history) { d_history = history; } + + /*! + * \brief Return true if this block has a fixed input to output rate. + * + * If true, then fixed_rate_in_to_out and fixed_rate_out_to_in may be called. + */ + bool fixed_rate() const { return d_fixed_rate; } + + // ---------------------------------------------------------------- + // override these to define your behavior + // ---------------------------------------------------------------- + + /*! + * \brief Estimate input requirements given output request + * + * \param noutput_items number of output items to produce + * \param ninput_items_required number of input items required on each input stream + * + * Given a request to product \p noutput_items, estimate the + * number of data items required on each input stream. The + * estimate doesn't have to be exact, but should be close. + */ + virtual void forecast(int noutput_items, + gr_vector_int &ninput_items_required); + + /*! + * \brief compute output items from input items + * + * \param noutput_items number of output items to write on each output stream + * \param ninput_items number of input items available on each input stream + * \param input_items vector of pointers to the input items, one entry per input stream + * \param output_items vector of pointers to the output items, one entry per output stream + * + * \returns number of items actually written to each output stream, or -1 on EOF. + * It is OK to return a value less than noutput_items. -1 <= return value <= noutput_items + * + * general_work must call consume or consume_each to indicate how + * many items were consumed on each input stream. + */ + virtual int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + /*! + * \brief Called to enable drivers, etc for i/o devices. + * + * This allows a block to enable an associated driver to begin + * transfering data just before we start to execute the scheduler. + * The end result is that this reduces latency in the pipeline + * when dealing with audio devices, usrps, etc. + */ + virtual bool start(); + + /*! + * \brief Called to disable drivers, etc for i/o devices. + */ + virtual bool stop(); + + // ---------------------------------------------------------------- + + /*! + * \brief Constrain the noutput_items argument passed to forecast and general_work + * + * set_output_multiple causes the scheduler to ensure that the + * noutput_items argument passed to forecast and general_work will + * be an integer multiple of \param multiple The default value of + * output multiple is 1. + */ + void set_output_multiple(int multiple); + int output_multiple() const { return d_output_multiple; } + bool output_multiple_set() const { return d_output_multiple_set; } + + /*! + * \brief Constrains buffers to work on a set item alignment (for SIMD) + * + * set_alignment_multiple causes the scheduler to ensure that the + * noutput_items argument passed to forecast and general_work will + * be an integer multiple of \param multiple The default value is + * 1. + * + * This control is similar to the output_multiple setting, except + * that if the number of items passed to the block is less than + * the output_multiple, this value is ignored and the block can + * produce like normal. The d_unaligned value is set to the number + * of items the block is off by. In the next call to general_work, + * the noutput_items is set to d_unaligned or less until + * d_unaligned==0. The buffers are now aligned again and the + * aligned calls can be performed again. + */ + void set_alignment(int multiple); + int alignment() const { return d_output_multiple; } + + void set_unaligned(int na); + int unaligned() const { return d_unaligned; } + void set_is_unaligned(bool u); + bool is_unaligned() const { return d_is_unaligned; } + + /*! + * \brief Tell the scheduler \p how_many_items of input stream \p + * which_input were consumed. + */ + void consume(int which_input, int how_many_items); + + /*! + * \brief Tell the scheduler \p how_many_items were consumed on + * each input stream. + */ + void consume_each(int how_many_items); + + /*! + * \brief Tell the scheduler \p how_many_items were produced on + * output stream \p which_output. + * + * If the block's general_work method calls produce, \p + * general_work must return WORK_CALLED_PRODUCE. + */ + void produce(int which_output, int how_many_items); + + /*! + * \brief Set the approximate output rate / input rate + * + * Provide a hint to the buffer allocator and scheduler. + * The default relative_rate is 1.0 + * + * decimators have relative_rates < 1.0 + * interpolators have relative_rates > 1.0 + */ + void set_relative_rate(double relative_rate); + + /*! + * \brief return the approximate output rate / input rate + */ + double relative_rate() const { return d_relative_rate; } + + /* + * The following two methods provide special case info to the + * scheduler in the event that a block has a fixed input to output + * ratio. sync_block, sync_decimator and + * sync_interpolator override these. If you're fixed rate, + * subclass one of those. + */ + /*! + * \brief Given ninput samples, return number of output samples that will be produced. + * N.B. this is only defined if fixed_rate returns true. + * Generally speaking, you don't need to override this. + */ + virtual int fixed_rate_ninput_to_noutput(int ninput); + + /*! + * \brief Given noutput samples, return number of input samples required to produce noutput. + * N.B. this is only defined if fixed_rate returns true. + * Generally speaking, you don't need to override this. + */ + virtual int fixed_rate_noutput_to_ninput(int noutput); + + /*! + * \brief Return the number of items read on input stream which_input + */ + uint64_t nitems_read(unsigned int which_input); + + /*! + * \brief Return the number of items written on output stream which_output + */ + uint64_t nitems_written(unsigned int which_output); + + /*! + * \brief Asks for the policy used by the scheduler to moved tags downstream. + */ + tag_propagation_policy_t tag_propagation_policy(); + + /*! + * \brief Set the policy by the scheduler to determine how tags are moved downstream. + */ + void set_tag_propagation_policy(tag_propagation_policy_t p); + + /*! + * \brief Return the minimum number of output items this block can + * produce during a call to work. + * + * Should be 0 for most blocks. Useful if we're dealing with + * packets and the block produces one packet per call to work. + */ + int min_noutput_items() const { return d_min_noutput_items; } + + /*! + * \brief Set the minimum number of output items this block can + * produce during a call to work. + * + * \param m the minimum noutput_items this block can produce. + */ + void set_min_noutput_items(int m) { d_min_noutput_items = m; } + + /*! + * \brief Return the maximum number of output items this block will + * handle during a call to work. + */ + int max_noutput_items(); + + /*! + * \brief Set the maximum number of output items this block will + * handle during a call to work. + * + * \param m the maximum noutput_items this block will handle. + */ + void set_max_noutput_items(int m); + + /*! + * \brief Clear the switch for using the max_noutput_items value of this block. + * + * When is_set_max_noutput_items() returns 'true', the scheduler + * will use the value returned by max_noutput_items() to limit the + * size of the number of items possible for this block's work + * function. If is_set_max_notput_items() returns 'false', then + * the scheduler ignores the internal value and uses the value set + * globally in the top_block. + * + * Use this value to clear the 'is_set' flag so the scheduler will + * ignore this. Use the set_max_noutput_items(m) call to both set + * a new value for max_noutput_items and to reenable its use in + * the scheduler. + */ + void unset_max_noutput_items(); + + /*! + * \brief Ask the block if the flag is or is not set to use the + * internal value of max_noutput_items during a call to work. + */ + bool is_set_max_noutput_items(); + + /* + * Used to expand the vectors that hold the min/max buffer sizes. + * + * Specifically, when -1 is used, the vectors are just initialized + * with 1 value; this is used by the flat_flowgraph to expand when + * required to add a new value for new ports on these blocks. + */ + void expand_minmax_buffer(int port) + { + if((size_t)port >= d_max_output_buffer.size()) + set_max_output_buffer(port, -1); + if((size_t)port >= d_min_output_buffer.size()) + set_min_output_buffer(port, -1); + } + + /*! + * \brief Returns max buffer size on output port \p i. + */ + long max_output_buffer(size_t i) + { + if(i >= d_max_output_buffer.size()) + throw std::invalid_argument("basic_block::max_output_buffer: port out of range."); + return d_max_output_buffer[i]; + } + + /*! + * \brief Sets max buffer size on all output ports. + */ + void set_max_output_buffer(long max_output_buffer) + { + for(int i = 0; i < output_signature()->max_streams(); i++) { + set_max_output_buffer(i, max_output_buffer); + } + } + + /*! + * \brief Sets max buffer size on output port \p port. + */ + void set_max_output_buffer(int port, long max_output_buffer) + { + if((size_t)port >= d_max_output_buffer.size()) + d_max_output_buffer.push_back(max_output_buffer); + else + d_max_output_buffer[port] = max_output_buffer; + } + + /*! + * \brief Returns min buffer size on output port \p i. + */ + long min_output_buffer(size_t i) + { + if(i >= d_min_output_buffer.size()) + throw std::invalid_argument("basic_block::min_output_buffer: port out of range."); + return d_min_output_buffer[i]; + } + + /*! + * \brief Sets min buffer size on all output ports. + */ + void set_min_output_buffer(long min_output_buffer) + { + for(int i=0; i<output_signature()->max_streams(); i++) { + set_min_output_buffer(i, min_output_buffer); + } + } + + /*! + * \brief Sets min buffer size on output port \p port. + */ + void set_min_output_buffer(int port, long min_output_buffer) + { + if((size_t)port >= d_min_output_buffer.size()) + d_min_output_buffer.push_back(min_output_buffer); + else + d_min_output_buffer[port] = min_output_buffer; + } + + // --------------- Performance counter functions ------------- + + /*! + * \brief Gets instantaneous noutput_items performance counter. + */ + float pc_noutput_items(); + + /*! + * \brief Gets average noutput_items performance counter. + */ + float pc_noutput_items_avg(); + + /*! + * \brief Gets variance of noutput_items performance counter. + */ + float pc_noutput_items_var(); + + /*! + * \brief Gets instantaneous num items produced performance counter. + */ + float pc_nproduced(); + + /*! + * \brief Gets average num items produced performance counter. + */ + float pc_nproduced_avg(); + + /*! + * \brief Gets variance of num items produced performance counter. + */ + float pc_nproduced_var(); + + /*! + * \brief Gets instantaneous fullness of \p which input buffer. + */ + float pc_input_buffers_full(int which); + + /*! + * \brief Gets average fullness of \p which input buffer. + */ + float pc_input_buffers_full_avg(int which); + + /*! + * \brief Gets variance of fullness of \p which input buffer. + */ + float pc_input_buffers_full_var(int which); + + /*! + * \brief Gets instantaneous fullness of all input buffers. + */ + std::vector<float> pc_input_buffers_full(); + + /*! + * \brief Gets average fullness of all input buffers. + */ + std::vector<float> pc_input_buffers_full_avg(); + + /*! + * \brief Gets variance of fullness of all input buffers. + */ + std::vector<float> pc_input_buffers_full_var(); + + /*! + * \brief Gets instantaneous fullness of \p which input buffer. + */ + float pc_output_buffers_full(int which); + + /*! + * \brief Gets average fullness of \p which input buffer. + */ + float pc_output_buffers_full_avg(int which); + + /*! + * \brief Gets variance of fullness of \p which input buffer. + */ + float pc_output_buffers_full_var(int which); + + /*! + * \brief Gets instantaneous fullness of all output buffers. + */ + std::vector<float> pc_output_buffers_full(); + + /*! + * \brief Gets average fullness of all output buffers. + */ + std::vector<float> pc_output_buffers_full_avg(); + + /*! + * \brief Gets variance of fullness of all output buffers. + */ + std::vector<float> pc_output_buffers_full_var(); + + /*! + * \brief Gets instantaneous clock cycles spent in work. + */ + float pc_work_time(); + + /*! + * \brief Gets average clock cycles spent in work. + */ + float pc_work_time_avg(); + + /*! + * \brief Gets average clock cycles spent in work. + */ + float pc_work_time_var(); + + /*! + * \brief Resets the performance counters + */ + void reset_perf_counters(); + + /*! + * \brief Sets up export of perf. counters to ControlPort. Only + * called by the scheduler. + */ + void setup_pc_rpc(); + + /*! + * \brief Checks if this block is already exporting perf. counters + * to ControlPort. + */ + bool is_pc_rpc_set() { return d_pc_rpc_set; } + + /*! + * \brief If the block calls this in its constructor, it's + * perf. counters will not be exported. + */ + void no_pc_rpc() { d_pc_rpc_set = true; } + + + // ---------------------------------------------------------------------------- + // Functions to handle thread affinity + + /*! + * \brief Set the thread's affinity to processor core \p n. + * + * \param mask a vector of ints of the core numbers available to this block. + */ + void set_processor_affinity(const std::vector<int> &mask); + + /*! + * \brief Remove processor affinity to a specific core. + */ + void unset_processor_affinity(); + + /*! + * \brief Get the current processor affinity. + */ + std::vector<int> processor_affinity() { return d_affinity; } + + // ---------------------------------------------------------------------------- + + private: + int d_output_multiple; + bool d_output_multiple_set; + int d_unaligned; + bool d_is_unaligned; + double d_relative_rate; // approx output_rate / input_rate + block_detail_sptr d_detail; // implementation details + unsigned d_history; + bool d_fixed_rate; + bool d_max_noutput_items_set; // if d_max_noutput_items is valid + int d_max_noutput_items; // value of max_noutput_items for this block + int d_min_noutput_items; + tag_propagation_policy_t d_tag_propagation_policy; // policy for moving tags downstream + std::vector<int> d_affinity; // thread affinity proc. mask + bool d_pc_rpc_set; + + protected: + block(void) {} // allows pure virtual interface sub-classes + block(const std::string &name, + gr::io_signature::sptr input_signature, + gr::io_signature::sptr output_signature); + + void set_fixed_rate(bool fixed_rate) { d_fixed_rate = fixed_rate; } + + /*! + * \brief Adds a new tag onto the given output buffer. + * + * \param which_output an integer of which output stream to attach the tag + * \param abs_offset a uint64 number of the absolute item number + * assicated with the tag. Can get from nitems_written. + * \param key the tag key as a PMT symbol + * \param value any PMT holding any value for the given key + * \param srcid optional source ID specifier; defaults to PMT_F + */ + inline void add_item_tag(unsigned int which_output, + uint64_t abs_offset, + const pmt::pmt_t &key, + const pmt::pmt_t &value, + const pmt::pmt_t &srcid=pmt::PMT_F) + { + tag_t tag; + tag.offset = abs_offset; + tag.key = key; + tag.value = value; + tag.srcid = srcid; + this->add_item_tag(which_output, tag); + } + + /*! + * \brief Adds a new tag onto the given output buffer. + * + * \param which_output an integer of which output stream to attach the tag + * \param tag the tag object to add + */ + void add_item_tag(unsigned int which_output, const tag_t &tag); + + /*! + * \brief Removes a tag from the given input buffer. + * + * \param which_input an integer of which input stream to remove the tag from + * \param abs_offset a uint64 number of the absolute item number + * assicated with the tag. Can get from nitems_written. + * \param key the tag key as a PMT symbol + * \param value any PMT holding any value for the given key + * \param srcid optional source ID specifier; defaults to PMT_F + * + * If no such tag is found, does nothing. + */ + inline void remove_item_tag(unsigned int which_input, + uint64_t abs_offset, + const pmt::pmt_t &key, + const pmt::pmt_t &value, + const pmt::pmt_t &srcid=pmt::PMT_F) + { + tag_t tag; + tag.offset = abs_offset; + tag.key = key; + tag.value = value; + tag.srcid = srcid; + this->remove_item_tag(which_input, tag); + } + + /*! + * \brief Removes a tag from the given input buffer. + * + * If no such tag is found, does nothing. + * + * \param which_input an integer of which input stream to remove the tag from + * \param tag the tag object to remove + */ + void remove_item_tag(unsigned int which_input, const tag_t &tag); + + /*! + * \brief Given a [start,end), returns a vector of all tags in the range. + * + * Range of counts is from start to end-1. + * + * Tags are tuples of: + * (item count, source id, key, value) + * + * \param v a vector reference to return tags into + * \param which_input an integer of which input stream to pull from + * \param abs_start a uint64 count of the start of the range of interest + * \param abs_end a uint64 count of the end of the range of interest + */ + void get_tags_in_range(std::vector<tag_t> &v, + unsigned int which_input, + uint64_t abs_start, + uint64_t abs_end); + + /*! + * \brief Given a [start,end), returns a vector of all tags in the + * range with a given key. + * + * Range of counts is from start to end-1. + * + * Tags are tuples of: + * (item count, source id, key, value) + * + * \param v a vector reference to return tags into + * \param which_input an integer of which input stream to pull from + * \param abs_start a uint64 count of the start of the range of interest + * \param abs_end a uint64 count of the end of the range of interest + * \param key a PMT symbol key to filter only tags of this key + */ + void get_tags_in_range(std::vector<tag_t> &v, + unsigned int which_input, + uint64_t abs_start, + uint64_t abs_end, + const pmt::pmt_t &key); + + std::vector<long> d_max_output_buffer; + std::vector<long> d_min_output_buffer; + + /*! Used by block's setters and work functions to make + * setting/resetting of parameters thread-safe. + * + * Used by calling gr::thread::scoped_lock l(d_setlock); + */ + gr::thread::mutex d_setlock; + + /*! Used by blocks to access the logger system. + */ + gr::logger_ptr d_logger; + gr::logger_ptr d_debug_logger; + + // These are really only for internal use, but leaving them public avoids + // having to work up an ever-varying list of friend GR_RUNTIME_APIs + + public: + block_detail_sptr detail() const { return d_detail; } + void set_detail(block_detail_sptr detail) { d_detail = detail; } + }; + + typedef std::vector<block_sptr> block_vector_t; + typedef std::vector<block_sptr>::iterator block_viter_t; + + inline block_sptr cast_to_block_sptr(basic_block_sptr p) + { + return boost::dynamic_pointer_cast<block, basic_block>(p); + } + + std::ostream& + operator << (std::ostream& os, const block *m); + +} /* namespace gr */ + +#endif /* INCLUDED_GR_RUNTIME_BLOCK_H */ diff --git a/gnuradio-runtime/include/gnuradio/block_detail.h b/gnuradio-runtime/include/gnuradio/block_detail.h new file mode 100644 index 0000000000..0a8615a2b6 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/block_detail.h @@ -0,0 +1,261 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2009,2010,2013 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 3, 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 detail. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_RUNTIME_BLOCK_DETAIL_H +#define INCLUDED_GR_RUNTIME_BLOCK_DETAIL_H + +#include <gnuradio/api.h> +#include <gnuradio/runtime_types.h> +#include <gnuradio/tpb_detail.h> +#include <gnuradio/tags.h> +#include <gnuradio/high_res_timer.h> +#include <stdexcept> + +namespace gr { + + /*! + * \brief Implementation details to support the signal processing abstraction + * \ingroup internal + * + * This class contains implementation detail that should be "out of + * sight" of almost all users of GNU Radio. This decoupling also + * means that we can make changes to the guts without having to + * recompile everything. + */ + class GR_RUNTIME_API block_detail + { + public: + ~block_detail(); + + int ninputs() const { return d_ninputs; } + int noutputs() const { return d_noutputs; } + bool sink_p() const { return d_noutputs == 0; } + bool source_p() const { return d_ninputs == 0; } + + void set_done(bool done); + bool done() const { return d_done; } + + void set_input(unsigned int which, buffer_reader_sptr reader); + buffer_reader_sptr input(unsigned int which) + { + if(which >= d_ninputs) + throw std::invalid_argument("block_detail::input"); + return d_input[which]; + } + + void set_output(unsigned int which, buffer_sptr buffer); + buffer_sptr output(unsigned int which) + { + if(which >= d_noutputs) + throw std::invalid_argument("block_detail::output"); + return d_output[which]; + } + + /*! + * \brief Tell the scheduler \p how_many_items of input stream \p + * which_input were consumed. + */ + void consume(int which_input, int how_many_items); + + /*! + * \brief Tell the scheduler \p how_many_items were consumed on + * each input stream. + */ + void consume_each(int how_many_items); + + /*! + * \brief Tell the scheduler \p how_many_items were produced on + * output stream \p which_output. + */ + void produce(int which_output, int how_many_items); + + /*! + * \brief Tell the scheduler \p how_many_items were produced on + * each output stream. + */ + void produce_each(int how_many_items); + + // Return the number of items read on input stream which_input + uint64_t nitems_read(unsigned int which_input); + + // Return the number of items written on output stream which_output + uint64_t nitems_written(unsigned int which_output); + + /*! + * \brief Adds a new tag to the given output stream. + * + * Calls gr::buffer::add_item_tag(), + * which appends the tag onto its deque. + * + * \param which_output an integer of which output stream to attach the tag + * \param tag the tag object to add + */ + void add_item_tag(unsigned int which_output, const tag_t &tag); + + /*! + * \brief Removes a tag from the given input stream. + * + * Calls gr::buffer::remove_item_tag(), which removes the tag from + * its deque. + * + * \param which_input an integer of which input stream to remove the tag from + * \param tag the tag object to add + */ + void remove_item_tag(unsigned int which_input, const tag_t &tag); + + /*! + * \brief Given a [start,end), returns a vector of all tags in the range. + * + * Pass-through function to gr::buffer_reader to get a vector of + * tags in given range. Range of counts is from start to end-1. + * + * Tags are tuples of: + * (item count, source id, key, value) + * + * \param v a vector reference to return tags into + * \param which_input an integer of which input stream to pull from + * \param abs_start a uint64 count of the start of the range of interest + * \param abs_end a uint64 count of the end of the range of interest + */ + void get_tags_in_range(std::vector<tag_t> &v, + unsigned int which_input, + uint64_t abs_start, + uint64_t abs_end); + + /*! + * \brief Given a [start,end), returns a vector of all tags in the + * range with a given key. + * + * Calls get_tags_in_range(which_input, abs_start, abs_end) to get + * a vector of tags from the buffers. This function then provides + * a secondary filter to the tags to extract only tags with the + * given 'key'. + * + * Tags are tuples of: + * (item count, source id, key, value) + * + * \param v a vector reference to return tags into + * \param which_input an integer of which input stream to pull from + * \param abs_start a uint64 count of the start of the range of interest + * \param abs_end a uint64 count of the end of the range of interest + * \param key a PMT symbol to select only tags of this key + */ + void get_tags_in_range(std::vector<tag_t> &v, + unsigned int which_input, + uint64_t abs_start, + uint64_t abs_end, + const pmt::pmt_t &key); + + /*! + * \brief Set core affinity of block to the cores in the vector + * mask. + * + * \param mask a vector of ints of the core numbers available to + * this block. + */ + void set_processor_affinity(const std::vector<int> &mask); + + /*! + * \brief Unset core affinity. + */ + void unset_processor_affinity(); + + bool threaded; // set if thread is currently running. + gr::thread::gr_thread_t thread; // portable thread handle + + void start_perf_counters(); + void stop_perf_counters(int noutput_items, int nproduced); + void reset_perf_counters(); + + // Calls to get performance counter items + float pc_noutput_items(); + float pc_nproduced(); + float pc_input_buffers_full(size_t which); + std::vector<float> pc_input_buffers_full(); + float pc_output_buffers_full(size_t which); + std::vector<float> pc_output_buffers_full(); + float pc_work_time(); + + float pc_noutput_items_avg(); + float pc_nproduced_avg(); + float pc_input_buffers_full_avg(size_t which); + std::vector<float> pc_input_buffers_full_avg(); + float pc_output_buffers_full_avg(size_t which); + std::vector<float> pc_output_buffers_full_avg(); + float pc_work_time_avg(); + + float pc_noutput_items_var(); + float pc_nproduced_var(); + float pc_input_buffers_full_var(size_t which); + std::vector<float> pc_input_buffers_full_var(); + float pc_output_buffers_full_var(size_t which); + std::vector<float> pc_output_buffers_full_var(); + float pc_work_time_var(); + + tpb_detail d_tpb; // used by thread-per-block scheduler + int d_produce_or; + + // ---------------------------------------------------------------------------- + + private: + unsigned int d_ninputs; + unsigned int d_noutputs; + std::vector<buffer_reader_sptr> d_input; + std::vector<buffer_sptr> d_output; + bool d_done; + + // Performance counters + float d_ins_noutput_items; + float d_avg_noutput_items; + float d_var_noutput_items; + float d_ins_nproduced; + float d_avg_nproduced; + float d_var_nproduced; + std::vector<float> d_ins_input_buffers_full; + std::vector<float> d_avg_input_buffers_full; + std::vector<float> d_var_input_buffers_full; + std::vector<float> d_ins_output_buffers_full; + std::vector<float> d_avg_output_buffers_full; + std::vector<float> d_var_output_buffers_full; + gr::high_res_timer_type d_start_of_work, d_end_of_work; + float d_ins_work_time; + float d_avg_work_time; + float d_var_work_time; + float d_pc_counter; + + block_detail(unsigned int ninputs, unsigned int noutputs); + + friend struct tpb_detail; + + friend GR_RUNTIME_API block_detail_sptr + make_block_detail(unsigned int ninputs, unsigned int noutputs); + }; + + GR_RUNTIME_API block_detail_sptr + make_block_detail(unsigned int ninputs, unsigned int noutputs); + + GR_RUNTIME_API long + block_detail_ncurrently_allocated(); + +} /* namespace gr */ + +#endif /* INCLUDED_GR_RUNTIME_BLOCK_DETAIL_H */ diff --git a/gnuradio-runtime/include/gnuradio/block_gateway.h b/gnuradio-runtime/include/gnuradio/block_gateway.h new file mode 100644 index 0000000000..0f328de2e5 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/block_gateway.h @@ -0,0 +1,271 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011-2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_RUNTIME_BLOCK_GATEWAY_H +#define INCLUDED_RUNTIME_BLOCK_GATEWAY_H + +#include <gnuradio/api.h> +#include <gnuradio/block.h> +#include <gnuradio/feval.h> + +namespace gr { + + /*! + * The work type enum tells the gateway what kind of block to + * implement. The choices are familiar gnuradio block overloads + * (sync, decim, interp). + */ + enum block_gw_work_type { + GR_BLOCK_GW_WORK_GENERAL, + GR_BLOCK_GW_WORK_SYNC, + GR_BLOCK_GW_WORK_DECIM, + GR_BLOCK_GW_WORK_INTERP, + }; + + /*! + * Shared message structure between python and gateway. + * Each action type represents a scheduler-called function. + */ + struct block_gw_message_type { + enum action_type { + ACTION_GENERAL_WORK, //dispatch work + ACTION_WORK, //dispatch work + ACTION_FORECAST, //dispatch forecast + ACTION_START, //dispatch start + ACTION_STOP, //dispatch stop + }; + + action_type action; + + int general_work_args_noutput_items; + std::vector<int> general_work_args_ninput_items; + std::vector<void *> general_work_args_input_items; //TODO this should be const void*, but swig cant int cast it right + std::vector<void *> general_work_args_output_items; + int general_work_args_return_value; + + int work_args_ninput_items; + int work_args_noutput_items; + std::vector<void *> work_args_input_items; //TODO this should be const void*, but swig cant int cast it right + std::vector<void *> work_args_output_items; + int work_args_return_value; + + int forecast_args_noutput_items; + std::vector<int> forecast_args_ninput_items_required; + + bool start_args_return_value; + + bool stop_args_return_value; + }; + + /*! + * The gateway block which performs all the magic. + * + * The gateway provides access to all the gr::block routines. + * The methods prefixed with gr::block__ are renamed + * to class methods without the prefix in python. + */ + class GR_RUNTIME_API block_gateway : virtual public gr::block + { + public: + // gr::block_gateway::sptr + typedef boost::shared_ptr<block_gateway> sptr; + + /*! + * Make a new gateway block. + * \param handler the swig director object with callback + * \param name the name of the block (Ex: "Shirley") + * \param in_sig the input signature for this block + * \param out_sig the output signature for this block + * \param work_type the type of block overload to implement + * \param factor the decimation or interpolation factor + * \return a new gateway block + */ + static sptr make(gr::feval_ll *handler, + const std::string &name, + gr::io_signature::sptr in_sig, + gr::io_signature::sptr out_sig, + const block_gw_work_type work_type, + const unsigned factor); + + //! Provide access to the shared message object + virtual block_gw_message_type &block_message(void) = 0; + + long block__unique_id(void) const { + return gr::block::unique_id(); + } + + std::string block__name(void) const { + return gr::block::name(); + } + + unsigned block__history(void) const { + return gr::block::history(); + } + + void block__set_history(unsigned history) { + return gr::block::set_history(history); + } + + void block__set_fixed_rate(bool fixed_rate) { + return gr::block::set_fixed_rate(fixed_rate); + } + + bool block__fixed_rate(void) const { + return gr::block::fixed_rate(); + } + + void block__set_output_multiple(int multiple) { + return gr::block::set_output_multiple(multiple); + } + + int block__output_multiple(void) const { + return gr::block::output_multiple(); + } + + void block__consume(int which_input, int how_many_items) { + return gr::block::consume(which_input, how_many_items); + } + + void block__consume_each(int how_many_items) { + return gr::block::consume_each(how_many_items); + } + + void block__produce(int which_output, int how_many_items) { + return gr::block::produce(which_output, how_many_items); + } + + void block__set_relative_rate(double relative_rate) { + return gr::block::set_relative_rate(relative_rate); + } + + double block__relative_rate(void) const { + return gr::block::relative_rate(); + } + + uint64_t block__nitems_read(unsigned int which_input) { + return gr::block::nitems_read(which_input); + } + + uint64_t block__nitems_written(unsigned int which_output) { + return gr::block::nitems_written(which_output); + } + + block::tag_propagation_policy_t block__tag_propagation_policy(void) { + return gr::block::tag_propagation_policy(); + } + + void block__set_tag_propagation_policy(block::tag_propagation_policy_t p) { + return gr::block::set_tag_propagation_policy(p); + } + + void block__add_item_tag(unsigned int which_output, + const tag_t &tag) + { + return gr::block::add_item_tag(which_output, tag); + } + + void block__add_item_tag(unsigned int which_output, + uint64_t abs_offset, + const pmt::pmt_t &key, + const pmt::pmt_t &value, + const pmt::pmt_t &srcid=pmt::PMT_F) + { + return gr::block::add_item_tag(which_output, abs_offset, + key, value, srcid); + } + + std::vector<tag_t> block__get_tags_in_range(unsigned int which_input, + uint64_t abs_start, + uint64_t abs_end) + { + std::vector<gr::tag_t> tags; + gr::block::get_tags_in_range(tags, which_input, abs_start, abs_end); + return tags; + } + + std::vector<tag_t> block__get_tags_in_range(unsigned int which_input, + uint64_t abs_start, + uint64_t abs_end, + const pmt::pmt_t &key) + { + std::vector<gr::tag_t> tags; + gr::block::get_tags_in_range(tags, which_input, abs_start, abs_end, key); + return tags; + } + + /* Message passing interface */ + void block__message_port_register_in(pmt::pmt_t port_id) { + gr::basic_block::message_port_register_in(port_id); + } + + void block__message_port_register_out(pmt::pmt_t port_id) { + gr::basic_block::message_port_register_out(port_id); + } + + void block__message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg) { + gr::basic_block::message_port_pub(port_id, msg); + } + + void block__message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target) { + gr::basic_block::message_port_sub(port_id, target); + } + + void block__message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target) { + gr::basic_block::message_port_unsub(port_id, target); + } + + pmt::pmt_t block__message_ports_in() { + return gr::basic_block::message_ports_in(); + } + + pmt::pmt_t block__message_ports_out() { + return gr::basic_block::message_ports_out(); + } + + void set_msg_handler_feval(pmt::pmt_t which_port, gr::feval_p *msg_handler) + { + if(msg_queue.find(which_port) == msg_queue.end()) { + throw std::runtime_error("attempt to set_msg_handler_feval() on bad input message port!"); + } + d_msg_handlers_feval[which_port] = msg_handler; + } + + protected: + typedef std::map<pmt::pmt_t, feval_p *, pmt::comperator> msg_handlers_feval_t; + msg_handlers_feval_t d_msg_handlers_feval; + + void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg) + { + // Is there a handler? + if(d_msg_handlers_feval.find(which_port) != d_msg_handlers_feval.end()) { + d_msg_handlers_feval[which_port]->calleval(msg); // Yes, invoke it. + } + else { + // Pass to generic dispatcher if not found + gr::basic_block::dispatch_msg(which_port, msg); + } + } + }; + +} /* namespace gr */ + +#endif /* INCLUDED_RUNTIME_BLOCK_GATEWAY_H */ diff --git a/gnuradio-runtime/include/gnuradio/block_registry.h b/gnuradio-runtime/include/gnuradio/block_registry.h new file mode 100644 index 0000000000..f94be2dafb --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/block_registry.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012-2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef GR_RUNTIME_BLOCK_REGISTRY_H +#define GR_RUNTIME_BLOCK_REGISTRY_H + +#include <gnuradio/api.h> +#include <gnuradio/basic_block.h> +#include <map> + +namespace gr { + +#ifndef GR_BASIC_BLOCK_H + class basic_block; + class block; +#endif + + class GR_RUNTIME_API block_registry + { + public: + block_registry(); + + long block_register(basic_block* block); + void block_unregister(basic_block* block); + + std::string register_symbolic_name(basic_block* block); + void register_symbolic_name(basic_block* block, std::string name); + + basic_block_sptr block_lookup(pmt::pmt_t symbol); + + void register_primitive(std::string blk, gr::block* ref); + void unregister_primitive(std::string blk); + void notify_blk(std::string blk); + + private: + //typedef std::map< long, basic_block_sptr > blocksubmap_t; + typedef std::map< long, basic_block* > blocksubmap_t; + typedef std::map< std::string, blocksubmap_t > blockmap_t; + + blockmap_t d_map; + pmt::pmt_t d_ref_map; + std::map< std::string, block*> primitive_map; + }; + +} /* namespace gr */ + +GR_RUNTIME_API extern gr::block_registry global_block_registry; + +#endif /* GR_RUNTIME_BLOCK_REGISTRY_H */ diff --git a/gnuradio-runtime/include/gnuradio/buffer.h b/gnuradio-runtime/include/gnuradio/buffer.h new file mode 100644 index 0000000000..490c8e0e9f --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/buffer.h @@ -0,0 +1,302 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2009-2011,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_RUNTIME_BUFFER_H +#define INCLUDED_GR_RUNTIME_BUFFER_H + +#include <gnuradio/api.h> +#include <gnuradio/runtime_types.h> +#include <gnuradio/tags.h> +#include <boost/weak_ptr.hpp> +#include <gnuradio/thread/thread.h> +#include <deque> + +namespace gr { + + class vmcircbuf; + + /*! + * \brief Allocate a buffer that holds at least \p nitems of size \p sizeof_item. + * + * The total size of the buffer will be rounded up to a system + * dependent boundary. This is typically the system page size, but + * under MS windows is 64KB. + * + * \param nitems is the minimum number of items the buffer will hold. + * \param sizeof_item is the size of an item in bytes. + * \param link is the block that writes to this buffer. + */ + GR_RUNTIME_API buffer_sptr make_buffer(int nitems, size_t sizeof_item, + block_sptr link=block_sptr()); + + /*! + * \brief Single writer, multiple reader fifo. + * \ingroup internal + */ + class GR_RUNTIME_API buffer + { + public: + virtual ~buffer(); + + /*! + * \brief return number of items worth of space available for writing + */ + int space_available(); + + /*! + * \brief return size of this buffer in items + */ + int bufsize() const { return d_bufsize; } + + /*! + * \brief return pointer to write buffer. + * + * The return value points at space that can hold at least + * space_available() items. + */ + void *write_pointer(); + + /*! + * \brief tell buffer that we wrote \p nitems into it + */ + void update_write_pointer(int nitems); + + void set_done(bool done); + bool done() const { return d_done; } + + /*! + * \brief Return the block that writes to this buffer. + */ + block_sptr link() { return block_sptr(d_link); } + + size_t nreaders() const { return d_readers.size(); } + buffer_reader* reader(size_t index) { return d_readers[index]; } + + gr::thread::mutex *mutex() { return &d_mutex; } + + uint64_t nitems_written() { return d_abs_write_offset; } + + size_t get_sizeof_item() { return d_sizeof_item; } + + /*! + * \brief Adds a new tag to the buffer. + * + * \param tag the new tag + */ + void add_item_tag(const tag_t &tag); + + /*! + * \brief Removes an existing tag from the buffer. + * + * If no such tag is found, does nothing. + * + * \param tag the tag that needs to be removed + */ + void remove_item_tag(const tag_t &tag); + + /*! + * \brief Removes all tags before \p max_time from buffer + * + * \param max_time the time (item number) to trim up until. + */ + void prune_tags(uint64_t max_time); + + std::deque<tag_t>::iterator get_tags_begin() { return d_item_tags.begin(); } + std::deque<tag_t>::iterator get_tags_end() { return d_item_tags.end(); } + + // ------------------------------------------------------------------------- + + private: + friend class buffer_reader; + friend GR_RUNTIME_API buffer_sptr make_buffer(int nitems, size_t sizeof_item, block_sptr link); + friend GR_RUNTIME_API buffer_reader_sptr buffer_add_reader(buffer_sptr buf, int nzero_preload, block_sptr link); + + protected: + char *d_base; // base address of buffer + unsigned int d_bufsize; // in items + private: + gr::vmcircbuf *d_vmcircbuf; + size_t d_sizeof_item; // in bytes + std::vector<buffer_reader *> d_readers; + boost::weak_ptr<block> d_link; // block that writes to this buffer + + // + // The mutex protects d_write_index, d_abs_write_offset, d_done, d_item_tags + // and the d_read_index's and d_abs_read_offset's in the buffer readers. + // + gr::thread::mutex d_mutex; + unsigned int d_write_index; // in items [0,d_bufsize) + uint64_t d_abs_write_offset; // num items written since the start + bool d_done; + std::deque<tag_t> d_item_tags; + uint64_t d_last_min_items_read; + + unsigned index_add(unsigned a, unsigned b) + { + unsigned s = a + b; + + if(s >= d_bufsize) + s -= d_bufsize; + + assert(s < d_bufsize); + return s; + } + + unsigned index_sub(unsigned a, unsigned b) + { + int s = a - b; + + if(s < 0) + s += d_bufsize; + + assert((unsigned) s < d_bufsize); + return s; + } + + virtual bool allocate_buffer(int nitems, size_t sizeof_item); + + /*! + * \brief constructor is private. Use gr_make_buffer to create instances. + * + * Allocate a buffer that holds at least \p nitems of size \p sizeof_item. + * + * \param nitems is the minimum number of items the buffer will hold. + * \param sizeof_item is the size of an item in bytes. + * \param link is the block that writes to this buffer. + * + * The total size of the buffer will be rounded up to a system + * dependent boundary. This is typically the system page size, but + * under MS windows is 64KB. + */ + buffer(int nitems, size_t sizeof_item, block_sptr link); + + /*! + * \brief disassociate \p reader from this buffer + */ + void drop_reader(buffer_reader *reader); + }; + + /*! + * \brief Create a new gr::buffer_reader and attach it to buffer \p buf + * \param buf is the buffer the \p gr::buffer_reader reads from. + * \param nzero_preload -- number of zero items to "preload" into buffer. + * \param link is the block that reads from the buffer using this gr::buffer_reader. + */ + GR_RUNTIME_API buffer_reader_sptr + buffer_add_reader(buffer_sptr buf, int nzero_preload, block_sptr link=block_sptr()); + + //! returns # of buffers currently allocated + GR_RUNTIME_API long buffer_ncurrently_allocated(); + + + // --------------------------------------------------------------------------- + + /*! + * \brief How we keep track of the readers of a gr::buffer. + * \ingroup internal + */ + class GR_RUNTIME_API buffer_reader + { + public: + ~buffer_reader(); + + /*! + * \brief Return number of items available for reading. + */ + int items_available() const; + + /*! + * \brief Return buffer this reader reads from. + */ + buffer_sptr buffer() const { return d_buffer; } + + /*! + * \brief Return maximum number of items that could ever be available for reading. + * This is used as a sanity check in the scheduler to avoid looping forever. + */ + int max_possible_items_available() const { return d_buffer->d_bufsize - 1; } + + /*! + * \brief return pointer to read buffer. + * + * The return value points to items_available() number of items + */ + const void *read_pointer(); + + /* + * \brief tell buffer we read \p items from it + */ + void update_read_pointer(int nitems); + + void set_done(bool done) { d_buffer->set_done(done); } + bool done() const { return d_buffer->done(); } + + gr::thread::mutex *mutex() { return d_buffer->mutex(); } + + uint64_t nitems_read() { return d_abs_read_offset; } + + size_t get_sizeof_item() { return d_buffer->get_sizeof_item(); } + + /*! + * \brief Return the block that reads via this reader. + * + */ + block_sptr link() { return block_sptr(d_link); } + + /*! + * \brief Given a [start,end), returns a vector all tags in the range. + * + * Get a vector of tags in given range. Range of counts is from start to end-1. + * + * Tags are tuples of: + * (item count, source id, key, value) + * + * \param v a vector reference to return tags into + * \param abs_start a uint64 count of the start of the range of interest + * \param abs_end a uint64 count of the end of the range of interest + */ + void get_tags_in_range(std::vector<tag_t> &v, + uint64_t abs_start, + uint64_t abs_end); + + // ------------------------------------------------------------------------- + + private: + friend class buffer; + friend GR_RUNTIME_API buffer_reader_sptr + buffer_add_reader(buffer_sptr buf, int nzero_preload, block_sptr link); + + buffer_sptr d_buffer; + unsigned int d_read_index; // in items [0,d->buffer.d_bufsize) + uint64_t d_abs_read_offset; // num items seen since the start + boost::weak_ptr<block> d_link; // block that reads via this buffer reader + + //! constructor is private. Use gr::buffer::add_reader to create instances + buffer_reader(buffer_sptr buffer, unsigned int read_index, block_sptr link); + }; + + //! returns # of buffer_readers currently allocated + GR_RUNTIME_API long buffer_reader_ncurrently_allocated (); + +} /* namespace gr */ + +#endif /* INCLUDED_GR_RUNTIME_BUFFER_H */ diff --git a/gnuradio-runtime/include/gr_constants.h b/gnuradio-runtime/include/gnuradio/constants.h index 3534166bc0..5ae924ca0d 100644 --- a/gnuradio-runtime/include/gr_constants.h +++ b/gnuradio-runtime/include/gnuradio/constants.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006,2009 Free Software Foundation, Inc. + * Copyright 2006,2009,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -19,35 +19,40 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ + #ifndef INCLUDED_GR_CONSTANTS_H #define INCLUDED_GR_CONSTANTS_H -#include <gr_runtime_api.h> +#include <gnuradio/api.h> #include <string> -/*! - * \brief return ./configure --prefix argument. Typically /usr/local - */ -GR_RUNTIME_API const std::string gr_prefix(); +namespace gr { -/*! - * \brief return ./configure --sysconfdir argument. Typically $prefix/etc or /etc - */ -GR_RUNTIME_API const std::string gr_sysconfdir(); + /*! + * \brief return ./configure --prefix argument. Typically /usr/local + */ + GR_RUNTIME_API const std::string prefix(); -/*! - * \brief return preferences file directory. Typically $sysconfdir/etc/conf.d - */ -GR_RUNTIME_API const std::string gr_prefsdir(); + /*! + * \brief return ./configure --sysconfdir argument. Typically $prefix/etc or /etc + */ + GR_RUNTIME_API const std::string sysconfdir(); -/*! - * \brief return date/time of build, as set when 'bootstrap' is run - */ -GR_RUNTIME_API const std::string gr_build_date(); + /*! + * \brief return preferences file directory. Typically $sysconfdir/etc/conf.d + */ + GR_RUNTIME_API const std::string prefsdir(); -/*! - * \brief return version string defined in configure.ac - */ -GR_RUNTIME_API const std::string gr_version(); + /*! + * \brief return date/time of build, as set when 'bootstrap' is run + */ + GR_RUNTIME_API const std::string build_date(); + + /*! + * \brief return version string defined in configure.ac + */ + GR_RUNTIME_API const std::string version(); + +} /* namespace gr */ #endif /* INCLUDED_GR_CONSTANTS_H */ diff --git a/gnuradio-runtime/include/gnuradio/dispatcher.h b/gnuradio-runtime/include/gnuradio/dispatcher.h new file mode 100644 index 0000000000..ab1d6190c6 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/dispatcher.h @@ -0,0 +1,73 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_DISPATCHER_H +#define INCLUDED_GR_DISPATCHER_H + +#include <gnuradio/api.h> +#include <gnuradio/select_handler.h> +#include <vector> + +namespace gr { + + class dispatcher; + typedef boost::shared_ptr<dispatcher> dispatcher_sptr; + + GR_RUNTIME_API dispatcher_sptr dispatcher_singleton(); + GR_RUNTIME_API dispatcher_sptr make_dispatcher(); + + /*! + * \brief invoke callbacks based on select. + * \ingroup internal + * + * \sa gr_select_handler + */ + class GR_RUNTIME_API dispatcher + { + dispatcher(); + friend GR_RUNTIME_API dispatcher_sptr make_dispatcher(); + + std::vector<select_handler_sptr> d_handler; + int d_max_index; + + public: + ~dispatcher(); + + bool add_handler(select_handler_sptr handler); + bool del_handler(select_handler_sptr handler); + bool del_handler(select_handler *handler); + + /*! + * \brief Event dispatching loop. + * + * Enter a polling loop that only terminates after all + * gr::select_handlers have been removed. \p timeout sets the + * timeout parameter to the select() call, measured in seconds. + * + * \param timeout maximum number of seconds to block in select. + */ + void loop(double timeout=10); + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_DISPATCHER_H */ diff --git a/gnuradio-runtime/include/gr_endianness.h b/gnuradio-runtime/include/gnuradio/endianness.h index c4ecb1383e..43c21a1c15 100644 --- a/gnuradio-runtime/include/gr_endianness.h +++ b/gnuradio-runtime/include/gnuradio/endianness.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -19,9 +19,14 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ + #ifndef INCLUDED_GR_ENDIANNESS_H #define INCLUDED_GR_ENDIANNESS_H -typedef enum {GR_MSB_FIRST, GR_LSB_FIRST} gr_endianness_t; +namespace gr { + + typedef enum {GR_MSB_FIRST, GR_LSB_FIRST} endianness_t; + +} /* namespace gr */ #endif /* INCLUDED_GR_ENDIANNESS_H */ diff --git a/gnuradio-runtime/include/gnuradio/error_handler.h b/gnuradio-runtime/include/gnuradio/error_handler.h new file mode 100644 index 0000000000..2d6a8c3883 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/error_handler.h @@ -0,0 +1,125 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +/* + * This code is based on error.hh from the "Click Modular Router". + * Original copyright follows: + */ +/* + * error.{cc,hh} -- flexible classes for error reporting + * Eddie Kohler + * + * Copyright (c) 1999-2000 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, subject to the conditions + * listed in the Click LICENSE file. These conditions include: you must + * preserve this copyright notice, and you cannot mention the copyright + * holders in advertising related to the Software without their permission. + * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This + * notice is a summary of the Click LICENSE file; the license in that file is + * legally binding. + */ + +#ifndef INCLUDED_GR_ERROR_HANDLER_H +#define INCLUDED_GR_ERROR_HANDLER_H + +#include <gnuradio/api.h> +#include <stdarg.h> +#include <string> +#include <cstdio> // for FILE + +namespace gr { + + /*! + * \brief abstract error handler + * \ingroup base + */ + class GR_RUNTIME_API error_handler + { + public: + enum seriousness { + ERR_DEBUG = 0x00000000, + ERR_MESSAGE = 0x00010000, + ERR_WARNING = 0x00020000, + ERR_ERROR = 0x00030000, + ERR_FATAL = 0x00040000 + }; + + error_handler() {} + virtual ~error_handler(); + + static error_handler *default_handler(); + static error_handler *silent_handler(); + + static bool has_default_handler(); + static void set_default_handler(error_handler *errh); + + void debug(const char *format, ...); + void message(const char *format, ...); + void warning(const char *format, ...); + void error(const char *format, ...); + void fatal(const char *format, ...); + + virtual int nwarnings() const = 0; + virtual int nerrors() const = 0; + virtual void reset_counts() = 0; + + void verror(seriousness s, const char *format, va_list); + void verror_text(seriousness s, const std::string &text); + + protected: + virtual void count_error(seriousness s) = 0; + virtual void handle_text(seriousness s, const std::string &str) = 0; + std::string make_text(seriousness s, const char *format, va_list); + }; + + + class GR_RUNTIME_API base_error_handler : public error_handler + { + int d_nwarnings; + int d_nerrors; + + public: + base_error_handler() : d_nwarnings(0), d_nerrors(0) {} + int nwarnings() const { return d_nwarnings; } + int nerrors() const { return d_nerrors; } + void reset_counts() { d_nwarnings = d_nerrors = 0; } + void count_error(seriousness s); + }; + + class GR_RUNTIME_API file_error_handler : public base_error_handler + { + FILE *d_file; + int d_fd; + + public: + file_error_handler(FILE *file); + file_error_handler(int file_descriptor); + ~file_error_handler(); + + void handle_text(seriousness s, const std::string &str); + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_ERROR_HANDLER_H */ diff --git a/gnuradio-runtime/include/gr_expj.h b/gnuradio-runtime/include/gnuradio/expj.h index 56291a0a6a..7556e17011 100644 --- a/gnuradio-runtime/include/gr_expj.h +++ b/gnuradio-runtime/include/gnuradio/expj.h @@ -22,15 +22,15 @@ #ifndef INCLUDED_GR_EXPJ_H #define INCLUDED_GR_EXPJ_H -#include <gr_runtime_api.h> -#include <gr_sincos.h> -#include <gr_types.h> +#include <gnuradio/api.h> +#include <gnuradio/sincos.h> +#include <gnuradio/types.h> static inline gr_complex gr_expj(float phase) { float t_imag, t_real; - gr_sincosf(phase, &t_imag, &t_real); + gr::sincosf(phase, &t_imag, &t_real); return gr_complex(t_real, t_imag); } diff --git a/gnuradio-runtime/include/gnuradio/feval.h b/gnuradio-runtime/include/gnuradio/feval.h new file mode 100644 index 0000000000..40e3ad9a55 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/feval.h @@ -0,0 +1,187 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_FEVAL_H +#define INCLUDED_GR_FEVAL_H + +#include <gnuradio/api.h> +#include <gnuradio/gr_complex.h> +#include <pmt/pmt.h> + +namespace gr { + + /*! + * \brief base class for evaluating a function: double -> double + * \ingroup misc + * + * This class is designed to be subclassed in Python or C++ and is + * callable from both places. It uses SWIG's "director" feature to + * implement the magic. + * + * It's slow. Don't use it in a performance critical path. + * + * Override eval to define the behavior. + * Use calleval to invoke eval (this kludge is required to allow a + * python specific "shim" to be inserted. + */ + class GR_RUNTIME_API feval_dd + { + protected: + /*! + * \brief override this to define the function + */ + virtual double eval(double x); + + public: + feval_dd() {} + virtual ~feval_dd(); + + virtual double calleval(double x); // invoke "eval" + }; + + /*! + * \brief base class for evaluating a function: complex -> complex + * \ingroup misc + * + * This class is designed to be subclassed in Python or C++ and is + * callable from both places. It uses SWIG's "director" feature to + * implement the magic. + * + * It's slow. Don't use it in a performance critical path. + * + * Override eval to define the behavior. + * Use calleval to invoke eval (this kludge is required to allow a + * python specific "shim" to be inserted. + */ + class GR_RUNTIME_API feval_cc + { + protected: + /*! + * \brief override this to define the function + */ + virtual gr_complex eval(gr_complex x); + + public: + feval_cc() {} + virtual ~feval_cc(); + + virtual gr_complex calleval(gr_complex x); // invoke "eval" + }; + + /*! + * \brief base class for evaluating a function: long -> long + * \ingroup misc + * + * This class is designed to be subclassed in Python or C++ and is + * callable from both places. It uses SWIG's "director" feature to + * implement the magic. + * + * It's slow. Don't use it in a performance critical path. + * + * Override eval to define the behavior. + * Use calleval to invoke eval (this kludge is required to allow a + * python specific "shim" to be inserted. + */ + class GR_RUNTIME_API feval_ll + { + protected: + /*! + * \brief override this to define the function + */ + virtual long eval(long x); + + public: + feval_ll() {} + virtual ~feval_ll(); + + virtual long calleval(long x); // invoke "eval" + }; + + /*! + * \brief base class for evaluating a function: void -> void + * \ingroup misc + * + * This class is designed to be subclassed in Python or C++ and is + * callable from both places. It uses SWIG's "director" feature to + * implement the magic. + * + * It's slow. Don't use it in a performance critical path. + * + * Override eval to define the behavior. + * Use calleval to invoke eval (this kludge is required to allow a + * python specific "shim" to be inserted. + */ + class GR_RUNTIME_API feval + { + protected: + /*! + * \brief override this to define the function + */ + virtual void eval(); + + public: + feval() {} + virtual ~feval(); + + virtual void calleval(); // invoke "eval" + }; + + /*! + * \brief base class for evaluating a function: pmt -> void + * \ingroup misc + * + * This class is designed to be subclassed in Python or C++ and is + * callable from both places. It uses SWIG's "director" feature to + * implement the magic. + * + * It's slow. Don't use it in a performance critical path. + * + * Override eval to define the behavior. + * Use calleval to invoke eval (this kludge is required to allow a + * python specific "shim" to be inserted. + */ + class GR_RUNTIME_API feval_p + { + protected: + /*! + * \brief override this to define the function + */ + virtual void eval(pmt::pmt_t x); + + public: + feval_p() {} + virtual ~feval_p(); + + virtual void calleval(pmt::pmt_t x); // invoke "eval" + }; + + /*! + * \brief trivial examples / test cases showing C++ calling Python code + */ + GR_RUNTIME_API double feval_dd_example(feval_dd *f, double x); + GR_RUNTIME_API gr_complex feval_cc_example(feval_cc *f, gr_complex x); + GR_RUNTIME_API long feval_ll_example(feval_ll *f, long x); + GR_RUNTIME_API void feval_example(feval *f); + +} /* namespace gr */ + +#endif /* INCLUDED_GR_FEVAL_H */ diff --git a/gnuradio-runtime/include/gnuradio/flowgraph.h b/gnuradio-runtime/include/gnuradio/flowgraph.h new file mode 100644 index 0000000000..cfa451f11b --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/flowgraph.h @@ -0,0 +1,256 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2007,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_RUNTIME_FLOWGRAPH_H +#define INCLUDED_GR_RUNTIME_FLOWGRAPH_H + +#include <gnuradio/api.h> +#include <gnuradio/basic_block.h> +#include <gnuradio/io_signature.h> +#include <iostream> + +namespace gr { + + /*! + * \brief Class representing a specific input or output graph endpoint + * \ingroup internal + */ + class GR_RUNTIME_API endpoint + { + private: + basic_block_sptr d_basic_block; + int d_port; + + public: + endpoint() : d_basic_block(), d_port(0) { } + endpoint(basic_block_sptr block, int port) { d_basic_block = block; d_port = port; } + basic_block_sptr block() const { return d_basic_block; } + int port() const { return d_port; } + + bool operator==(const endpoint &other) const; + }; + + inline bool endpoint::operator==(const endpoint &other) const + { + return (d_basic_block == other.d_basic_block && + d_port == other.d_port); + } + + class GR_RUNTIME_API msg_endpoint + { + private: + basic_block_sptr d_basic_block; + pmt::pmt_t d_port; + bool d_is_hier; + + public: + msg_endpoint() : d_basic_block(), d_port(pmt::PMT_NIL) { } + msg_endpoint(basic_block_sptr block, pmt::pmt_t port, bool is_hier=false) { + d_basic_block = block; d_port = port; d_is_hier = is_hier; + } + basic_block_sptr block() const { return d_basic_block; } + pmt::pmt_t port() const { return d_port; } + bool is_hier() const { return d_is_hier; } + void set_hier(bool h) { d_is_hier = h; } + + bool operator==(const msg_endpoint &other) const; + }; + + inline bool + msg_endpoint::operator==(const msg_endpoint &other) const + { + return (d_basic_block == other.d_basic_block && + pmt::equal(d_port, other.d_port)); + } + + // Hold vectors of gr::endpoint objects + typedef std::vector<endpoint> endpoint_vector_t; + typedef std::vector<endpoint>::iterator endpoint_viter_t; + + /*! + *\brief Class representing a connection between to graph endpoints + */ + class GR_RUNTIME_API edge + { + public: + edge() : d_src(), d_dst() { }; + edge(const endpoint &src, const endpoint &dst) + : d_src(src), d_dst(dst) { } + ~edge(); + + const endpoint &src() const { return d_src; } + const endpoint &dst() const { return d_dst; } + + private: + endpoint d_src; + endpoint d_dst; + }; + + // Hold vectors of gr::edge objects + typedef std::vector<edge> edge_vector_t; + typedef std::vector<edge>::iterator edge_viter_t; + + + /*! + *\brief Class representing a msg connection between to graph msg endpoints + */ + class GR_RUNTIME_API msg_edge + { + public: + msg_edge() : d_src(), d_dst() { }; + msg_edge(const msg_endpoint &src, const msg_endpoint &dst) + : d_src(src), d_dst(dst) { } + ~msg_edge() {} + + const msg_endpoint &src() const { return d_src; } + const msg_endpoint &dst() const { return d_dst; } + + private: + msg_endpoint d_src; + msg_endpoint d_dst; + }; + + // Hold vectors of gr::msg_edge objects + typedef std::vector<msg_edge> msg_edge_vector_t; + typedef std::vector<msg_edge>::iterator msg_edge_viter_t; + + // Create a shared pointer to a heap allocated flowgraph + // (types defined in runtime_types.h) + GR_RUNTIME_API flowgraph_sptr make_flowgraph(); + + /*! + * \brief Class representing a directed, acyclic graph of basic blocks + * \ingroup internal + */ + class GR_RUNTIME_API flowgraph + { + public: + friend GR_RUNTIME_API flowgraph_sptr make_flowgraph(); + + // Destruct an arbitrary flowgraph + ~flowgraph(); + + // Connect two endpoints + void connect(const endpoint &src, const endpoint &dst); + + // Disconnect two endpoints + void disconnect(const endpoint &src, const endpoint &dst); + + // Connect an output port to an input port (convenience) + void connect(basic_block_sptr src_block, int src_port, + basic_block_sptr dst_block, int dst_port); + + // Disconnect an input port from an output port (convenience) + void disconnect(basic_block_sptr src_block, int src_port, + basic_block_sptr dst_block, int dst_port); + + // Connect two msg endpoints + void connect(const msg_endpoint &src, const msg_endpoint &dst); + + // Disconnect two msg endpoints + void disconnect(const msg_endpoint &src, const msg_endpoint &dst); + + // Validate connectivity, raise exception if invalid + void validate(); + + // Clear existing flowgraph + void clear(); + + // Return vector of edges + const edge_vector_t &edges() const { return d_edges; } + + // Return vector of msg edges + const msg_edge_vector_t &msg_edges() const { return d_msg_edges; } + + // Return vector of connected blocks + basic_block_vector_t calc_used_blocks(); + + // Return toplogically sorted vector of blocks. All the sources come first. + basic_block_vector_t topological_sort(basic_block_vector_t &blocks); + + // Return vector of vectors of disjointly connected blocks, + // topologically sorted. + std::vector<basic_block_vector_t> partition(); + + protected: + basic_block_vector_t d_blocks; + edge_vector_t d_edges; + msg_edge_vector_t d_msg_edges; + + flowgraph(); + std::vector<int> calc_used_ports(basic_block_sptr block, bool check_inputs); + basic_block_vector_t calc_downstream_blocks(basic_block_sptr block, int port); + edge_vector_t calc_upstream_edges(basic_block_sptr block); + bool has_block_p(basic_block_sptr block); + edge calc_upstream_edge(basic_block_sptr block, int port); + + private: + void check_valid_port(gr::io_signature::sptr sig, int port); + void check_valid_port(const msg_endpoint &e); + void check_dst_not_used(const endpoint &dst); + void check_type_match(const endpoint &src, const endpoint &dst); + edge_vector_t calc_connections(basic_block_sptr block, bool check_inputs); // false=use outputs + void check_contiguity(basic_block_sptr block, const std::vector<int> &used_ports, bool check_inputs); + + basic_block_vector_t calc_downstream_blocks(basic_block_sptr block); + basic_block_vector_t calc_reachable_blocks(basic_block_sptr block, basic_block_vector_t &blocks); + void reachable_dfs_visit(basic_block_sptr block, basic_block_vector_t &blocks); + basic_block_vector_t calc_adjacent_blocks(basic_block_sptr block, basic_block_vector_t &blocks); + basic_block_vector_t sort_sources_first(basic_block_vector_t &blocks); + bool source_p(basic_block_sptr block); + void topological_dfs_visit(basic_block_sptr block, basic_block_vector_t &output); + }; + + // Convenience functions + inline + void flowgraph::connect(basic_block_sptr src_block, int src_port, + basic_block_sptr dst_block, int dst_port) + { + connect(endpoint(src_block, src_port), + endpoint(dst_block, dst_port)); + } + + inline + void flowgraph::disconnect(basic_block_sptr src_block, int src_port, + basic_block_sptr dst_block, int dst_port) + { + disconnect(endpoint(src_block, src_port), + endpoint(dst_block, dst_port)); + } + + inline std::ostream& + operator <<(std::ostream &os, const endpoint endp) + { + os << endp.block()->alias() << ":" << endp.port(); + return os; + } + + inline std::ostream& + operator <<(std::ostream &os, const edge edge) + { + os << edge.src() << "->" << edge.dst(); + return os; + } + +} /* namespace gr */ + +#endif /* INCLUDED_GR_RUNTIME_FLOWGRAPH_H */ diff --git a/gnuradio-runtime/include/gnuradio/fxpt.h b/gnuradio-runtime/include/gnuradio/fxpt.h new file mode 100644 index 0000000000..6143acafeb --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/fxpt.h @@ -0,0 +1,108 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_FXPT_H +#define INCLUDED_GR_FXPT_H + +#include <gnuradio/api.h> +#include <gnuradio/types.h> + +namespace gr { + + /*! + * \brief fixed point sine and cosine and friends. + * \ingroup misc + * + * fixed pt radians + * --------- -------- + * -2**31 -pi + * 0 0 + * 2**31-1 pi - epsilon + */ + class GR_RUNTIME_API fxpt + { + static const int WORDBITS = 32; + static const int NBITS = 10; + static const float s_sine_table[1 << NBITS][2]; + static const float PI; + static const float TWO_TO_THE_31; + + public: + static gr_int32 + float_to_fixed(float x) + { + // Fold x into -PI to PI. + int d = (int)floor(x/2/PI+0.5); + x -= d*2*PI; + // And convert to an integer. + return (gr_int32) ((float) x * TWO_TO_THE_31 / PI); + } + + static float + fixed_to_float (gr_int32 x) + { + return x * (PI / TWO_TO_THE_31); + } + + /*! + * \brief Given a fixed point angle x, return float sine (x) + */ + static float + sin(gr_int32 x) + { + gr_uint32 ux = x; + int index = ux >> (WORDBITS - NBITS); + return s_sine_table[index][0] * (ux >> 1) + s_sine_table[index][1]; + } + + /* + * \brief Given a fixed point angle x, return float cosine (x) + */ + static float + cos (gr_int32 x) + { + gr_uint32 ux = x + 0x40000000; + int index = ux >> (WORDBITS - NBITS); + return s_sine_table[index][0] * (ux >> 1) + s_sine_table[index][1]; + } + + /* + * \brief Given a fixedpoint angle x, return float cos(x) and sin (x) + */ + static void sincos(gr_int32 x, float *s, float *c) + { + gr_uint32 ux = x; + int sin_index = ux >> (WORDBITS - NBITS); + *s = s_sine_table[sin_index][0] * (ux >> 1) + s_sine_table[sin_index][1]; + + ux = x + 0x40000000; + int cos_index = ux >> (WORDBITS - NBITS); + *c = s_sine_table[cos_index][0] * (ux >> 1) + s_sine_table[cos_index][1]; + + return; + } + + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_FXPT_H */ diff --git a/gnuradio-runtime/include/gnuradio/fxpt_nco.h b/gnuradio-runtime/include/gnuradio/fxpt_nco.h new file mode 100644 index 0000000000..33a176d9b4 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/fxpt_nco.h @@ -0,0 +1,160 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2004,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_FXPT_NCO_H +#define INCLUDED_GR_FXPT_NCO_H + +#include <gnuradio/api.h> +#include <gnuradio/fxpt.h> +#include <gnuradio/gr_complex.h> +#include <stdint.h> + +namespace gr { + + /*! + * \brief Numerically Controlled Oscillator (NCO) + * \ingroup misc + */ + class /*GR_RUNTIME_API*/ fxpt_nco + { + uint32_t d_phase; + int32_t d_phase_inc; + + public: + fxpt_nco() : d_phase(0), d_phase_inc(0) {} + + ~fxpt_nco() {} + + // radians + void set_phase(float angle) { + d_phase = gr::fxpt::float_to_fixed(angle); + } + + void adjust_phase(float delta_phase) { + d_phase += gr::fxpt::float_to_fixed(delta_phase); + } + + // angle_rate is in radians / step + void set_freq(float angle_rate){ + d_phase_inc = gr::fxpt::float_to_fixed(angle_rate); + } + + // angle_rate is a delta in radians / step + void adjust_freq(float delta_angle_rate) + { + d_phase_inc += gr::fxpt::float_to_fixed(delta_angle_rate); + } + + // increment current phase angle + + void step() + { + d_phase += d_phase_inc; + } + + void step(int n) + { + d_phase += d_phase_inc * n; + } + + // units are radians / step + float get_phase() const { return gr::fxpt::fixed_to_float(d_phase); } + float get_freq() const { return gr::fxpt::fixed_to_float(d_phase_inc); } + + // compute sin and cos for current phase angle + void sincos(float *sinx, float *cosx) const + { + *sinx = gr::fxpt::sin(d_phase); + *cosx = gr::fxpt::cos(d_phase); + } + + // compute cos and sin for a block of phase angles + void sincos(gr_complex *output, int noutput_items, double ampl=1.0) + { + for(int i = 0; i < noutput_items; i++) { + output[i] = gr_complex(gr::fxpt::cos(d_phase) * ampl, gr::fxpt::sin(d_phase) * ampl); + step(); + } + } + + // compute sin for a block of phase angles + void sin(float *output, int noutput_items, double ampl=1.0) + { + for(int i = 0; i < noutput_items; i++) { + output[i] = (float)(gr::fxpt::sin(d_phase) * ampl); + step(); + } + } + + // compute cos for a block of phase angles + void cos(float *output, int noutput_items, double ampl=1.0) + { + for(int i = 0; i < noutput_items; i++) { + output[i] = (float)(gr::fxpt::cos(d_phase) * ampl); + step (); + } + } + + // compute sin for a block of phase angles + void sin(short *output, int noutput_items, double ampl=1.0) + { + for(int i = 0; i < noutput_items; i++) { + output[i] = (short)(gr::fxpt::sin(d_phase) * ampl); + step(); + } + } + + // compute cos for a block of phase angles + void cos(short *output, int noutput_items, double ampl=1.0) + { + for(int i = 0; i < noutput_items; i++) { + output[i] = (short)(gr::fxpt::cos(d_phase) * ampl); + step(); + } + } + + // compute sin for a block of phase angles + void sin(int *output, int noutput_items, double ampl=1.0) + { + for(int i = 0; i < noutput_items; i++) { + output[i] = (int)(gr::fxpt::sin(d_phase) * ampl); + step(); + } + } + + // compute cos for a block of phase angles + void cos(int *output, int noutput_items, double ampl=1.0) + { + for(int i = 0; i < noutput_items; i++) { + output[i] = (int)(gr::fxpt::cos(d_phase) * ampl); + step(); + } + } + + // compute cos or sin for current phase angle + float cos() const { return gr::fxpt::cos(d_phase); } + float sin() const { return gr::fxpt::sin(d_phase); } + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_FXPT_NCO_H */ diff --git a/gnuradio-runtime/include/gnuradio/fxpt_vco.h b/gnuradio-runtime/include/gnuradio/fxpt_vco.h new file mode 100644 index 0000000000..77d58677ce --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/fxpt_vco.h @@ -0,0 +1,80 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2004,2005,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_FXPT_VCO_H +#define INCLUDED_GR_FXPT_VCO_H + +#include <gnuradio/api.h> +#include <gnuradio/fxpt.h> +#include <gnuradio/gr_complex.h> + +namespace gr { + + /*! + * \brief Voltage Controlled Oscillator (VCO) + * \ingroup misc + */ + class /*GR_RUNTIME_API*/ fxpt_vco { + gr_int32 d_phase; + + public: + fxpt_vco () : d_phase(0) {} + + ~fxpt_vco() {} + + // radians + void set_phase(float angle) { + d_phase = fxpt::float_to_fixed(angle); + } + + void adjust_phase(float delta_phase) { + d_phase += fxpt::float_to_fixed(delta_phase); + } + + float get_phase() const { + return fxpt::fixed_to_float(d_phase); + } + + // compute sin and cos for current phase angle + void sincos(float *sinx, float *cosx) const + { + *sinx = fxpt::sin(d_phase); + *cosx = fxpt::cos(d_phase); + } + + // compute a block at a time + void cos(float *output, const float *input, int noutput_items, float k, float ampl = 1.0) + { + for(int i = 0; i < noutput_items; i++) { + output[i] = (float)(fxpt::cos(d_phase) * ampl); + adjust_phase(input[i] * k); + } + } + + // compute cos or sin for current phase angle + float cos() const { return fxpt::cos(d_phase); } + float sin() const { return fxpt::sin(d_phase); } + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_FXPT_VCO_H */ diff --git a/gnuradio-runtime/include/gr_complex.h b/gnuradio-runtime/include/gnuradio/gr_complex.h index 6166c0b142..bd94c0f0f8 100644 --- a/gnuradio-runtime/include/gr_complex.h +++ b/gnuradio-runtime/include/gnuradio/gr_complex.h @@ -19,6 +19,7 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ + #ifndef INCLUDED_GR_COMPLEX_H #define INCLUDED_GR_COMPLEX_H diff --git a/gnuradio-runtime/include/gnuradio/hier_block2.h b/gnuradio-runtime/include/gnuradio/hier_block2.h new file mode 100644 index 0000000000..ff09f9139d --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/hier_block2.h @@ -0,0 +1,221 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006-2009,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_RUNTIME_HIER_BLOCK2_H +#define INCLUDED_GR_RUNTIME_HIER_BLOCK2_H + +#include <gnuradio/api.h> +#include <gnuradio/basic_block.h> + +namespace gr { + + /*! + * \brief public constructor for hier_block2 + */ + GR_RUNTIME_API hier_block2_sptr + make_hier_block2(const std::string &name, + gr::io_signature::sptr input_signature, + gr::io_signature::sptr output_signature); + + class hier_block2_detail; + + /*! + * \brief Hierarchical container class for gr::block's and gr::hier_block2's + * \ingroup container_blk + * \ingroup base_blk + */ + class GR_RUNTIME_API hier_block2 : public basic_block + { + private: + friend class hier_block2_detail; + friend GR_RUNTIME_API hier_block2_sptr + make_hier_block2(const std::string &name, + gr::io_signature::sptr input_signature, + gr::io_signature::sptr output_signature); + + /*! + * \brief Private implementation details of gr::hier_block2 + */ + hier_block2_detail *d_detail; + + protected: + hier_block2(void) {} // allows pure virtual interface sub-classes + hier_block2(const std::string &name, + gr::io_signature::sptr input_signature, + gr::io_signature::sptr output_signature); + + public: + virtual ~hier_block2(); + + /*! + * \brief typedef for object returned from self(). + * + * This type is only guaranteed to be passable to connect and + * disconnect. No other assumptions should be made about it. + */ + typedef basic_block_sptr opaque_self; + + /*! + * \brief Return an object, representing the current block, which + * can be passed to connect. + * + * The returned object may only be used as an argument to connect + * or disconnect. Any other use of self() results in unspecified + * (erroneous) behavior. + */ + opaque_self self(); + + /*! + * \brief Add a stand-alone (possibly hierarchical) block to + * internal graph + * + * This adds a gr-block or hierarchical block to the internal + * graph without wiring it to anything else. + */ + void connect(basic_block_sptr block); + + /*! + * \brief Add gr-blocks or hierarchical blocks to internal graph + * and wire together + * + * This adds (if not done earlier by another connect) a pair of + * gr-blocks or hierarchical blocks to the internal flowgraph, and + * wires the specified output port to the specified input port. + */ + void connect(basic_block_sptr src, int src_port, + basic_block_sptr dst, int dst_port); + + /*! + * \brief Add gr-blocks or hierarchical blocks to internal graph + * and wire together + * + * This adds (if not done earlier by another connect) a pair of + * gr-blocks or hierarchical blocks to the internal message port + * subscription + */ + void msg_connect(basic_block_sptr src, pmt::pmt_t srcport, + basic_block_sptr dst, pmt::pmt_t dstport); + void msg_connect(basic_block_sptr src, std::string srcport, + basic_block_sptr dst, std::string dstport); + void msg_disconnect(basic_block_sptr src, pmt::pmt_t srcport, + basic_block_sptr dst, pmt::pmt_t dstport); + void msg_disconnect(basic_block_sptr src, std::string srcport, + basic_block_sptr dst, std::string dstport); + + /*! + * \brief Remove a gr-block or hierarchical block from the + * internal flowgraph. + * + * This removes a gr-block or hierarchical block from the internal + * flowgraph, disconnecting it from other blocks as needed. + */ + void disconnect(basic_block_sptr block); + + /*! + * \brief Disconnect a pair of gr-blocks or hierarchical blocks in + * internal flowgraph. + * + * This disconnects the specified input port from the specified + * output port of a pair of gr-blocks or hierarchical blocks. + */ + void disconnect(basic_block_sptr src, int src_port, + basic_block_sptr dst, int dst_port); + + /*! + * \brief Disconnect all connections in the internal flowgraph. + * + * This call removes all output port to input port connections in + * the internal flowgraph. + */ + void disconnect_all(); + + /*! + * Lock a flowgraph in preparation for reconfiguration. When an + * equal number of calls to lock() and unlock() have occurred, the + * flowgraph will be reconfigured. + * + * N.B. lock() and unlock() may not be called from a flowgraph + * thread (E.g., gr::block::work method) or deadlock will occur + * when reconfiguration happens. + */ + virtual void lock(); + + /*! + * Unlock a flowgraph in preparation for reconfiguration. When an + * equal number of calls to lock() and unlock() have occurred, the + * flowgraph will be reconfigured. + * + * N.B. lock() and unlock() may not be called from a flowgraph + * thread (E.g., gr::block::work method) or deadlock will occur + * when reconfiguration happens. + */ + virtual void unlock(); + + // This is a public method for ease of code organization, but should be + // ignored by the user. + flat_flowgraph_sptr flatten() const; + + hier_block2_sptr to_hier_block2(); // Needed for Python type coercion + + bool has_msg_port(pmt::pmt_t which_port) { + return message_port_is_hier(which_port) || basic_block::has_msg_port(which_port); + } + + bool message_port_is_hier(pmt::pmt_t port_id) { + return message_port_is_hier_in(port_id) || message_port_is_hier_out(port_id); + } + + bool message_port_is_hier_in(pmt::pmt_t port_id) { + return pmt::list_has(hier_message_ports_in, port_id); + } + + bool message_port_is_hier_out(pmt::pmt_t port_id) { + return pmt::list_has(hier_message_ports_out, port_id); + } + + pmt::pmt_t hier_message_ports_in; + pmt::pmt_t hier_message_ports_out; + + void message_port_register_hier_in(pmt::pmt_t port_id) { + if(pmt::list_has(hier_message_ports_in, port_id)) + throw std::invalid_argument("hier msg in port by this name already registered"); + if(msg_queue.find(port_id) != msg_queue.end()) + throw std::invalid_argument("block already has a primitive input port by this name"); + hier_message_ports_in = pmt::list_add(hier_message_ports_in, port_id); + } + + void message_port_register_hier_out(pmt::pmt_t port_id) { + if(pmt::list_has(hier_message_ports_out, port_id)) + throw std::invalid_argument("hier msg out port by this name already registered"); + if(pmt::dict_has_key(message_subscribers, port_id)) + throw std::invalid_argument("block already has a primitive output port by this name"); + hier_message_ports_out = pmt::list_add(hier_message_ports_out, port_id); + } + }; + + inline hier_block2_sptr cast_to_hier_block2_sptr(basic_block_sptr block) { + return boost::dynamic_pointer_cast<hier_block2, basic_block>(block); + } + +} /* namespace gr */ + +#endif /* INCLUDED_GR_RUNTIME_HIER_BLOCK2_H */ diff --git a/gnuradio-runtime/include/high_res_timer.h b/gnuradio-runtime/include/gnuradio/high_res_timer.h index fc7b007c61..fc7b007c61 100644 --- a/gnuradio-runtime/include/high_res_timer.h +++ b/gnuradio-runtime/include/gnuradio/high_res_timer.h diff --git a/gnuradio-runtime/include/ice_application_base.h b/gnuradio-runtime/include/gnuradio/ice_application_base.h index 64ec615e5c..1cb60fbf96 100644 --- a/gnuradio-runtime/include/ice_application_base.h +++ b/gnuradio-runtime/include/gnuradio/ice_application_base.h @@ -28,8 +28,8 @@ #include <sys/time.h> #endif -#include <gr_runtime_api.h> -#include <gr_prefs.h> +#include <gnuradio/api.h> +#include <gnuradio/prefs.h> #include <Ice/Ice.h> #include <boost/thread.hpp> #include <boost/thread/mutex.hpp> @@ -119,7 +119,7 @@ void ice_application_base<TserverBase, TserverClass>::starticeexample() char* argv[2]; argv[0] = (char*)""; - std::string conffile = gr_prefs::singleton()->get_string("ControlPort", "config", ""); + std::string conffile = gr::prefs::singleton()->get_string("ControlPort", "config", ""); if(conffile.size() > 0) { std::stringstream iceconf; diff --git a/gnuradio-runtime/include/ice_server_template.h b/gnuradio-runtime/include/gnuradio/ice_server_template.h index ff411b7f41..45c1756a48 100644 --- a/gnuradio-runtime/include/ice_server_template.h +++ b/gnuradio-runtime/include/gnuradio/ice_server_template.h @@ -23,8 +23,8 @@ #ifndef ICE_SERVER_TEMPLATE_H #define ICE_SERVER_TEMPLATE_H -#include <rpcserver_ice.h> -#include <ice_application_base.h> +#include <gnuradio/rpcserver_ice.h> +#include <gnuradio/ice_application_base.h> #include <iostream> template<typename TserverBase, typename TserverClass, typename TImplClass, typename TIceClass> diff --git a/gnuradio-runtime/include/gnuradio/io_signature.h b/gnuradio-runtime/include/gnuradio/io_signature.h new file mode 100644 index 0000000000..973f93cd98 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/io_signature.h @@ -0,0 +1,111 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_IO_SIGNATURE_H +#define INCLUDED_IO_SIGNATURE_H + +#include <gnuradio/api.h> +#include <gnuradio/runtime_types.h> + +namespace gr { + + /*! + * \brief i/o signature for input and output ports. + * \brief misc + */ + class GR_RUNTIME_API io_signature + { + int d_min_streams; + int d_max_streams; + std::vector<int> d_sizeof_stream_item; + + io_signature(int min_streams, int max_streams, + const std::vector<int> &sizeof_stream_items); + + public: + typedef boost::shared_ptr<io_signature> sptr; + + static const int IO_INFINITE = -1; + + ~io_signature(); + + /*! + * \brief Create an i/o signature + * + * \ingroup internal + * \param min_streams specify minimum number of streams (>= 0) + * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite) + * \param sizeof_stream_item specify the size of the items in each stream + */ + static sptr make(int min_streams, int max_streams, + int sizeof_stream_item); + + /*! + * \brief Create an i/o signature + * + * \param min_streams specify minimum number of streams (>= 0) + * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite) + * \param sizeof_stream_item1 specify the size of the items in the first stream + * \param sizeof_stream_item2 specify the size of the items in the second and subsequent streams + */ + static sptr make2(int min_streams, int max_streams, + int sizeof_stream_item1, + int sizeof_stream_item2); + + /*! + * \brief Create an i/o signature + * + * \param min_streams specify minimum number of streams (>= 0) + * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite) + * \param sizeof_stream_item1 specify the size of the items in the first stream + * \param sizeof_stream_item2 specify the size of the items in the second stream + * \param sizeof_stream_item3 specify the size of the items in the third and subsequent streams + */ + static sptr make3(int min_streams, int max_streams, + int sizeof_stream_item1, + int sizeof_stream_item2, + int sizeof_stream_item3); + + /*! + * \brief Create an i/o signature + * + * \param min_streams specify minimum number of streams (>= 0) + * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite) + * \param sizeof_stream_items specify the size of the items in the streams + * + * If there are more streams than there are entries in + * sizeof_stream_items, the value of the last entry in + * sizeof_stream_items is used for the missing values. + * sizeof_stream_items must contain at least 1 entry. + */ + static sptr makev(int min_streams, int max_streams, + const std::vector<int> &sizeof_stream_items); + + int min_streams() const { return d_min_streams; } + int max_streams() const { return d_max_streams; } + int sizeof_stream_item(int index) const; + std::vector<int> sizeof_stream_items() const; + }; + +} /* namespace gr */ + +#endif /* INCLUDED_IO_SIGNATURE_H */ diff --git a/gnuradio-runtime/include/gnuradio/logger.h.in b/gnuradio-runtime/include/gnuradio/logger.h.in new file mode 100644 index 0000000000..87f3611d9c --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/logger.h.in @@ -0,0 +1,747 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012-2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/******************************************************************************* +* Author: Mark Plett +* Description: +* The gr::logger module wraps the log4cpp library for logging in gnuradio +*******************************************************************************/ + +#ifndef INCLUDED_GR_LOGGER_H +#define INCLUDED_GR_LOGGER_H + +/*! +* \ingroup logging +* \brief GNU Radio logging wrapper for log4cpp library (C++ port of log4j) +* +*/ + +#ifndef ENABLE_GR_LOG +#cmakedefine ENABLE_GR_LOG +#endif +#ifndef HAVE_LOG4CPP +#cmakedefine HAVE_LOG4CPP +#endif + +#include <gnuradio/api.h> +#include <assert.h> +#include <iostream> +#include <time.h> +#include <boost/filesystem.hpp> +#include <boost/thread.hpp> +#include <pmt/pmt.h> + +#ifdef ENABLE_GR_LOG + +// We have three configurations... first logging to stdout/stderr +#ifndef HAVE_LOG4CPP + +namespace gr { + //#warning GR logging Enabled and using std::cout + typedef std::string logger_ptr; +} /* namespace gr */ + +#define GR_LOG_DECLARE_LOGPTR(logger) +#define GR_LOG_ASSIGN_LOGPTR(logger,name) +#define GR_CONFIG_LOGGER(config) +#define GR_CONFIG_AND_WATCH_LOGGER(config,period) +#define GR_LOG_GETLOGGER(logger, name) +#define GR_SET_LEVEL(name, level) +#define GR_LOG_SET_LEVEL(logger, level) +#define GR_GET_LEVEL(name, level) +#define GR_LOG_GET_LEVEL(logger, level) +#define GR_ADD_APPENDER(name,appender) +#define GR_LOG_ADD_APPENDER(logger,appender) +#define GR_ADD_CONSOLE_APPENDER(logger,target,pattern) +#define GR_LOG_ADD_CONSOLE_APPENDER(logger,target,pattern) +#define GR_ADD_FILE_APPENDER(name,filename,append,pattern) +#define GR_LOG_ADD_FILE_APPENDER(logger,filename,append,pattern) +#define GR_ADD_ROLLINGFILE_APPENDER(name,filename,filesize,bkup_index,append,mode,pattern) +#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger,filename,filesize,bkup_index,append,mode,pattern) +#define GR_GET_LOGGER_NAMES(names) +#define GR_RESET_CONFIGURATION() +#define GR_DEBUG(name, msg) std::cout<<"DEBUG: "<<msg<<std::endl +#define GR_INFO(name, msg) std::cout<<"INFO: "<<msg<<std::endl +#define GR_NOTICE(name, msg) std::cout<<"NOTICE: "<<msg<<std::endl +#define GR_WARN(name, msg) std::cerr<<"WARN: "<<msg<<std::endl +#define GR_ERROR(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl +#define GR_ALERT(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl +#define GR_CRIT(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl +#define GR_FATAL(name, msg) std::cerr<<"FATAL: "<<msg<<std::endl +#define GR_EMERG(name, msg) std::cerr<<"EMERG: "<<msg<<std::endl +#define GR_ERRORIF(name, cond, msg) {if((cond)) std::cerr<<"ERROR: "<<msg<<std::endl;} +#define GR_ASSERT(name, cond, msg) {if(!(cond)) std::cerr<<"FATAL: "<<msg<<std::endl; assert(cond);} +#define GR_LOG_DEBUG(logger, msg) std::cout<<"DEBUG: "<<msg<<std::endl +#define GR_LOG_INFO(logger, msg) std::cout<<"INFO: "<<msg<<std::endl +#define GR_LOG_NOTICE(logger, msg) std::cout<<"NOTICE: "<<msg<<std::endl +#define GR_LOG_WARN(logger, msg) std::cerr<<"WARN: "<<msg<<std::endl +#define GR_LOG_ERROR(logger, msg) std::cerr<<"ERROR: "<<msg<<std::endl +#define GR_LOG_ALERT(logger, msg) std::cerr<<"ALERT: "<<msg<<std::endl +#define GR_LOG_CRIT(logger, msg) std::cerr<<"CRIT: "<<msg<<std::endl +#define GR_LOG_FATAL(logger, msg) std::cerr<<"FATAL: "<<msg<<std::endl +#define GR_LOG_EMERG(logger, msg) std::cerr<<"EMERG: "<<msg<<std::endl +#define GR_LOG_ERRORIF(logger, cond, msg) { \ + if((cond)) std::cerr<<"ERROR: "<<msg<<std::endl;} +#define GR_LOG_ASSERT(logger, cond, msg) { \ + if(!(cond)) {std::cerr<<"FATAL: "<<msg<<std::endl; assert(cond);};} + + +#else /* HAVE_LOG4CPP */ + +// Second configuration...logging to log4cpp +#include <log4cpp/Category.hh> +#include <log4cpp/PropertyConfigurator.hh> +#include <log4cpp/FileAppender.hh> +#include <log4cpp/RollingFileAppender.hh> +#include <log4cpp/OstreamAppender.hh> +#include <log4cpp/PatternLayout.hh> + +namespace gr { + + /*! + * \brief GR_LOG macros + * \ingroup logging + * + * These macros wrap the standard LOG4CPP_LEVEL macros. The availablie macros + * are: + * LOG_DEBUG + * LOG_INFO + * LOG_WARN + * LOG_TRACE + * LOG_ERROR + * LOG_ALERT + * LOG_CRIT + * LOG_FATAL + * LOG_EMERG + */ + typedef log4cpp::Category* logger_ptr; + +} /* namespace gr */ + + + /* Macros for Programmatic Configuration */ +#define GR_LOG_DECLARE_LOGPTR(logger) \ + gr::logger_ptr logger; + +#define GR_LOG_ASSIGN_LOGPTR(logger,name) \ + logger = gr::logger_get_logger(name); + +#define GR_CONFIG_LOGGER(config) \ + gr::logger_config::load_config(config) + +#define GR_CONFIG_AND_WATCH_LOGGER(config,period) \ + gr::logger_config::load_config(config,period) + +#define GR_LOG_GETLOGGER(logger, name) \ + gr::logger_ptr logger = gr::logger_get_logger(name); + +#define GR_SET_LEVEL(name, level) { \ + gr::logger_ptr logger = gr::logger_get_logger(name); \ + gr::logger_set_level(logger,level);} + +#define GR_LOG_SET_LEVEL(logger, level) \ + gr::logger_set_level(logger, level); + +#define GR_GET_LEVEL(name, level) { \ + gr::logger_ptr logger = gr::logger_get_logger(name); \ + gr::logger_get_level(logger,level);} + +#define GR_LOG_GET_LEVEL(logger, level) \ + gr::logger_get_level(logger,level); + +#define GR_ADD_APPENDER(name, appender) { \ + gr::logger_ptr logger = gr::logger_get_logger(name); \ + gr::logger_add_appender(logger,appender);} + +#define GR_LOG_ADD_APPENDER(logger, appender) { \ + gr::logger_add_appender(logger, appender);} + +#define GR_ADD_CONSOLE_APPENDER(name, target, pattern) { \ + gr::logger_ptr logger = gr::logger_get_logger(name); \ + gr::logger_add_console_appender(logger,target,pattern);} + +#define GR_LOG_ADD_CONSOLE_APPENDER(logger, target, pattern) { \ + gr::logger_add_console_appender(logger,target,pattern);} + +#define GR_ADD_FILE_APPENDER(name, filename, append, pattern) { \ + gr::logger_ptr logger = gr::logger_get_logger(name); \ + gr::logger_add_file_appender(logger,filename,append,pattern);} + +#define GR_LOG_ADD_FILE_APPENDER(logger, filename, append, pattern) { \ + gr::logger_add_file_appender(logger,filename,append,pattern);} + +#define GR_ADD_ROLLINGFILE_APPENDER(name, filename, filesize, bkup_index, append, mode, pattern) { \ + gr::logger_ptr logger = gr::logger_get_logger(name); \ + gr::logger_add_rollingfile_appender(logger,filename,filesize,bkup_index,append,mode,pattern);} + +#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger, filename, filesize, bkup_index, append, mode, pattern) { \ + gr::logger_add_rollingfile_appender(logger,filename,filesize,bkup_index,append,mode,pattern);} + +#define GR_GET_LOGGER_NAMES(names) { \ + names = gr::logger_get_logger_names();} + +#define GR_RESET_CONFIGURATION() \ + gr::logger_config::reset_config(); + + /* Logger name referenced macros */ +#define GR_DEBUG(name, msg) { \ + gr::logger_ptr logger = gr::logger_get_logger(name); \ + *logger<< log4cpp::Priority::DEBUG << msg << log4cpp::eol;} + +#define GR_INFO(name, msg) { \ + gr::logger_ptr logger = gr::logger_get_logger(name); \ + *logger<< log4cpp::Priority::INFO << msg << log4cpp::eol;} + +#define GR_NOTICE(name, msg) { \ + gr::logger_ptr logger = gr::logger_get_logger(name); \ + *logger << log4cpp::Priority::NOTICE << msg;} + +#define GR_WARN(name, msg) { \ + gr::logger_ptr logger = gr::logger_get_logger(name); \ + *logger<< log4cpp::Priority::WARN << msg << log4cpp::eol;} + +#define GR_ERROR(name, msg) { \ + gr::logger_ptr logger = gr::logger_get_logger(name); \ + *logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;} + +#define GR_CRIT(name, msg) { \ + gr::logger_ptr logger = gr::logger_get_logger(name); \ + *logger<< log4cpp::Priority::CRIT << msg << log4cpp::eol;} + +#define GR_ALERT(name, msg) { \ + gr::logger_ptr logger = gr::logger_get_logger(name); \ + *logger<< log4cpp::Priority::ALERT << msg << log4cpp::eol;} + +#define GR_FATAL(name, msg) { \ + gr::logger_ptr logger = gr::logger_get_logger(name); \ + *logger<< log4cpp::Priority::FATAL << msg << log4cpp::eol;} + +#define GR_EMERG(name, msg) { \ + gr::logger_ptr logger = gr::logger_get_logger(name); \ + *logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol;} + +#define GR_ERRORIF(name, cond, msg) { \ + if((cond)) { \ + gr::logger_ptr logger = gr::logger_get_logger(name); \ + *logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;} \ + } + +#define GR_ASSERT(name, cond, msg) { \ + if(!(cond)) { \ + gr::logger_ptr logger = gr::logger_get_logger(name); \ + *logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol;} \ + assert(0); \ + } + + /* LoggerPtr Referenced Macros */ +#define GR_LOG_DEBUG(logger, msg) { \ + *logger << log4cpp::Priority::DEBUG << msg << log4cpp::eol;} + +#define GR_LOG_INFO(logger, msg) { \ + *logger << log4cpp::Priority::INFO << msg << log4cpp::eol;} + +#define GR_LOG_NOTICE(logger, msg) { \ + *logger << log4cpp::Priority::NOTICE << msg << log4cpp::eol;} + +#define GR_LOG_WARN(logger, msg) { \ + *logger << log4cpp::Priority::WARN << msg << log4cpp::eol;} + +#define GR_LOG_ERROR(logger, msg) { \ + *logger << log4cpp::Priority::ERROR << msg << log4cpp::eol;} + +#define GR_LOG_CRIT(logger, msg) { \ + *logger << log4cpp::Priority::CRIT << msg << log4cpp::eol;} + +#define GR_LOG_ALERT(logger, msg) { \ + *logger << log4cpp::Priority::ALERT << msg << log4cpp::eol;} + +#define GR_LOG_FATAL(logger, msg) { \ + *logger << log4cpp::Priority::FATAL << msg << log4cpp::eol;} + +#define GR_LOG_EMERG(logger, msg) { \ + *logger << log4cpp::Priority::EMERG << msg << log4cpp::eol;} + +#define GR_LOG_ERRORIF(logger,cond, msg) { \ + if((cond)) { \ + *logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;} \ + } + +#define GR_LOG_ASSERT(logger, cond, msg) { \ + if(!(cond)) { \ + *logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol; \ + assert(0);} \ + } + +namespace gr { + + /*! + * \brief Class to control configuration of logger. + * This is a singleton that cna launch a thread to wathc a config file for changes + * \ingroup logging + */ + class logger_config + { + private: + /*! \brief filename of logger config file */ + std::string filename; + /*! \brief Period (seconds) over which watcher thread checks config file for changes */ + unsigned int watch_period; + /*! \brief Pointer to watch thread for config file changes */ + boost::thread *watch_thread; + + /*! \brief Watcher thread method + * /param filename Name of configuration file + * /param watch_period Seconds between checks for changes in config file + */ + static void watch_file(std::string filename,unsigned int watch_period); + + static bool logger_configured; + + logger_config()/*: + rpc_get_filename("logger_config", "filename", &logger_config::get_filename4rpc, + pmt::mp(""), pmt::mp(""), pmt::mp(""), + "", "filename", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP), + rpc_get_watchperiod("logger_config", "watch_period", &logger_config::get_watchperiod4rpc, + pmt::mp(0), pmt::mp(32768), pmt::mp(0), + "", "watch_period", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP), + rpc_get_config("logger_config", "config", &logger_config::get_config4rpc, + pmt::mp(""), pmt::mp(""), pmt::mp(""), + "", "filename", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP), + rpc_set_config("logger_config","config", &logger_config::set_config4rpc, + pmt::mp(""), pmt::mp(""), pmt::mp(""), + "", "filename", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP) + */ + { + } //!< Constructor + + /* + rpcbasic_register_get<logger_config,std::string> rpc_get_filename; + rpcbasic_register_get<logger_config,int> rpc_get_watchperiod; + rpcbasic_register_get<logger_config,std::string> rpc_get_config; + rpcbasic_register_set<logger_config,std::string> rpc_set_config; + */ + + logger_config(logger_config const&); //!<Copy constructor + void operator=(logger_config const&); //!<Assignment Operator + + std::string get_filename4rpc() { + return filename; + } + int get_watchperiod4rpc(){return watch_period;}; + + std::string get_config4rpc() { + return filename; + } + + void set_config4rpc(std::string set) { + printf("Set string was:%s\n", set.c_str()); + } + + /*! \brief destrcutor stops watch thread before exits */ + ~logger_config() { + stop_watch(); + } + + /*! \brief Instance getter for singleton. Only used by class. */ + static logger_config& get_instance(void); + + public: + /*! \brief Getter for config filename */ + static std::string get_filename(); + /*! \brief Getter for watch period */ + static unsigned int get_watch_period(); + /*! \brief Method to load configuration + * /param filename Name of configuration file + * /param watch_period Seconds between checks for changes in config file + */ + static void load_config(std::string filename,unsigned int watch_period=0); + /*! \brief Method to stop watcher thread */ + static void stop_watch(); + /*! \brief method to reset logger configuration */ + static void reset_config(void); + }; + + /*! + * \brief Retrieve a pointer to a logger by name + * + * Retrives a logger pointer + * \p name. + * + * \param name Name of the logger for which a pointer is requested + */ + GR_RUNTIME_API logger_ptr logger_get_logger(std::string name); + + /*! + * \brief Load logger's configuration file. + * + * Initialize the GNU Radio logger by loading the configuration file + * \p config_filename. + * + * \param config_filename The configuration file. Set to "" for the + * basic logger that outputs to the console. + */ + GR_RUNTIME_API bool logger_load_config(const std::string &config_filename=""); + + /*! + * \brief Reset logger's configuration file. + * + * Remove all appenders from loggers + */ + GR_RUNTIME_API void logger_reset_config(void); + + /*! + * \brief Set the logger's output level. + * + * Sets the level of the logger. This takes a string that is + * translated to the standard levels and can be (case insensitive): + * + * \li off , notset + * \li debug + * \li info + * \li notice + * \li warn + * \li error + * \li crit + * \li alert + * \li fatal + * \li emerg + * + * \param logger the logger to set the level of. + * \param level string to set the level to. + */ + GR_RUNTIME_API void logger_set_level(logger_ptr logger, + const std::string &level); + + /*! + * \brief Set the logger's output level. + * + * Sets the level of the logger. This takes the actual Log4cpp::Priority + * data type, which can be: + * + * \li log4cpp::Priority::NOTSET + * \li log4cpp::Priority::DEBUG + * \li log4cpp::Priority::INFO + * \li log4cpp::Priority::NOTICE + * \li log4cpp::Priority::WARN + * \li log4cpp::Priority::ERROR + * \li log4cpp::Priority::CRIT + * \li log4cpp::Priority::ALERT + * \li log4cpp::Priority::FATAL + * \li log4cpp::Priority::EMERG + * + * \param logger the logger to set the level of. + * \param level new logger level of type Log4cpp::Priority + */ + GR_RUNTIME_API void logger_set_level(logger_ptr logger, + log4cpp::Priority::Value level); + + /*! + * \brief Get the logger's output level. + * + * Gets the level of the logger. This returns a string that + * corresponds to the standard levels and can be (case insensitive): + * + * \li notset + * \li debug + * \li info + * \li notice + * \li warn + * \li error + * \li crit + * \li alert + * \li fatal + * \li emerg + * + * \param logger the logger to get the level of. + * \param level string to get the level into. + */ + GR_RUNTIME_API void logger_get_level(logger_ptr logger, std::string &level); + + /*! + * \brief Get the logger's output level. + * + * Gets the level of the logger. This returns the actual Log4cpp::Level + * data type, which can be: + * + * \li log4cpp::Priority::NOTSET + * \li log4cpp::Priority::DEBUG + * \li log4cpp::Priority::INFO + * \li log4cpp::Priority::NOTICE + * \li log4cpp::Priority::WARN + * \li log4cpp::Priority::ERROR + * \li log4cpp::Priority::CRIT + * \li log4cpp::Priority::ALERT + * \li log4cpp::Priority::FATAL + * \li log4cpp::Priority::EMERG + * + * \param logger the logger to get the level of. + * \param level of the logger. + */ + GR_RUNTIME_API void logger_get_level(logger_ptr logger, + log4cpp::Priority::Value &level); + + /*! + * \brief Add console appender to a given logger + * + * Add console appender to a given logger + * + * \param logger Logger to which appender will be added + * \param target Std target to write 'cout' or 'cerr' (default is cout) + * \param pattern Formating pattern for log messages + */ + GR_RUNTIME_API void logger_add_appender(logger_ptr logger, + std::string appender); + + /*! + * \brief Add console appender to a given logger + * + * Add console appender to a given logger + * + * \param logger Logger to which appender will be added + * \param target Std target to write 'cout' or 'cerr' (default is cout) + * \param pattern Formating pattern for log messages + */ + GR_RUNTIME_API void logger_add_console_appender(logger_ptr logger, + std::string target, + std::string pattern); + + /*! + * \brief Add file appender to a given logger + * + * Add file appender to a given logger + * + * \param logger Logger to which appender will be added + * \param filename File to which log will be written + * \param append Overwrite or append to log file + * \param pattern Formating pattern for log messages + */ + GR_RUNTIME_API void logger_add_file_appender(logger_ptr logger, + std::string filename, + bool append, std::string pattern); + + /*! + * \brief Add rolling file appender to a given logger + * + * Add rolling file appender to a given logger + * + * \param logger Logger to which appender will be added + * \param filename File to which log will be written + * \param filesize Sizez of files to write + * \param bkup_index Number of files to write + * \param append Overwrite or append to log file + * \param mode Permissions to set on log file + * \param pattern Formating pattern for log messages + */ + GR_RUNTIME_API void logger_add_rollingfile_appender(logger_ptr logger, std::string filename, + size_t filesize, int bkup_index, bool append, + mode_t mode,std::string pattern); + + /*! + * \brief Add rolling file appender to a given logger + * + * Add rolling file appender to a given logger + * + * \return vector of string names of loggers + */ + GR_RUNTIME_API std::vector<std::string> logger_get_logger_names(void); + +} /* namespace gr */ + +#endif /* HAVE_LOG4CPP */ + + // If Logger disable do nothing +#else /* ENABLE_GR_LOG */ + +namespace gr { + typedef void* logger_ptr; +} /* namespace gr */ + +#define GR_LOG_DECLARE_LOGPTR(logger) +#define GR_LOG_ASSIGN_LOGPTR(logger,name) +#define GR_CONFIG_LOGGER(config) +#define GR_CONFIG_AND_WATCH_LOGGER(config,period) +#define GR_LOG_GETLOGGER(logger, name) +#define GR_SET_LEVEL(name, level) +#define GR_LOG_SET_LEVEL(logger, level) +#define GR_GET_LEVEL(name, level) +#define GR_LOG_GET_LEVEL(logger, level) +#define GR_ADD_APPENDER(name,appender) +#define GR_LOG_ADD_APPENDER(logger,appender) +#define GR_ADD_CONSOLE_APPENDER(logger,target,pattern) +#define GR_LOG_ADD_CONSOLE_APPENDER(logger,target,pattern) +#define GR_ADD_FILE_APPENDER(name,filename,append,pattern) +#define GR_LOG_ADD_FILE_APPENDER(logger,filename,append,pattern) +#define GR_ADD_ROLLINGFILE_APPENDER(name,filename,filesize,bkup_index,append,mode,pattern) +#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger,filename,filesize,bkup_index,append,mode,pattern) +#define GR_GET_LOGGER_NAMES(names) +#define GR_RESET_CONFIGURATION() +#define GR_DEBUG(name, msg) +#define GR_INFO(name, msg) +#define GR_NOTICE(name, msg) +#define GR_WARN(name, msg) +#define GR_ERROR(name, msg) +#define GR_ALERT(name, msg) +#define GR_CRIT(name, msg) +#define GR_FATAL(name, msg) +#define GR_EMERG(name, msg) +#define GR_ERRORIF(name, cond, msg) +#define GR_ASSERT(name, cond, msg) +#define GR_LOG_DEBUG(logger, msg) +#define GR_LOG_INFO(logger, msg) +#define GR_LOG_NOTICE(logger, msg) +#define GR_LOG_WARN(logger, msg) +#define GR_LOG_ERROR(logger, msg) +#define GR_LOG_ALERT(logger, msg) +#define GR_LOG_CRIT(logger, msg) +#define GR_LOG_FATAL(logger, msg) +#define GR_LOG_EMERG(logger, msg) +#define GR_LOG_ERRORIF(logger, cond, msg) +#define GR_LOG_ASSERT(logger, cond, msg) + +#endif /* ENABLE_GR_LOG */ + +namespace gr { + + // Even if logger is disabled we'll need for methods below to exist in python. + // The macros these call will be disabled if ENABLE_GR_LOG is undefined + + /********************* Start Classes and Methods for Python ******************/ + /*! + * \brief Logger class for referencing loggers in python. Not + * needed in C++ (use macros) Wraps and manipulates loggers for + * python as python has no macros + * \ingroup logging + * + */ + class logger + { + private: + /*! \brief logger pointer to logger associated wiith this wrapper class */ + logger_ptr d_logger; + public: + /*! + * \brief contructor Provide name of logger to associate with this class + * \param logger_name Name of logger associated with class + */ + logger(std::string logger_name) { + GR_LOG_ASSIGN_LOGPTR(d_logger,logger_name); + }; + + /*! \brief Destructor */ + ~logger(){;} + + // Wrappers for logging macros + /*! \brief inline function, wrapper to set the logger level */ + void set_level(std::string level){GR_LOG_SET_LEVEL(d_logger,level);} + + /*! \brief inline function, wrapper to get the logger level */ + void get_level(std::string &level){GR_LOG_GET_LEVEL(d_logger,level);} + + /*! \brief inline function, wrapper for LOG4CPP_DEBUG for DEBUG message */ + void debug(std::string msg){GR_LOG_DEBUG(d_logger,msg);}; + + /*! \brief inline function, wrapper for LOG4CPP_INFO for INFO message */ + void info(std::string msg){GR_LOG_INFO(d_logger,msg);} + + /*! \brief inline function, wrapper for NOTICE message */ + void notice(std::string msg){GR_LOG_NOTICE(d_logger,msg);} + + /*! \brief inline function, wrapper for LOG4CPP_WARN for WARN message */ + void warn(std::string msg){GR_LOG_WARN(d_logger,msg);} + + /*! \brief inline function, wrapper for LOG4CPP_ERROR for ERROR message */ + void error(std::string msg){GR_LOG_ERROR(d_logger,msg);} + + /*! \brief inline function, wrapper for NOTICE message */ + void crit(std::string msg){GR_LOG_CRIT(d_logger,msg);} + + /*! \brief inline function, wrapper for ALERT message */ + void alert(std::string msg){GR_LOG_ALERT(d_logger,msg);} + + /*! \brief inline function, wrapper for FATAL message */ + void fatal(std::string msg){GR_LOG_FATAL(d_logger,msg);} + + /*! \brief inline function, wrapper for EMERG message */ + void emerg(std::string msg){GR_LOG_EMERG(d_logger,msg);} + + /*! \brief inline function, wrapper for LOG4CPP_ASSERT for conditional ERROR message */ + void errorIF(bool cond,std::string msg){GR_LOG_ERRORIF(d_logger,cond,msg);} + + /*! \brief inline function, wrapper for LOG4CPP_ASSERT for conditional ERROR message */ + void log_assert(bool cond,std::string msg){GR_LOG_ASSERT(d_logger,cond,msg);} + + /*! \brief inline function, Method to add appender to logger by + name (define appender in conf file) */ + void add_appender(std::string appender) { + GR_LOG_ADD_APPENDER(d_logger, appender); + } + + /*! \brief inline function, Method to add console appender to logger */ + void add_console_appender(std::string target,std::string pattern) { + GR_LOG_ADD_CONSOLE_APPENDER(d_logger, target, pattern); + } + + /*! \brief inline function, Method to add file appender to logger */ + void add_file_appender(std::string filename, bool append, std::string pattern) { + GR_LOG_ADD_FILE_APPENDER(d_logger, filename, append, pattern); + } + + /*! \brief inline function, Method to add rolling file appender to logger */ + void add_rollingfile_appender(std::string filename, size_t filesize, + int bkup_index, bool append, mode_t mode, + std::string pattern) { + GR_LOG_ADD_ROLLINGFILE_APPENDER(d_logger,filename,filesize, + bkup_index,append,mode,pattern); + } + }; + +} /* namespace gr */ + +/**************** Start Configuration Class and Methods for Python ************/ +/*! + * \brief Function to call configuration macro from python. + * Note: Configuration is only updated if filename or watch_period has changed. + * \param config_filename Name of configuration file + * \param watch_period Seconds to wait between checking for changes in conf file. + * Watch_period defaults to 0 in which case the file is not watched for changes + */ +GR_RUNTIME_API void gr_logger_config(const std::string config_filename, + unsigned int watch_period = 0); + +/*! + * \brief Function to return logger names to python + * \return Vector of name strings + * + */ +GR_RUNTIME_API std::vector<std::string> gr_logger_get_logger_names(void); + +/*! + * \brief Function to reset logger configuration from python + * + */ +GR_RUNTIME_API void gr_logger_reset_config(void); + +#endif /* INCLUDED_GR_LOGGER_H */ diff --git a/gnuradio-runtime/include/gnuradio/math.h b/gnuradio-runtime/include/gnuradio/math.h new file mode 100644 index 0000000000..ec4cfb014f --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/math.h @@ -0,0 +1,226 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2005,2008,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* + * mathematical odds and ends. + */ + +#ifndef _GR_MATH_H_ +#define _GR_MATH_H_ + +#include <gnuradio/api.h> +#include <gnuradio/gr_complex.h> + +namespace gr { + + static inline bool + is_power_of_2(long x) + { + return x != 0 && (x & (x-1)) == 0; + } + + /*! + * \brief Fast arc tangent using table lookup and linear interpolation + * \ingroup misc + * + * \param y component of input vector + * \param x component of input vector + * \returns float angle angle of vector (x, y) in radians + * + * This function calculates the angle of the vector (x,y) based on a + * table lookup and linear interpolation. The table uses a 256 point + * table covering -45 to +45 degrees and uses symetry to determine + * the final angle value in the range of -180 to 180 degrees. Note + * that this function uses the small angle approximation for values + * close to zero. This routine calculates the arc tangent with an + * average error of +/- 0.045 degrees. + */ + GR_RUNTIME_API float fast_atan2f(float y, float x); + + static inline float + fast_atan2f(gr_complex z) + { + return fast_atan2f(z.imag(), z.real()); + } + + /* This bounds x by +/- clip without a branch */ + static inline float + branchless_clip(float x, float clip) + { + float x1 = fabsf(x+clip); + float x2 = fabsf(x-clip); + x1 -= x2; + return 0.5*x1; + } + + static inline float + clip(float x, float clip) + { + float y = x; + if(x > clip) + y = clip; + else if(x < -clip) + y = -clip; + return y; + } + + // Slicer Functions + static inline unsigned int + binary_slicer(float x) + { + if(x >= 0) + return 1; + else + return 0; + } + + static inline unsigned int + quad_45deg_slicer(float r, float i) + { + unsigned int ret = 0; + if((r >= 0) && (i >= 0)) + ret = 0; + else if((r < 0) && (i >= 0)) + ret = 1; + else if((r < 0) && (i < 0)) + ret = 2; + else + ret = 3; + return ret; + } + + static inline unsigned int + quad_0deg_slicer(float r, float i) + { + unsigned int ret = 0; + if(fabsf(r) > fabsf(i)) { + if(r > 0) + ret = 0; + else + ret = 2; + } + else { + if(i > 0) + ret = 1; + else + ret = 3; + } + + return ret; + } + + static inline unsigned int + quad_45deg_slicer(gr_complex x) + { + return quad_45deg_slicer(x.real(), x.imag()); + } + + static inline unsigned int + quad_0deg_slicer(gr_complex x) + { + return quad_0deg_slicer(x.real(), x.imag()); + } + + // Branchless Slicer Functions + static inline unsigned int + branchless_binary_slicer(float x) + { + return (x >= 0); + } + + static inline unsigned int + branchless_quad_0deg_slicer(float r, float i) + { + unsigned int ret = 0; + ret = (fabsf(r) > fabsf(i)) * (((r < 0) << 0x1)); // either 0 (00) or 2 (10) + ret |= (fabsf(i) > fabsf(r)) * (((i < 0) << 0x1) | 0x1); // either 1 (01) or 3 (11) + + return ret; + } + + static inline unsigned int + branchless_quad_0deg_slicer(gr_complex x) + { + return branchless_quad_0deg_slicer(x.real(), x.imag()); + } + + static inline unsigned int + branchless_quad_45deg_slicer(float r, float i) + { + char ret = (r <= 0); + ret |= ((i <= 0) << 1); + return (ret ^ ((ret & 0x2) >> 0x1)); + } + + static inline unsigned int + branchless_quad_45deg_slicer(gr_complex x) + { + return branchless_quad_45deg_slicer(x.real(), x.imag()); + } + + /*! + * \param x any value + * \param pow2 must be a power of 2 + * \returns \p x rounded down to a multiple of \p pow2. + */ + static inline size_t + p2_round_down(size_t x, size_t pow2) + { + return x & -pow2; + } + + /*! + * \param x any value + * \param pow2 must be a power of 2 + * \returns \p x rounded up to a multiple of \p pow2. + */ + static inline size_t + p2_round_up(size_t x, size_t pow2) + { + return p2_round_down(x + pow2 - 1, pow2); + } + + /*! + * \param x any value + * \param pow2 must be a power of 2 + * \returns \p x modulo \p pow2. + */ + static inline size_t + p2_modulo(size_t x, size_t pow2) + { + return x & (pow2 - 1); + } + + /*! + * \param x any value + * \param pow2 must be a power of 2 + * \returns \p pow2 - (\p x modulo \p pow2). + */ + static inline size_t + p2_modulo_neg(size_t x, size_t pow2) + { + return pow2 - p2_modulo(x, pow2); + } + +} /* namespace gr */ + +#endif /* _GR_MATH_H_ */ diff --git a/gnuradio-runtime/include/gnuradio/message.h b/gnuradio-runtime/include/gnuradio/message.h new file mode 100644 index 0000000000..0fda2d9c8c --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/message.h @@ -0,0 +1,91 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_MESSAGE_H +#define INCLUDED_GR_MESSAGE_H + +#include <gnuradio/api.h> +#include <gnuradio/types.h> +#include <string> + +namespace gr { + + /*! + * \brief Message class. + * + * \ingroup misc + * The ideas and method names for adjustable message length were + * lifted from the click modular router "Packet" class. + */ + class GR_RUNTIME_API message + { + public: + typedef boost::shared_ptr<message> sptr; + + private: + sptr d_next; // link field for msg queue + long d_type; // type of the message + double d_arg1; // optional arg1 + double d_arg2; // optional arg2 + + unsigned char *d_buf_start; // start of allocated buffer + unsigned char *d_msg_start; // where the msg starts + unsigned char *d_msg_end; // one beyond end of msg + unsigned char *d_buf_end; // one beyond end of allocated buffer + + message(long type, double arg1, double arg2, size_t length); + + friend class msg_queue; + + unsigned char *buf_data() const { return d_buf_start; } + size_t buf_len() const { return d_buf_end - d_buf_start; } + + public: + /*! + * \brief public constructor for message + */ + static sptr make(long type = 0, double arg1 = 0, double arg2 = 0, size_t length = 0); + + static sptr make_from_string(const std::string s, long type = 0, + double arg1 = 0, double arg2 = 0); + + + ~message(); + + long type() const { return d_type; } + double arg1() const { return d_arg1; } + double arg2() const { return d_arg2; } + + void set_type(long type) { d_type = type; } + void set_arg1(double arg1) { d_arg1 = arg1; } + void set_arg2(double arg2) { d_arg2 = arg2; } + + unsigned char *msg() const { return d_msg_start; } + size_t length() const { return d_msg_end - d_msg_start; } + std::string to_string() const; + }; + + GR_RUNTIME_API long message_ncurrently_allocated(); + +} /* namespace gr */ + +#endif /* INCLUDED_GR_MESSAGE_H */ diff --git a/gnuradio-runtime/include/messages/CMakeLists.txt b/gnuradio-runtime/include/gnuradio/messages/CMakeLists.txt index f79f2bd24f..f79f2bd24f 100644 --- a/gnuradio-runtime/include/messages/CMakeLists.txt +++ b/gnuradio-runtime/include/gnuradio/messages/CMakeLists.txt diff --git a/gnuradio-runtime/include/messages/msg_accepter.h b/gnuradio-runtime/include/gnuradio/messages/msg_accepter.h index d3e89daf74..cd87b21dec 100644 --- a/gnuradio-runtime/include/messages/msg_accepter.h +++ b/gnuradio-runtime/include/gnuradio/messages/msg_accepter.h @@ -22,7 +22,7 @@ #ifndef INCLUDED_MSG_ACCEPTER_H #define INCLUDED_MSG_ACCEPTER_H -#include <gr_runtime_api.h> +#include <gnuradio/api.h> #include <pmt/pmt.h> #include <boost/shared_ptr.hpp> diff --git a/gnuradio-runtime/include/messages/msg_accepter_msgq.h b/gnuradio-runtime/include/gnuradio/messages/msg_accepter_msgq.h index 5d1d4f7e27..ba699b8ee6 100644 --- a/gnuradio-runtime/include/messages/msg_accepter_msgq.h +++ b/gnuradio-runtime/include/gnuradio/messages/msg_accepter_msgq.h @@ -22,9 +22,9 @@ #ifndef INCLUDED_MSG_ACCEPTER_MSGQ_H #define INCLUDED_MSG_ACCEPTER_MSGQ_H -#include <gr_runtime_api.h> -#include <messages/msg_accepter.h> -#include <messages/msg_queue.h> +#include <gnuradio/api.h> +#include <gnuradio/messages/msg_accepter.h> +#include <gnuradio/messages/msg_queue.h> namespace gr { namespace messages { diff --git a/gnuradio-runtime/include/messages/msg_passing.h b/gnuradio-runtime/include/gnuradio/messages/msg_passing.h index 3bfccda339..6ad6c40b08 100644 --- a/gnuradio-runtime/include/messages/msg_passing.h +++ b/gnuradio-runtime/include/gnuradio/messages/msg_passing.h @@ -26,9 +26,9 @@ * \brief Include this header to use the message passing features */ -#include <gr_runtime_api.h> +#include <gnuradio/api.h> #include <pmt/pmt.h> -#include <messages/msg_accepter.h> +#include <gnuradio/messages/msg_accepter.h> namespace gr { namespace messages { diff --git a/gnuradio-runtime/include/messages/msg_producer.h b/gnuradio-runtime/include/gnuradio/messages/msg_producer.h index 3167fc442a..758320fc6a 100644 --- a/gnuradio-runtime/include/messages/msg_producer.h +++ b/gnuradio-runtime/include/gnuradio/messages/msg_producer.h @@ -22,7 +22,7 @@ #ifndef INCLUDED_MSG_PRODUCER_H #define INCLUDED_MSG_PRODUCER_H -#include <gr_runtime_api.h> +#include <gnuradio/api.h> #include <pmt/pmt.h> #include <boost/shared_ptr.hpp> diff --git a/gnuradio-runtime/include/messages/msg_queue.h b/gnuradio-runtime/include/gnuradio/messages/msg_queue.h index 81531afcdf..dfe1ca97be 100644 --- a/gnuradio-runtime/include/messages/msg_queue.h +++ b/gnuradio-runtime/include/gnuradio/messages/msg_queue.h @@ -23,8 +23,8 @@ #ifndef INCLUDED_MSG_QUEUE_H #define INCLUDED_MSG_QUEUE_H -#include <gr_runtime_api.h> -#include <thread/thread.h> +#include <gnuradio/api.h> +#include <gnuradio/thread/thread.h> #include <pmt/pmt.h> #include <deque> @@ -47,7 +47,7 @@ namespace gr { gr::thread::condition_variable d_not_full; unsigned int d_limit; // max # of messages in queue. 0 -> unbounded - std::deque<pmt::pmt_t> d_msgs; + std::deque<pmt::pmt_t> d_msgs; public: msg_queue(unsigned int limit); @@ -69,7 +69,7 @@ namespace gr { /*! * \brief If there's a message in the q, delete it and return it. - * If no message is available, return pmt_t(). + * If no message is available, return pmt::pmt_t(). */ pmt::pmt_t delete_head_nowait(); diff --git a/gnuradio-runtime/include/gr_misc.h b/gnuradio-runtime/include/gnuradio/misc.h index 182ae87de6..290e39b490 100644 --- a/gnuradio-runtime/include/gr_misc.h +++ b/gnuradio-runtime/include/gnuradio/misc.h @@ -23,8 +23,8 @@ #ifndef INCLUDED_GR_MISC_H #define INCLUDED_GR_MISC_H -#include <gr_runtime_api.h> -#include <gr_types.h> +#include <gnuradio/api.h> +#include <gnuradio/types.h> GR_RUNTIME_API unsigned int gr_rounduppow2(unsigned int n); diff --git a/gnuradio-runtime/include/gr_msg_accepter.h b/gnuradio-runtime/include/gnuradio/msg_accepter.h index e7feac4686..1f60a9e555 100644 --- a/gnuradio-runtime/include/gr_msg_accepter.h +++ b/gnuradio-runtime/include/gnuradio/msg_accepter.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2009 Free Software Foundation, Inc. + * Copyright 2009,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -19,25 +19,28 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef INCLUDED_GR_MSG_ACCEPTER_H -#define INCLUDED_GR_MSG_ACCEPTER_H +#ifndef INCLUDED_GR_RUNTIME_MSG_ACCEPTER_H +#define INCLUDED_GR_RUNTIME_MSG_ACCEPTER_H -#include <gr_runtime_api.h> -#include <messages/msg_accepter.h> +#include <gnuradio/api.h> +#include <gnuradio/messages/msg_accepter.h> #include <pmt/pmt.h> -/*! - * \brief Accepts messages and inserts them into a message queue, then notifies - * subclass gr_basic_block there is a message pending. - */ -class GR_RUNTIME_API gr_msg_accepter : public gr::messages::msg_accepter -{ -public: - gr_msg_accepter(); - ~gr_msg_accepter(); +namespace gr { + + /*! + * \brief Accepts messages and inserts them into a message queue, + * then notifies subclass gr::basic_block there is a message pending. + */ + class GR_RUNTIME_API msg_accepter : public gr::messages::msg_accepter + { + public: + msg_accepter(); + ~msg_accepter(); - void post(pmt::pmt_t which_port, pmt::pmt_t msg); + void post(pmt::pmt_t which_port, pmt::pmt_t msg); + }; -}; +} /* namespace gr */ -#endif /* INCLUDED_GR_MSG_ACCEPTER_H */ +#endif /* INCLUDED_GR_RUNTIME_MSG_ACCEPTER_H */ diff --git a/gnuradio-runtime/include/gr_msg_handler.h b/gnuradio-runtime/include/gnuradio/msg_handler.h index 06d583a38b..b37f215616 100644 --- a/gnuradio-runtime/include/gr_msg_handler.h +++ b/gnuradio-runtime/include/gnuradio/msg_handler.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2005,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -19,25 +19,31 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ + #ifndef INCLUDED_GR_MSG_HANDLER_H #define INCLUDED_GR_MSG_HANDLER_H -#include <gr_runtime_api.h> -#include <gr_message.h> +#include <gnuradio/api.h> +#include <gnuradio/message.h> -class gr_msg_handler; -typedef boost::shared_ptr<gr_msg_handler> gr_msg_handler_sptr; +namespace gr { -/*! - * \brief abstract class of message handlers - * \ingroup base - */ -class GR_RUNTIME_API gr_msg_handler { -public: - virtual ~gr_msg_handler (); + class msg_handler; + typedef boost::shared_ptr<msg_handler> msg_handler_sptr; + + /*! + * \brief abstract class of message handlers + * \ingroup base + */ + class GR_RUNTIME_API msg_handler + { + public: + virtual ~msg_handler(); + + //! handle \p msg + virtual void handle(message::sptr msg) = 0; + }; - //! handle \p msg - virtual void handle (gr_message_sptr msg) = 0; -}; +} /* namespace gr */ #endif /* INCLUDED_GR_MSG_HANDLER_H */ diff --git a/gnuradio-runtime/include/gnuradio/msg_queue.h b/gnuradio-runtime/include/gnuradio/msg_queue.h new file mode 100644 index 0000000000..3326cf9a7f --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/msg_queue.h @@ -0,0 +1,95 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2009 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_MSG_QUEUE_H +#define INCLUDED_GR_MSG_QUEUE_H + +#include <gnuradio/api.h> +#include <gnuradio/msg_handler.h> +#include <gnuradio/thread/thread.h> + +namespace gr { + + /*! + * \brief thread-safe message queue + * \ingroup misc + */ + class GR_RUNTIME_API msg_queue : public msg_handler + { + gr::thread::mutex d_mutex; + gr::thread::condition_variable d_not_empty; + gr::thread::condition_variable d_not_full; + message::sptr d_head; + message::sptr d_tail; + unsigned int d_count; // # of messages in queue. + unsigned int d_limit; // max # of messages in queue. 0 -> unbounded + + public: + typedef boost::shared_ptr<msg_queue> sptr; + + static sptr make(unsigned int limit=0); + + msg_queue(unsigned int limit); + ~msg_queue(); + + //! Generic msg_handler method: insert the message. + void handle(message::sptr msg) { insert_tail (msg); } + + /*! + * \brief Insert message at tail of queue. + * \param msg message + * + * Block if queue if full. + */ + void insert_tail(message::sptr msg); + + /*! + * \brief Delete message from head of queue and return it. + * Block if no message is available. + */ + message::sptr delete_head(); + + /*! + * \brief If there's a message in the q, delete it and return it. + * If no message is available, return 0. + */ + message::sptr delete_head_nowait(); + + //! Delete all messages from the queue + void flush(); + + //! is the queue empty? + bool empty_p() const { return d_count == 0; } + + //! is the queue full? + bool full_p() const { return d_limit != 0 && d_count >= d_limit; } + + //! return number of messages in queue + unsigned int count() const { return d_count; } + + //! return limit on number of message in queue. 0 -> unbounded + unsigned int limit() const { return d_limit; } + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_MSG_QUEUE_H */ diff --git a/gnuradio-runtime/include/gnuradio/nco.h b/gnuradio-runtime/include/gnuradio/nco.h new file mode 100644 index 0000000000..aff72068b9 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/nco.h @@ -0,0 +1,199 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _GR_NCO_H_ +#define _GR_NCO_H_ + +#include <gnuradio/sincos.h> +#include <gnuradio/gr_complex.h> +#include <vector> +#include <cmath> + +namespace gr { + + /*! + * \brief base class template for Numerically Controlled Oscillator (NCO) + * \ingroup misc + */ + template<class o_type, class i_type> + class nco + { + public: + nco() : phase(0), phase_inc(0) {} + + virtual ~nco() {} + + // radians + void set_phase(double angle) + { + phase = angle; + } + + void adjust_phase(double delta_phase) + { + phase += delta_phase; + } + + // angle_rate is in radians / step + void set_freq(double angle_rate) + { + phase_inc = angle_rate; + } + + // angle_rate is a delta in radians / step + void adjust_freq(double delta_angle_rate) + { + phase_inc += delta_angle_rate; + } + + // increment current phase angle + void step() + { + phase += phase_inc; + if(fabs(phase) > M_PI) { + while(phase > M_PI) + phase -= 2*M_PI; + + while(phase < -M_PI) + phase += 2*M_PI; + } + } + + void step(int n) + { + phase += phase_inc * n; + if(fabs(phase) > M_PI){ + while(phase > M_PI) + phase -= 2*M_PI; + + while(phase < -M_PI) + phase += 2*M_PI; + } + } + + // units are radians / step + double get_phase() const { return phase; } + double get_freq() const { return phase_inc; } + + // compute sin and cos for current phase angle + void sincos(float *sinx, float *cosx) const; + + // compute cos or sin for current phase angle + float cos() const { return std::cos(phase); } + float sin() const { return std::sin(phase); } + + // compute a block at a time + void sin(float *output, int noutput_items, double ampl = 1.0); + void cos(float *output, int noutput_items, double ampl = 1.0); + void sincos(gr_complex *output, int noutput_items, double ampl = 1.0); + void sin(short *output, int noutput_items, double ampl = 1.0); + void cos(short *output, int noutput_items, double ampl = 1.0); + void sin(int *output, int noutput_items, double ampl = 1.0); + void cos(int *output, int noutput_items, double ampl = 1.0); + + protected: + double phase; + double phase_inc; + }; + + template<class o_type, class i_type> + void + nco<o_type,i_type>::sincos(float *sinx, float *cosx) const + { + gr::sincosf(phase, sinx, cosx); + } + + template<class o_type, class i_type> + void + nco<o_type,i_type>::sin(float *output, int noutput_items, double ampl) + { + for(int i = 0; i < noutput_items; i++) { + output[i] = (float)(sin () * ampl); + step(); + } + } + + template<class o_type, class i_type> + void + nco<o_type,i_type>::cos(float *output, int noutput_items, double ampl) + { + for(int i = 0; i < noutput_items; i++) { + output[i] = (float)(cos() * ampl); + step(); + } + } + + template<class o_type, class i_type> + void + nco<o_type,i_type>::sin(short *output, int noutput_items, double ampl) + { + for(int i = 0; i < noutput_items; i++) { + output[i] = (short)(sin() * ampl); + step(); + } + } + + template<class o_type, class i_type> + void + nco<o_type,i_type>::cos(short *output, int noutput_items, double ampl) + { + for(int i = 0; i < noutput_items; i++) { + output[i] = (short)(cos() * ampl); + step(); + } + } + + template<class o_type, class i_type> + void + nco<o_type,i_type>::sin(int *output, int noutput_items, double ampl) + { + for(int i = 0; i < noutput_items; i++) { + output[i] = (int)(sin() * ampl); + step(); + } + } + + template<class o_type, class i_type> + void + nco<o_type,i_type>::cos(int *output, int noutput_items, double ampl) + { + for(int i = 0; i < noutput_items; i++) { + output[i] = (int)(cos() * ampl); + step(); + } + } + + template<class o_type, class i_type> + void + nco<o_type,i_type>::sincos(gr_complex *output, int noutput_items, double ampl) + { + for(int i = 0; i < noutput_items; i++) { + float cosx, sinx; + nco::sincos(&sinx, &cosx); + output[i] = gr_complex(cosx * ampl, sinx * ampl); + step(); + } + } + +} /* namespace gr */ + +#endif /* _NCO_H_ */ diff --git a/gnuradio-runtime/include/gnuradio/prefs.h b/gnuradio-runtime/include/gnuradio/prefs.h new file mode 100644 index 0000000000..b675c83491 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/prefs.h @@ -0,0 +1,152 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_PREFS_H +#define INCLUDED_GR_PREFS_H + +#include <gnuradio/api.h> +#include <string> +#include <map> +#include <gnuradio/thread/thread.h> + +namespace gr { + + typedef std::map< std::string, std::map<std::string, std::string> > config_map_t; + typedef std::map< std::string, std::map<std::string, std::string> >::iterator config_map_itr; + typedef std::map<std::string, std::string> config_map_elem_t; + typedef std::map<std::string, std::string>::iterator config_map_elem_itr; + + /*! + * \brief Base class for representing user preferences a la windows INI files. + * \ingroup misc + * + * The real implementation is in Python, and is accessable from C++ + * via the magic of SWIG directors. + */ + class GR_RUNTIME_API prefs + { + public: + static prefs *singleton(); + static void set_singleton(prefs *p); + + prefs(); + virtual ~prefs(); + + /*! + * \brief Returns the configuration options as a string. + */ + std::string to_string(); + + /*! + * \brief Saves the configuration settings to + * ${HOME}/.gnuradio/config.conf. + * + * WARNING: this will overwrite your current config.conf file. + */ + void save(); + + /*! + * \brief Does \p section exist? + */ + virtual bool has_section(const std::string §ion); + + /*! + * \brief Does \p option exist? + */ + virtual bool has_option(const std::string §ion, + const std::string &option); + + /*! + * \brief If option exists return associated value; else + * default_val. + */ + virtual const std::string get_string(const std::string §ion, + const std::string &option, + const std::string &default_val); + + /*! + * \brief Set or add a string \p option to \p section with value + * \p val. + */ + virtual void set_string(const std::string §ion, + const std::string &option, + const std::string &val); + + /*! + * \brief If option exists and value can be converted to bool, + * return it; else default_val. + */ + virtual bool get_bool(const std::string §ion, + const std::string &option, + bool default_val); + + /*! + * \brief Set or add a bool \p option to \p section with value \p val. + */ + virtual void set_bool(const std::string §ion, + const std::string &option, + bool val); + + /*! + * \brief If option exists and value can be converted to long, + * return it; else default_val. + */ + virtual long get_long(const std::string §ion, + const std::string &option, + long default_val); + + /*! + * \brief Set or add a long \p option to \p section with value \p val. + */ + virtual void set_long(const std::string §ion, + const std::string &option, + long val); + + /*! + * \brief If option exists and value can be converted to double, + * return it; else default_val. + */ + virtual double get_double(const std::string §ion, + const std::string &option, + double default_val); + + /*! + * \brief Set or add a double \p option to \p section with value \p val. + */ + virtual void set_double(const std::string §ion, + const std::string &option, + double val); + + protected: + virtual std::vector<std::string> _sys_prefs_filenames(); + virtual void _read_files(); + virtual void _convert_to_map(const std::string &conf); + virtual char * option_to_env(std::string section, std::string option); + + private: + gr::thread::mutex d_mutex; + config_map_t d_config_map; + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_PREFS_H */ diff --git a/gnuradio-runtime/include/gnuradio/py_feval.h b/gnuradio-runtime/include/gnuradio/py_feval.h new file mode 100644 index 0000000000..94def79ca1 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/py_feval.h @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <pmt/pmt.h> + +namespace gr { + + class py_feval_dd : public feval_dd + { + public: + double calleval(double x) + { + ensure_py_gil_state _lock; + return eval(x); + } + }; + + class py_feval_cc : public feval_cc + { + public: + gr_complex calleval(gr_complex x) + { + ensure_py_gil_state _lock; + return eval(x); + } + }; + + class py_feval_ll : public feval_ll + { + public: + long calleval(long x) + { + ensure_py_gil_state _lock; + return eval(x); + } + }; + + class py_feval : public feval + { + public: + void calleval() + { + ensure_py_gil_state _lock; + eval(); + } + }; + + class py_feval_p : public feval_p + { + public: + void calleval(pmt::pmt_t x) + { + ensure_py_gil_state _lock; + eval(x); + } + }; + +} /* namespace gr */ diff --git a/gnuradio-runtime/include/pycallback_object.h b/gnuradio-runtime/include/gnuradio/pycallback_object.h index 23782a42be..de35181c0b 100644 --- a/gnuradio-runtime/include/pycallback_object.h +++ b/gnuradio-runtime/include/gnuradio/pycallback_object.h @@ -21,9 +21,9 @@ */ #include <iostream> -#include <rpcregisterhelpers.h> -#include <ice_application_base.h> -#include <IcePy_Communicator.h> +#include <gnuradio/rpcregisterhelpers.h> +#include <gnuradio/ice_application_base.h> +#include <gnuradio/IcePy_Communicator.h> #include <pythread.h> #include <boost/format.hpp> diff --git a/gnuradio-runtime/include/random.h b/gnuradio-runtime/include/gnuradio/random.h index c643c3e422..e01fcb7be7 100644 --- a/gnuradio-runtime/include/random.h +++ b/gnuradio-runtime/include/gnuradio/random.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2003, 2008 Free Software Foundation, Inc. + * Copyright 2002 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,8 +20,11 @@ * Boston, MA 02110-1301, USA. */ -#ifndef _RANDOM_H_ -#define _RANDOM_H_ +#ifndef INCLUDED_GR_RANDOM_H +#define INCLUDED_GR_RANDOM_H + +#include <gnuradio/api.h> +#include <gnuradio/gr_complex.h> // While rand(3) specifies RAND_MAX, random(3) says that the output // ranges from 0 to 2^31-1 but does not specify a macro to denote @@ -35,4 +38,44 @@ static const int RANDOM_MAX = 2147483647; // 2^31-1 #include <stdlib.h> -#endif // _RANDOM_H_ +namespace gr { + + /*! + * \brief pseudo random number generator + * \ingroup math_blk + */ + class GR_RUNTIME_API random + { + protected: + static const int NTAB = 32; + long d_seed; + long d_iy; + long d_iv[NTAB]; + int d_iset; + float d_gset; + + public: + random(long seed=3021); + + void reseed(long seed); + + /*! + * \brief uniform random deviate in the range [0.0, 1.0) + */ + float ran1(); + + /*! + * \brief normally distributed deviate with zero mean and variance 1 + */ + float gasdev(); + + float laplacian(); + float impulse(float factor); + float rayleigh(); + gr_complex rayleigh_complex(); + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_RANDOM_H */ + diff --git a/gnuradio-runtime/include/gr_realtime.h b/gnuradio-runtime/include/gnuradio/realtime.h index a1e5af69c4..f3910f8c7d 100644 --- a/gnuradio-runtime/include/gr_realtime.h +++ b/gnuradio-runtime/include/gnuradio/realtime.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2006,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -23,15 +23,19 @@ #ifndef INCLUDED_GR_REALTIME_H #define INCLUDED_GR_REALTIME_H -#include <gr_runtime_api.h> -#include <realtime.h> +#include <gnuradio/api.h> +#include <gnuradio/realtime_impl.h> -typedef gr::rt_status_t gr_rt_status_t; +namespace gr { + + typedef impl::rt_status_t rt_status_t; -/*! - * \brief If possible, enable high-priority "real time" scheduling. - * \ingroup misc - */ -GR_RUNTIME_API gr_rt_status_t gr_enable_realtime_scheduling(); + /*! + * \brief If possible, enable high-priority "real time" scheduling. + * \ingroup misc + */ + GR_RUNTIME_API rt_status_t enable_realtime_scheduling(); + +} /* namespace gr */ #endif /* INCLUDED_GR_REALTIME_H */ diff --git a/gnuradio-runtime/include/gnuradio/realtime_impl.h b/gnuradio-runtime/include/gnuradio/realtime_impl.h new file mode 100644 index 0000000000..82845918ee --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/realtime_impl.h @@ -0,0 +1,97 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2008,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GNURADIO_REALTIME_H +#define INCLUDED_GNURADIO_REALTIME_H + +#include <gnuradio/api.h> +#include <stdexcept> + +/*! + * \brief System independent way to ask for realtime scheduling + * + * \sa sys_pri.h + */ +namespace gr { + namespace impl { + + typedef enum { + RT_OK = 0, + RT_NOT_IMPLEMENTED, + RT_NO_PRIVS, + RT_OTHER_ERROR + } rt_status_t; + + enum rt_sched_policy { + RT_SCHED_RR = 0, // round robin + RT_SCHED_FIFO = 1, // first in first out + }; + + /* + * Define the range for our virtual priorities (don't change + * these) + * + * Processes (or threads) with numerically higher priority values + * are scheduled before processes with numerically lower priority + * values. Thus, the value returned by rt_priority_max() will be + * greater than the value returned by rt_priority_min(). + */ + static inline int rt_priority_min() { return 0; } + static inline int rt_priority_max() { return 15; } + static inline int rt_priority_default() { return 1; } + + struct GR_RUNTIME_API rt_sched_param { + int priority; + rt_sched_policy policy; + + rt_sched_param() + : priority(rt_priority_default()), policy(RT_SCHED_RR){} + + rt_sched_param(int priority_, rt_sched_policy policy_ = RT_SCHED_RR) + { + if(priority_ < rt_priority_min() || priority_ > rt_priority_max()) + throw std::invalid_argument("rt_sched_param: priority out of range"); + + priority = priority_; + policy = policy_; + } + }; + + /*! + * \brief If possible, enable "realtime" scheduling. + * \ingroup misc + * + * In general, this means that the code will be scheduled before + * any non-realtime (normal) processes. Note that if your code + * contains an non-blocking infinite loop and you enable realtime + * scheduling, it's possible to hang the system. + */ + + // NOTE: If you change this, you need to change the code in + // gnuradio-core/src/lib/runtime/gr_realtime.i, see note there. + rt_status_t + GR_RUNTIME_API enable_realtime_scheduling(rt_sched_param = rt_sched_param()); + + } /* namespace impl */ +} /* namespace gr */ + +#endif /* INCLUDED_GNURADIO_REALTIME_H */ diff --git a/gnuradio-runtime/include/rpccallbackregister_base.h b/gnuradio-runtime/include/gnuradio/rpccallbackregister_base.h index f2cd1d8051..3b5b392ec3 100644 --- a/gnuradio-runtime/include/rpccallbackregister_base.h +++ b/gnuradio-runtime/include/gnuradio/rpccallbackregister_base.h @@ -23,8 +23,8 @@ #ifndef RPCCALLBACKREGISTER_BASE_H #define RPCCALLBACKREGISTER_BASE_H -#include <messages/msg_accepter.h> -#include <messages/msg_producer.h> +#include <gnuradio/messages/msg_accepter.h> +#include <gnuradio/messages/msg_producer.h> typedef uint32_t DisplayType; diff --git a/gnuradio-runtime/include/rpcmanager.h b/gnuradio-runtime/include/gnuradio/rpcmanager.h index 6a385c8998..12cf279406 100644 --- a/gnuradio-runtime/include/rpcmanager.h +++ b/gnuradio-runtime/include/gnuradio/rpcmanager.h @@ -23,9 +23,9 @@ #ifndef RPCMANAGER_H #define RPCMANAGER_H -#include <gr_runtime_api.h> -#include <rpcmanager_base.h> -#include <rpcserver_booter_aggregator.h> +#include <gnuradio/api.h> +#include <gnuradio/rpcmanager_base.h> +#include <gnuradio/rpcserver_booter_aggregator.h> #include <memory> #include <iostream> @@ -53,7 +53,7 @@ class GR_RUNTIME_API rpcmanager : public virtual rpcmanager_base static bool make_aggregator; static bool booter_registered; static bool aggregator_registered; - static void rpcserver_booter_base_sptr_dest( rpcserver_booter_base* b) {;} + static void rpcserver_booter_base_sptr_dest(rpcserver_booter_base* b) {;} static rpcserver_booter_base* boot; static std::auto_ptr<rpcserver_booter_aggregator> aggregator; }; diff --git a/gnuradio-runtime/include/rpcmanager_base.h b/gnuradio-runtime/include/gnuradio/rpcmanager_base.h index 60425c4a15..60425c4a15 100644 --- a/gnuradio-runtime/include/rpcmanager_base.h +++ b/gnuradio-runtime/include/gnuradio/rpcmanager_base.h diff --git a/gnuradio-runtime/include/rpcpmtconverters_ice.h b/gnuradio-runtime/include/gnuradio/rpcpmtconverters_ice.h index e592f4cdfb..e592f4cdfb 100644 --- a/gnuradio-runtime/include/rpcpmtconverters_ice.h +++ b/gnuradio-runtime/include/gnuradio/rpcpmtconverters_ice.h diff --git a/gnuradio-runtime/include/rpcregisterhelpers.h b/gnuradio-runtime/include/gnuradio/rpcregisterhelpers.h index b09aae9704..e405f4e1ea 100644 --- a/gnuradio-runtime/include/rpcregisterhelpers.h +++ b/gnuradio-runtime/include/gnuradio/rpcregisterhelpers.h @@ -26,11 +26,11 @@ #include <stdio.h> #include <sstream> #include <iostream> -#include <rpcserver_booter_base.h> -#include <rpcmanager.h> -#include <rpcserver_selector.h> -#include <rpcserver_base.h> -#include <gr_block_registry.h> +#include <gnuradio/rpcserver_booter_base.h> +#include <gnuradio/rpcmanager.h> +#include <gnuradio/rpcserver_selector.h> +#include <gnuradio/rpcserver_base.h> +#include <gnuradio/block_registry.h> // Base classes template<typename T, typename Tto> class rpcextractor_base @@ -325,7 +325,7 @@ typedef boost::shared_ptr<rpcbasic_base> rpcbasic_sptr; template<typename T, typename Tto> struct rpcbasic_register_set : public rpcbasic_base { - // Function used to add a 'set' RPC call using a gr_basic_block's alias. + // Function used to add a 'set' RPC call using a basic_block's alias. rpcbasic_register_set(const std::string& block_alias, const char* functionbase, void (T::*function)(Tto), @@ -426,7 +426,7 @@ template<typename T, typename Tfrom> class rpcbasic_register_get : public rpcbasic_base { public: - // Function used to add a 'set' RPC call using a gr_basic_block's alias. + // Function used to add a 'set' RPC call using a basic_block's alias. // primary constructor to allow for T get() functions rpcbasic_register_get(const std::string& block_alias, const char* functionbase, diff --git a/gnuradio-runtime/include/rpcserver_aggregator.h b/gnuradio-runtime/include/gnuradio/rpcserver_aggregator.h index 050d9bb1e5..cc19d7ff48 100644 --- a/gnuradio-runtime/include/rpcserver_aggregator.h +++ b/gnuradio-runtime/include/gnuradio/rpcserver_aggregator.h @@ -25,8 +25,8 @@ #include <vector> #include <string> -#include <rpcserver_base.h> -#include <rpcmanager_base.h> +#include <gnuradio/rpcserver_base.h> +#include <gnuradio/rpcmanager_base.h> class rpcserver_aggregator : public virtual rpcserver_base { diff --git a/gnuradio-runtime/include/rpcserver_base.h b/gnuradio-runtime/include/gnuradio/rpcserver_base.h index bc985c8d53..e2a1f6ef24 100644 --- a/gnuradio-runtime/include/rpcserver_base.h +++ b/gnuradio-runtime/include/gnuradio/rpcserver_base.h @@ -23,7 +23,7 @@ #ifndef RPCSERVER_BASE_H #define RPCSERVER_BASE_H -#include <rpccallbackregister_base.h> +#include <gnuradio/rpccallbackregister_base.h> class rpcserver_base : public virtual callbackregister_base { diff --git a/gnuradio-runtime/include/rpcserver_booter_aggregator.h b/gnuradio-runtime/include/gnuradio/rpcserver_booter_aggregator.h index 38739a1b50..aac9ef8de6 100644 --- a/gnuradio-runtime/include/rpcserver_booter_aggregator.h +++ b/gnuradio-runtime/include/gnuradio/rpcserver_booter_aggregator.h @@ -23,9 +23,9 @@ #ifndef RPCSERVER_BOOTER_AGGREGATOR #define RPCSERVER_BOOTER_AGGREGATOR -#include <gr_runtime_api.h> -#include <rpcserver_booter_base.h> -#include <rpcserver_aggregator.h> +#include <gnuradio/api.h> +#include <gnuradio/rpcserver_booter_base.h> +#include <gnuradio/rpcserver_aggregator.h> #include <boost/shared_ptr.hpp> #include <string> diff --git a/gnuradio-runtime/include/rpcserver_booter_base.h b/gnuradio-runtime/include/gnuradio/rpcserver_booter_base.h index 682944dada..682944dada 100644 --- a/gnuradio-runtime/include/rpcserver_booter_base.h +++ b/gnuradio-runtime/include/gnuradio/rpcserver_booter_base.h diff --git a/gnuradio-runtime/include/rpcserver_booter_ice.h b/gnuradio-runtime/include/gnuradio/rpcserver_booter_ice.h index 69dfcc7602..11095ac433 100644 --- a/gnuradio-runtime/include/rpcserver_booter_ice.h +++ b/gnuradio-runtime/include/gnuradio/rpcserver_booter_ice.h @@ -23,8 +23,8 @@ #ifndef RPCSERVER_BOOTER_ICE_H #define RPCSERVER_BOOTER_ICE_H -#include <rpcserver_booter_base.h> -#include <ice_server_template.h> +#include <gnuradio/rpcserver_booter_base.h> +#include <gnuradio/ice_server_template.h> #include <gnuradio.h> class rpcserver_base; diff --git a/gnuradio-runtime/include/rpcserver_ice.h b/gnuradio-runtime/include/gnuradio/rpcserver_ice.h index 2c08f57dc7..c6c9d45717 100644 --- a/gnuradio-runtime/include/rpcserver_ice.h +++ b/gnuradio-runtime/include/gnuradio/rpcserver_ice.h @@ -23,8 +23,8 @@ #ifndef RPCSERVER_ICE_H #define RPCSERVER_ICE_H -#include <rpcserver_base.h> -#include <rpcpmtconverters_ice.h> +#include <gnuradio/rpcserver_base.h> +#include <gnuradio/rpcpmtconverters_ice.h> #include <string> #include <sstream> #include <map> diff --git a/gnuradio-runtime/include/rpcserver_selector.h b/gnuradio-runtime/include/gnuradio/rpcserver_selector.h index fa63c9a2dc..fa63c9a2dc 100644 --- a/gnuradio-runtime/include/rpcserver_selector.h +++ b/gnuradio-runtime/include/gnuradio/rpcserver_selector.h diff --git a/gnuradio-runtime/include/gnuradio/runtime_types.h b/gnuradio-runtime/include/gnuradio/runtime_types.h new file mode 100644 index 0000000000..f4674c0f0c --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/runtime_types.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_RUNTIME_TYPES_H +#define INCLUDED_GR_RUNTIME_TYPES_H + +#include <gnuradio/api.h> +#include <gnuradio/types.h> + +namespace gr { + + /* + * typedefs for smart pointers we use throughout the runtime system + */ + class basic_block; + class block; + class block_detail; + class buffer; + class buffer_reader; + class hier_block2; + class flat_flowgraph; + class flowgraph; + class top_block; + + typedef boost::shared_ptr<basic_block> basic_block_sptr; + typedef boost::shared_ptr<block> block_sptr; + typedef boost::shared_ptr<block_detail> block_detail_sptr; + typedef boost::shared_ptr<buffer> buffer_sptr; + typedef boost::shared_ptr<buffer_reader> buffer_reader_sptr; + typedef boost::shared_ptr<hier_block2> hier_block2_sptr; + typedef boost::shared_ptr<flat_flowgraph> flat_flowgraph_sptr; + typedef boost::shared_ptr<flowgraph> flowgraph_sptr; + typedef boost::shared_ptr<top_block> top_block_sptr; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_RUNTIME_TYPES_H */ diff --git a/gnuradio-runtime/include/gnuradio/select_handler.h b/gnuradio-runtime/include/gnuradio/select_handler.h new file mode 100644 index 0000000000..df7c753ced --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/select_handler.h @@ -0,0 +1,90 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_SELECT_HANDLER_H +#define INCLUDED_GR_SELECT_HANDLER_H + +#include <gnuradio/api.h> +#include <boost/shared_ptr.hpp> + +namespace gr { + + class select_handler; + typedef boost::shared_ptr<select_handler> select_handler_sptr; + + /*! + * \brief Abstract handler for select based notification. + * \ingroup base + * + * \sa gr::dispatcher + */ + class GR_RUNTIME_API select_handler + { + int d_fd; + + protected: + select_handler(int file_descriptor); + + public: + virtual ~select_handler(); + + int fd() const { return d_fd; } + int file_descriptor() const { return d_fd; } + + /*! + * \brief Called when file_descriptor is readable. + * + * Called when the dispatcher detects that file_descriptor can be + * read without blocking. + */ + virtual void handle_read() = 0; + + /*! + * \brief Called when file_descriptor is writable. + * + * Called when dispatcher detects that file descriptor can be + * written without blocking. + */ + virtual void handle_write() = 0; + + /*! + * Called each time around the dispatcher loop to determine + * whether this handler's file descriptor should be added to the + * list on which read events can occur. The default method + * returns true, indicating that by default, all handlers are + * interested in read events. + */ + virtual bool readable() { return true; } + + /*! + * Called each time around the dispatcher loop to determine + * whether this handler's file descriptor should be added to the + * list on which write events can occur. The default method + * returns true, indicating that by default, all handlers are + * interested in write events. + */ + virtual bool writable() { return true; } + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_SELECT_HANDLER_H */ diff --git a/gnuradio-runtime/include/gr_sincos.h b/gnuradio-runtime/include/gnuradio/sincos.h index 5a182081de..f162f6e31b 100644 --- a/gnuradio-runtime/include/gr_sincos.h +++ b/gnuradio-runtime/include/gnuradio/sincos.h @@ -23,19 +23,13 @@ #ifndef INCLUDED_GR_SINCOS_H #define INCLUDED_GR_SINCOS_H -#include <gr_runtime_api.h> +#include <gnuradio/api.h> -#ifdef __cplusplus -extern "C" { -#endif +namespace gr { -// compute sine and cosine at the same time - -GR_RUNTIME_API void gr_sincos (double x, double *sin, double *cos); -GR_RUNTIME_API void gr_sincosf (float x, float *sin, float *cos); - -#ifdef __cplusplus -}; -#endif + // compute sine and cosine at the same time + GR_RUNTIME_API void sincos (double x, double *sin, double *cos); + GR_RUNTIME_API void sincosf (float x, float *sin, float *cos); +} #endif /* INCLUDED_GR_SINCOS_H */ diff --git a/gnuradio-runtime/include/gr_single_threaded_scheduler.h b/gnuradio-runtime/include/gnuradio/single_threaded_scheduler.h index d538fa3921..eccbf03b36 100644 --- a/gnuradio-runtime/include/gr_single_threaded_scheduler.h +++ b/gnuradio-runtime/include/gnuradio/single_threaded_scheduler.h @@ -23,40 +23,43 @@ #ifndef INCLUDED_GR_SINGLE_THREADED_SCHEDULER_H #define INCLUDED_GR_SINGLE_THREADED_SCHEDULER_H -#include <gr_runtime_api.h> -#include <gr_runtime_types.h> +#include <gnuradio/api.h> +#include <gnuradio/runtime_types.h> #include <fstream> -class gr_single_threaded_scheduler; -typedef boost::shared_ptr<gr_single_threaded_scheduler> gr_single_threaded_scheduler_sptr; +namespace gr { + class single_threaded_scheduler; + typedef boost::shared_ptr<single_threaded_scheduler> single_threaded_scheduler_sptr; -/*! - * \brief Simple scheduler for stream computations. - * \ingroup internal - */ + /*! + * \brief Simple scheduler for stream computations. + * \ingroup internal + */ + class GR_RUNTIME_API single_threaded_scheduler + { + public: + ~single_threaded_scheduler(); -class GR_RUNTIME_API gr_single_threaded_scheduler { - public: - ~gr_single_threaded_scheduler (); + void run(); + void stop(); - void run (); - void stop (); + private: + const std::vector<block_sptr> d_blocks; + volatile bool d_enabled; + std::ofstream *d_log; - private: - const std::vector<gr_block_sptr> d_blocks; - volatile bool d_enabled; - std::ofstream *d_log; + single_threaded_scheduler(const std::vector<block_sptr> &blocks); - gr_single_threaded_scheduler (const std::vector<gr_block_sptr> &blocks); + void main_loop(); - void main_loop (); + friend GR_RUNTIME_API single_threaded_scheduler_sptr + make_single_threaded_scheduler(const std::vector<block_sptr> &blocks); + }; - friend GR_RUNTIME_API gr_single_threaded_scheduler_sptr - gr_make_single_threaded_scheduler (const std::vector<gr_block_sptr> &blocks); -}; + GR_RUNTIME_API single_threaded_scheduler_sptr + make_single_threaded_scheduler(const std::vector<block_sptr> &blocks); -GR_RUNTIME_API gr_single_threaded_scheduler_sptr -gr_make_single_threaded_scheduler (const std::vector<gr_block_sptr> &blocks); +} /* namespace gr */ #endif /* INCLUDED_GR_SINGLE_THREADED_SCHEDULER_H */ diff --git a/gnuradio-runtime/include/gr_sptr_magic.h b/gnuradio-runtime/include/gnuradio/sptr_magic.h index 2a94806d18..898edc87fd 100644 --- a/gnuradio-runtime/include/gr_sptr_magic.h +++ b/gnuradio-runtime/include/gnuradio/sptr_magic.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008 Free Software Foundation, Inc. + * Copyright 2008,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -18,35 +18,40 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef INCLUDED_GR_SPTR_MAGIC_H -#define INCLUDED_GR_SPTR_MAGIC_H -#include <gr_runtime_api.h> +#ifndef INCLUDED_GR_RUNTIME_SPTR_MAGIC_H +#define INCLUDED_GR_RUNTIME_SPTR_MAGIC_H + +#include <gnuradio/api.h> #include <boost/shared_ptr.hpp> -class gr_basic_block; -class gr_hier_block2; +namespace gr { + class basic_block; + class hier_block2; +} namespace gnuradio { - namespace detail { - class GR_RUNTIME_API sptr_magic { + class GR_RUNTIME_API sptr_magic + { public: - static boost::shared_ptr<gr_basic_block> fetch_initial_sptr(gr_basic_block *p); - static void create_and_stash_initial_sptr(gr_hier_block2 *p); + static boost::shared_ptr<gr::basic_block> fetch_initial_sptr(gr::basic_block *p); + static void create_and_stash_initial_sptr(gr::hier_block2 *p); }; }; /* - * \brief New! Improved! Standard method to get/create the boost::shared_ptr for a block. + * \brief New! Improved! Standard method to get/create the + * boost::shared_ptr for a block. */ template<class T> boost::shared_ptr<T> get_initial_sptr(T *p) { - return boost::dynamic_pointer_cast<T, gr_basic_block>(detail::sptr_magic::fetch_initial_sptr(p)); + return boost::dynamic_pointer_cast<T, gr::basic_block> + (detail::sptr_magic::fetch_initial_sptr(p)); } -}; +} -#endif /* INCLUDED_GR_SPTR_MAGIC_H */ +#endif /* INCLUDED_GR_RUNTIME_SPTR_MAGIC_H */ diff --git a/gnuradio-runtime/include/gnuradio/sync_block.h b/gnuradio-runtime/include/gnuradio/sync_block.h new file mode 100644 index 0000000000..4b0022ab7e --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/sync_block.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_RUNTIME_SYNC_BLOCK_H +#define INCLUDED_GR_RUNTIME_SYNC_BLOCK_H + +#include <gnuradio/api.h> +#include <gnuradio/block.h> + +namespace gr { + + /*! + * \brief synchronous 1:1 input to output with history + * \ingroup base_blk + * + * Override work to provide the signal processing implementation. + */ + class GR_RUNTIME_API sync_block : public block + { + protected: + sync_block(void) {} // allows pure virtual interface sub-classes + sync_block(const std::string &name, + gr::io_signature::sptr input_signature, + gr::io_signature::sptr output_signature); + + public: + /*! + * \brief just like gr::block::general_work, only this arranges to + * call consume_each for you + * + * The user must override work to define the signal processing code + */ + virtual int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) = 0; + + // gr::sync_block overrides these to assist work + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + int fixed_rate_ninput_to_noutput(int ninput); + int fixed_rate_noutput_to_ninput(int noutput); + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_RUNTIME_SYNC_BLOCK_H */ diff --git a/gnuradio-runtime/include/gnuradio/sync_decimator.h b/gnuradio-runtime/include/gnuradio/sync_decimator.h new file mode 100644 index 0000000000..129abdca79 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/sync_decimator.h @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004, 2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_RUNTIME_SYNC_DECIMATOR_H +#define INCLUDED_GR_RUNTIME_SYNC_DECIMATOR_H + +#include <gnuradio/api.h> +#include <gnuradio/sync_block.h> + +namespace gr { + + /*! + * \brief synchronous N:1 input to output with history + * \ingroup base_blk + * + * Override work to provide the signal processing implementation. + */ + class GR_RUNTIME_API sync_decimator : public sync_block + { + private: + unsigned d_decimation; + + protected: + sync_decimator(void) {} // allows pure virtual interface sub-classes + sync_decimator(const std::string &name, + gr::io_signature::sptr input_signature, + gr::io_signature::sptr output_signature, + unsigned decimation); + + public: + unsigned decimation() const { return d_decimation; } + void set_decimation(unsigned decimation) + { + d_decimation = decimation; + set_relative_rate(1.0 / decimation); + } + + // gr::sync_decimator overrides these to assist work + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + // derived classes should override work + + int fixed_rate_ninput_to_noutput(int ninput); + int fixed_rate_noutput_to_ninput(int noutput); + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_RUNTIME_SYNC_DECIMATOR_H */ diff --git a/gnuradio-runtime/include/gnuradio/sync_interpolator.h b/gnuradio-runtime/include/gnuradio/sync_interpolator.h new file mode 100644 index 0000000000..bfe79f902e --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/sync_interpolator.h @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2008,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_RUNTIME_SYNC_INTERPOLATOR_H +#define INCLUDED_GR_RUNTIME_SYNC_INTERPOLATOR_H + +#include <gnuradio/api.h> +#include <gnuradio/sync_block.h> + +namespace gr { + + /*! + * \brief synchronous 1:N input to output with history + * \ingroup base_blk + * + * Override work to provide the signal processing implementation. + */ + class GR_RUNTIME_API sync_interpolator : public sync_block + { + private: + unsigned d_interpolation; + + protected: + sync_interpolator(void) {} // allows pure virtual interface sub-classes + sync_interpolator(const std::string &name, + gr::io_signature::sptr input_signature, + gr::io_signature::sptr output_signature, + unsigned interpolation); + + public: + unsigned interpolation() const { return d_interpolation; } + void set_interpolation(unsigned interpolation) + { + d_interpolation = interpolation; + set_relative_rate(1.0 * interpolation); + set_output_multiple(interpolation); + } + + // gr::sync_interpolator overrides these to assist work + void forecast(int noutput_items, + gr_vector_int &ninput_items_required); + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + // derived classes should override work + + int fixed_rate_ninput_to_noutput(int ninput); + int fixed_rate_noutput_to_ninput(int noutput); + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_RUNTIME_SYNC_INTERPOLATOR_H */ diff --git a/gnuradio-runtime/include/gr_sys_paths.h b/gnuradio-runtime/include/gnuradio/sys_paths.h index 6235e0e78f..1bd2e0deb7 100644 --- a/gnuradio-runtime/include/gr_sys_paths.h +++ b/gnuradio-runtime/include/gnuradio/sys_paths.h @@ -1,5 +1,5 @@ /* - * Copyright 2011 Free Software Foundation, Inc. + * Copyright 2011,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -19,15 +19,19 @@ * Boston, MA 02110-1301, USA. */ -#ifndef _GR_SYS_PATHS_H_ -#define _GR_SYS_PATHS_H_ +#ifndef GR_SYS_PATHS_H +#define GR_SYS_PATHS_H -#include <gr_runtime_api.h> +#include <gnuradio/api.h> -//! directory to create temporary files -GR_RUNTIME_API const char *gr_tmp_path(); +namespace gr { -//! directory to store application data -GR_RUNTIME_API const char *gr_appdata_path(); + //! directory to create temporary files + GR_RUNTIME_API const char *tmp_path(); -#endif /* _GR_SYS_PATHS_H_ */ + //! directory to store application data + GR_RUNTIME_API const char *appdata_path(); + +} /* namespace gr */ + +#endif /* GR_SYS_PATHS_H */ diff --git a/gnuradio-runtime/include/sys_pri.h b/gnuradio-runtime/include/gnuradio/sys_pri.h index 745176e681..adceb91b9d 100644 --- a/gnuradio-runtime/include/sys_pri.h +++ b/gnuradio-runtime/include/gnuradio/sys_pri.h @@ -22,7 +22,7 @@ #ifndef INCLUDED_GNURADIO_SYS_PRI_H #define INCLUDED_GNURADIO_SYS_PRI_H -#include <gr_runtime_api.h> +#include <gnuradio/api.h> #include <realtime.h> /* diff --git a/gnuradio-runtime/include/gnuradio/tagged_stream_block.h b/gnuradio-runtime/include/gnuradio/tagged_stream_block.h new file mode 100644 index 0000000000..1fe92ee25a --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/tagged_stream_block.h @@ -0,0 +1,144 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_RUNTIME_TAGGED_STREAM_BLOCK_H +#define INCLUDED_GR_RUNTIME_TAGGED_STREAM_BLOCK_H + +#include <gnuradio/api.h> +#include <gnuradio/block.h> + +namespace gr { + + /*! + * \brief Block that operates on PDUs in form of tagged streams + * \ingroup base_blk + * + * Override work to provide the signal processing implementation. + */ + class GR_RUNTIME_API tagged_stream_block : public block + { + private: + pmt::pmt_t d_length_tag_key; //!< This is the key for the tag that stores the PDU length + gr_vector_int d_n_input_items_reqd; //!< How many input items do I need to process the next PDU? + + protected: + std::string d_length_tag_key_str; + tagged_stream_block(void) {} // allows pure virtual interface sub-classes + tagged_stream_block(const std::string &name, + gr::io_signature::sptr input_signature, + gr::io_signature::sptr output_signature, + const std::string &length_tag_key); + + /*! + * \brief Parse all tags on the first sample of a PDU, return the + * number of items per input and prune the length tags. + * + * In most cases, you don't need to override this, unless the + * number of items read is not directly coded in one single tag. + * + * Default behaviour: + * - Go through all input ports + * - On every input port, search for the tag with the key specified in \p length_tag_key + * - Copy that value as an int to the corresponding position in \p n_input_items_reqd + * - Remove the length tag. + * + * \param[in] tags All the tags found on the first item of every input port. + * \param[out] n_input_items_reqd Number of items which will be read from every input + */ + virtual void parse_length_tags(const std::vector<std::vector<tag_t> > &tags, + gr_vector_int &n_input_items_reqd); + + /*! + * \brief Calculate the number of output items. + * + * This is basically the inverse function to forecast(): Given a + * number of input items, it returns the maximum number of output + * items. + * + * You most likely need to override this function, unless your + * block is a sync block or integer interpolator/decimator. + */ + virtual int calculate_output_stream_length(const gr_vector_int &ninput_items); + + /*! + * \brief Set the new length tags on the output stream + * + * Default behaviour: Set a tag with key \p length_tag_key and the + * number of produced items on every output port. + * + * For anything else, override this. + * + * \param n_produced Length of the new PDU + * \param n_ports Number of output ports + */ + virtual void update_length_tags(int n_produced, int n_ports); + + public: + /*! \brief Don't override this. + */ + void /* final */ forecast (int noutput_items, gr_vector_int &ninput_items_required); + + /*! + * - Reads the number of input items from the tags using parse_length_tags() + * - Checks there's enough data on the input and output buffers + * - If not, inform the scheduler and do nothing + * - Calls work() with the exact number of items per PDU + * - Updates the tags using update_length_tags() + */ + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + /*! + * \brief Just like gr::block::general_work, but makes sure the input is valid + * + * The user must override work to define the signal processing + * code. Check the documentation for general_work() to see what + * happens here. + * + * Like gr::sync_block, this calls consume() for you (it consumes + * ninput_items[i] items from the i-th port). + * + * A note on tag propagation: The PDU length tags are handled by + * other functions, but all other tags are handled just as in any + * other \p gr::block. So, most likely, you either set the tag + * propagation policy to TPP_DONT and handle the tag propagation + * manually, or you propagate tags through the scheduler and don't + * do anything here. + * + * \param noutput_items The size of the writable output buffer + * \param ninput_items The exact size of the items on every input for this particular PDU. + * These will be consumed if a length tag key is provided! + * \param input_items See gr::block + * \param output_items See gr::block + */ + virtual int work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) = 0; + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_RUNTIME_TAGGED_STREAM_BLOCK_H */ + diff --git a/gnuradio-runtime/include/gr_tags.h b/gnuradio-runtime/include/gnuradio/tags.h index 668b2bf248..5600601741 100644 --- a/gnuradio-runtime/include/gr_tags.h +++ b/gnuradio-runtime/include/gnuradio/tags.h @@ -1,5 +1,6 @@ +/* -*- c++ -*- */ /* - * Copyright 2011 Free Software Foundation, Inc. + * Copyright 2011,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -22,11 +23,13 @@ #ifndef INCLUDED_GR_TAGS_H #define INCLUDED_GR_TAGS_H -#include <gr_runtime_api.h> +#include <gnuradio/api.h> #include <pmt/pmt.h> -struct GR_RUNTIME_API gr_tag_t{ - +namespace gr { + + struct GR_RUNTIME_API tag_t + { //! the item \p tag occurred at (as a uint64_t) uint64_t offset; @@ -39,17 +42,23 @@ struct GR_RUNTIME_API gr_tag_t{ //! the source ID of \p tag (as a PMT) pmt::pmt_t srcid; - //! Comparison function to test which tag, \p x or \p y, came first in time - static inline bool offset_compare( - const gr_tag_t &x, const gr_tag_t &y - ){ - return x.offset < y.offset; + /*! + * Comparison function to test which tag, \p x or \p y, came + * first in time + */ + static inline bool offset_compare(const tag_t &x, + const tag_t &y) + { + return x.offset < y.offset; } - inline bool operator == (const gr_tag_t &t) const + inline bool operator == (const tag_t &t) const { - return (t.key == key) && (t.value == value) && (t.srcid == srcid) && (t.offset == offset); + return (t.key == key) && (t.value == value) && \ + (t.srcid == srcid) && (t.offset == offset); } -}; + }; + +} /* namespace gr */ #endif /*INCLUDED_GR_TAGS_H*/ diff --git a/gnuradio-runtime/include/thread/CMakeLists.txt b/gnuradio-runtime/include/gnuradio/thread/CMakeLists.txt index 8ea4bfc66e..8ea4bfc66e 100644 --- a/gnuradio-runtime/include/thread/CMakeLists.txt +++ b/gnuradio-runtime/include/gnuradio/thread/CMakeLists.txt diff --git a/gnuradio-runtime/include/thread/thread.h b/gnuradio-runtime/include/gnuradio/thread/thread.h index 548d76e9a5..04d67d0821 100644 --- a/gnuradio-runtime/include/thread/thread.h +++ b/gnuradio-runtime/include/gnuradio/thread/thread.h @@ -22,7 +22,7 @@ #ifndef INCLUDED_THREAD_H #define INCLUDED_THREAD_H -#include <gr_runtime_api.h> +#include <gnuradio/api.h> #include <boost/thread/thread.hpp> #include <boost/thread/mutex.hpp> #include <boost/thread/locks.hpp> diff --git a/gnuradio-runtime/include/thread/thread_body_wrapper.h b/gnuradio-runtime/include/gnuradio/thread/thread_body_wrapper.h index dcf8cff48e..9761d3fbe2 100644 --- a/gnuradio-runtime/include/thread/thread_body_wrapper.h +++ b/gnuradio-runtime/include/gnuradio/thread/thread_body_wrapper.h @@ -22,8 +22,8 @@ #ifndef INCLUDED_THREAD_BODY_WRAPPER_H #define INCLUDED_THREAD_BODY_WRAPPER_H -#include <gr_runtime_api.h> -#include <thread/thread.h> +#include <gnuradio/api.h> +#include <gnuradio/thread/thread.h> #include <exception> #include <iostream> diff --git a/gnuradio-runtime/include/thread/thread_group.h b/gnuradio-runtime/include/gnuradio/thread/thread_group.h index 81b561bd64..830017d11e 100644 --- a/gnuradio-runtime/include/thread/thread_group.h +++ b/gnuradio-runtime/include/gnuradio/thread/thread_group.h @@ -15,8 +15,8 @@ #ifndef INCLUDED_THREAD_GROUP_H #define INCLUDED_THREAD_GROUP_H -#include <gr_runtime_api.h> -#include <thread/thread.h> +#include <gnuradio/api.h> +#include <gnuradio/thread/thread.h> #include <boost/utility.hpp> #include <boost/thread/shared_mutex.hpp> #include <boost/function.hpp> diff --git a/gnuradio-runtime/include/gr_timer.h b/gnuradio-runtime/include/gnuradio/timer.h index 45b663b368..d685fd9a19 100644 --- a/gnuradio-runtime/include/gr_timer.h +++ b/gnuradio-runtime/include/gnuradio/timer.h @@ -22,8 +22,8 @@ #ifndef INCLUDED_GR_TIMER_H #define INCLUDED_GR_TIMER_H -#include <gr_runtime_api.h> -#include <gr_types.h> +#include <gnuradio/api.h> +#include <gnuradio/types.h> class gr_timer; diff --git a/gnuradio-runtime/include/gnuradio/top_block.h b/gnuradio-runtime/include/gnuradio/top_block.h new file mode 100644 index 0000000000..b3692e09e2 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/top_block.h @@ -0,0 +1,146 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007-2009,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_TOP_BLOCK_H +#define INCLUDED_GR_TOP_BLOCK_H + +#include <gnuradio/api.h> +#include <gnuradio/hier_block2.h> + +namespace gr { + + class top_block_impl; + + GR_RUNTIME_API top_block_sptr make_top_block(const std::string &name); + + /*! + *\brief Top-level hierarchical block representing a flowgraph + * \ingroup container_blk + */ + class GR_RUNTIME_API top_block : public hier_block2 + { + private: + friend GR_RUNTIME_API top_block_sptr + make_top_block(const std::string &name); + + top_block_impl *d_impl; + + protected: + top_block(const std::string &name); + + public: + ~top_block(); + + /*! + * \brief The simple interface to running a flowgraph. + * + * Calls start() then wait(). Used to run a flowgraph that will + * stop on its own, or when another thread will call stop(). + * + * \param max_noutput_items the maximum number of output items + * allowed for any block in the flowgraph. This passes through to + * the start function; see that function for more details. + */ + void run(int max_noutput_items=100000000); + + /*! + * Start the contained flowgraph. Creates one or more threads to + * execute the flow graph. Returns to the caller once the threads + * are created. Calling start() on a top_block that is already + * started IS an error. + * + * \param max_noutput_items the maximum number of output items + * allowed for any block in the flowgraph; the noutput_items can + * always be less than this, but this will cap it as a + * maximum. Use this to adjust the maximum latency a flowgraph can + * exhibit. + */ + void start(int max_noutput_items=100000000); + + /*! + * Stop the running flowgraph. Notifies each thread created by the + * scheduler to shutdown, then returns to caller. Calling stop() + * on a top_block that is already stopped IS NOT an error. + */ + void stop(); + + /*! + * Wait for a flowgraph to complete. Flowgraphs complete when + * either (1) all blocks indicate that they are done (typically + * only when using blocks.file_source, or blocks.head, or (2) + * after stop() has been called to request shutdown. Calling wait + * on a top_block that is not running IS NOT an error (wait + * returns w/o blocking). + */ + void wait(); + + /*! + * Lock a flowgraph in preparation for reconfiguration. When an + * equal number of calls to lock() and unlock() have occurred, the + * flowgraph will be reconfigured. + * + * N.B. lock() and unlock() may not be called from a flowgraph + * thread (E.g., block::work method) or deadlock will occur + * when reconfiguration happens. + */ + virtual void lock(); + + /*! + * Unlock a flowgraph in preparation for reconfiguration. When an + * equal number of calls to lock() and unlock() have occurred, the + * flowgraph will be reconfigured. + * + * N.B. lock() and unlock() may not be called from a flowgraph thread + * (E.g., block::work method) or deadlock will occur when + * reconfiguration happens. + */ + virtual void unlock(); + + /*! + * Returns a string that lists the edge connections in the + * flattened flowgraph. + */ + std::string edge_list(); + + /*! + * Displays flattened flowgraph edges and block connectivity + */ + void dump(); + + //! Get the number of max noutput_items in the flowgraph + int max_noutput_items(); + + //! Set the maximum number of noutput_items in the flowgraph + void set_max_noutput_items(int nmax); + + top_block_sptr to_top_block(); // Needed for Python type coercion + + void setup_rpc(); + }; + + inline top_block_sptr cast_to_top_block_sptr(basic_block_sptr block) { + return boost::dynamic_pointer_cast<top_block, basic_block>(block); + } + +} /* namespce gr */ + +#endif /* INCLUDED_GR_TOP_BLOCK_H */ diff --git a/gnuradio-runtime/include/gnuradio/tpb_detail.h b/gnuradio-runtime/include/gnuradio/tpb_detail.h new file mode 100644 index 0000000000..9b7454b508 --- /dev/null +++ b/gnuradio-runtime/include/gnuradio/tpb_detail.h @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2013 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 3, 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_GR_TPB_DETAIL_H +#define INCLUDED_GR_TPB_DETAIL_H + +#include <gnuradio/api.h> +#include <gnuradio/thread/thread.h> +#include <deque> +#include <pmt/pmt.h> + +namespace gr { + + class block_detail; + + /*! + * \brief used by thread-per-block scheduler + */ + struct GR_RUNTIME_API tpb_detail { + gr::thread::mutex mutex; //< protects all vars + bool input_changed; + gr::thread::condition_variable input_cond; + bool output_changed; + gr::thread::condition_variable output_cond; + + public: + tpb_detail() + : input_changed(false), output_changed(false) { } + + //! Called by us to tell all our upstream blocks that their output + //! may have changed. + void notify_upstream(block_detail *d); + + //! Called by us to tell all our downstream blocks that their + //! input may have changed. + void notify_downstream(block_detail *d); + + //! Called by us to notify both upstream and downstream + void notify_neighbors(block_detail *d); + + //! Called by pmt msg posters + void notify_msg() { + input_cond.notify_one(); + output_cond.notify_one(); + } + + //! Called by us + void clear_changed() + { + gr::thread::scoped_lock guard(mutex); + input_changed = false; + output_changed = false; + } + + private: + //! Used by notify_downstream + void set_input_changed() + { + gr::thread::scoped_lock guard(mutex); + input_changed = true; + input_cond.notify_one(); + } + + //! Used by notify_upstream + void set_output_changed() + { + gr::thread::scoped_lock guard(mutex); + output_changed = true; + output_cond.notify_one(); + } + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_TPB_DETAIL_H */ diff --git a/gnuradio-runtime/include/gr_types.h b/gnuradio-runtime/include/gnuradio/types.h index 47e22469b0..6cb0f72834 100644 --- a/gnuradio-runtime/include/gr_types.h +++ b/gnuradio-runtime/include/gnuradio/types.h @@ -23,12 +23,12 @@ #ifndef INCLUDED_GR_TYPES_H #define INCLUDED_GR_TYPES_H -#include <gr_runtime_api.h> +#include <gnuradio/api.h> #include <boost/shared_ptr.hpp> #include <vector> #include <stddef.h> // size_t -#include <gr_complex.h> +#include <gnuradio/gr_complex.h> typedef std::vector<int> gr_vector_int; typedef std::vector<unsigned int> gr_vector_uint; @@ -39,7 +39,7 @@ typedef std::vector<const void *> gr_vector_const_void_star; /* * #include <config.h> must be placed beforehand - * in the source file including gr_types.h for + * in the source file including gnuradio/types.h for * the following to work correctly */ #ifdef HAVE_STDINT_H diff --git a/gnuradio-runtime/include/gr_unittests.h b/gnuradio-runtime/include/gnuradio/unittests.h index d160ba3354..209c3ab32a 100644 --- a/gnuradio-runtime/include/gr_unittests.h +++ b/gnuradio-runtime/include/gnuradio/unittests.h @@ -20,7 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#include <gr_runtime_api.h> +#include <gnuradio/api.h> #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/gnuradio-runtime/include/gr_basic_block.h b/gnuradio-runtime/include/gr_basic_block.h deleted file mode 100644 index beb54dbb6b..0000000000 --- a/gnuradio-runtime/include/gr_basic_block.h +++ /dev/null @@ -1,344 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2008,2009,2011 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_BASIC_BLOCK_H -#define INCLUDED_GR_BASIC_BLOCK_H - -#include <gr_runtime_api.h> -#include <gr_runtime_types.h> -#include <gr_sptr_magic.h> -#include <boost/enable_shared_from_this.hpp> -#include <boost/function.hpp> -#include <gr_msg_accepter.h> -#include <string> -#include <deque> -#include <map> -#include <gr_io_signature.h> -#include <thread/thread.h> -#include <boost/foreach.hpp> -#include <boost/thread/condition_variable.hpp> -#include <iostream> - -#ifdef GR_CTRLPORT -#include <rpcregisterhelpers.h> -#endif - -/*! - * \brief The abstract base class for all signal processing blocks. - * \ingroup internal - * - * Basic blocks are the bare abstraction of an entity that has a name, - * a set of inputs and outputs, and a message queue. These are never instantiated - * directly; rather, this is the abstract parent class of both gr_hier_block, - * which is a recursive container, and gr_block, which implements actual - * signal processing functions. - */ - -class GR_RUNTIME_API gr_basic_block : public gr_msg_accepter, public boost::enable_shared_from_this<gr_basic_block> -{ - typedef boost::function<void(pmt::pmt_t)> msg_handler_t; - - private: - - //msg_handler_t d_msg_handler; - typedef std::map<pmt::pmt_t , msg_handler_t, pmt::comperator> d_msg_handlers_t; - d_msg_handlers_t d_msg_handlers; - - typedef std::deque<pmt::pmt_t> msg_queue_t; - typedef std::map<pmt::pmt_t, msg_queue_t, pmt::comperator> msg_queue_map_t; - typedef std::map<pmt::pmt_t, msg_queue_t, pmt::comperator>::iterator msg_queue_map_itr; - std::map<pmt::pmt_t, boost::shared_ptr<boost::condition_variable>, pmt::comperator> msg_queue_ready; - - gr::thread::mutex mutex; //< protects all vars - - protected: - friend class gr_flowgraph; - friend class gr_flat_flowgraph; // TODO: will be redundant - friend class gr_tpb_thread_body; - - enum vcolor { WHITE, GREY, BLACK }; - - std::string d_name; - gr_io_signature_sptr d_input_signature; - gr_io_signature_sptr d_output_signature; - long d_unique_id; - long d_symbolic_id; - std::string d_symbol_name; - std::string d_symbol_alias; - vcolor d_color; - bool d_rpc_set; - - msg_queue_map_t msg_queue; - std::vector<boost::any> d_rpc_vars; // container for all RPC variables - - gr_basic_block(void){} //allows pure virtual interface sub-classes - - //! Protected constructor prevents instantiation by non-derived classes - gr_basic_block(const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature); - - //! may only be called during constructor - void set_input_signature(gr_io_signature_sptr iosig) { - d_input_signature = iosig; - } - - //! may only be called during constructor - void set_output_signature(gr_io_signature_sptr iosig) { - d_output_signature = iosig; - } - - /*! - * \brief Allow the flowgraph to set for sorting and partitioning - */ - void set_color(vcolor color) { d_color = color; } - vcolor color() const { return d_color; } - - /*! - * \brief Tests if there is a handler attached to port \p which_port - */ - bool has_msg_handler(pmt::pmt_t which_port) { - return (d_msg_handlers.find(which_port) != d_msg_handlers.end()); - } - - /* - * This function is called by the runtime system to dispatch messages. - * - * The thread-safety guarantees mentioned in set_msg_handler are implemented - * by the callers of this method. - */ - virtual void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg) - { - // AA Update this - if(has_msg_handler(which_port)) { // Is there a handler? - d_msg_handlers[which_port](msg); // Yes, invoke it. - } - } - - // Message passing interface - pmt::pmt_t message_subscribers; - - public: - virtual ~gr_basic_block(); - long unique_id() const { return d_unique_id; } - long symbolic_id() const { return d_symbolic_id; } - std::string name() const { return d_name; } - std::string symbol_name() const { return d_symbol_name; } - gr_io_signature_sptr input_signature() const { return d_input_signature; } - gr_io_signature_sptr output_signature() const { return d_output_signature; } - gr_basic_block_sptr to_basic_block(); // Needed for Python type coercion - bool alias_set() { return !d_symbol_alias.empty(); } - std::string alias(){ return alias_set()?d_symbol_alias:symbol_name(); } - pmt::pmt_t alias_pmt(){ return pmt::intern(alias()); } - void set_block_alias(std::string name); - - // ** Message passing interface ** - void message_port_register_in(pmt::pmt_t port_id); - void message_port_register_out(pmt::pmt_t port_id); - void message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg); - void message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target); - void message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target); - - virtual bool message_port_is_hier(pmt::pmt_t port_id) { (void) port_id; std::cout << "is_hier\n"; return false; } - virtual bool message_port_is_hier_in(pmt::pmt_t port_id) { (void) port_id; std::cout << "is_hier_in\n"; return false; } - virtual bool message_port_is_hier_out(pmt::pmt_t port_id) { (void) port_id; std::cout << "is_hier_out\n"; return false; } - - /*! - * \brief Get input message port names. - * - * Returns the available input message ports for a block. The - * return object is a PMT vector that is filled with PMT symbols. - */ - pmt::pmt_t message_ports_in(); - - /*! - * \brief Get output message port names. - * - * Returns the available output message ports for a block. The - * return object is a PMT vector that is filled with PMT symbols. - */ - pmt::pmt_t message_ports_out(); - - /*! - * Accept msg, place in queue, arrange for thread to be awakened if it's not already. - */ - void _post(pmt::pmt_t which_port, pmt::pmt_t msg); - - //! is the queue empty? - //bool empty_p(const pmt::pmt_t &which_port) const { return msg_queue[which_port].empty(); } - bool empty_p(pmt::pmt_t which_port) { - if(msg_queue.find(which_port) == msg_queue.end()) - throw std::runtime_error("port does not exist!"); - return msg_queue[which_port].empty(); - } - bool empty_p() { - bool rv = true; - BOOST_FOREACH(msg_queue_map_t::value_type &i, msg_queue) { - rv &= msg_queue[i.first].empty(); - } - return rv; - } - - //! How many messages in the queue? - size_t nmsgs(pmt::pmt_t which_port) { - if(msg_queue.find(which_port) == msg_queue.end()) - throw std::runtime_error("port does not exist!"); - return msg_queue[which_port].size(); - } - - //| Acquires and release the mutex - void insert_tail( pmt::pmt_t which_port, pmt::pmt_t msg); - /*! - * \returns returns pmt at head of queue or pmt_t() if empty. - */ - pmt::pmt_t delete_head_nowait( pmt::pmt_t which_port); - - /*! - * \returns returns pmt at head of queue or pmt_t() if empty. - */ - pmt::pmt_t delete_head_blocking( pmt::pmt_t which_port); - - msg_queue_t::iterator get_iterator(pmt::pmt_t which_port){ - return msg_queue[which_port].begin(); - } - - void erase_msg(pmt::pmt_t which_port, msg_queue_t::iterator it){ - msg_queue[which_port].erase(it); - } - - virtual bool has_msg_port(pmt::pmt_t which_port){ - if(msg_queue.find(which_port) != msg_queue.end()){ - return true; - } - if(pmt::dict_has_key(message_subscribers, which_port)){ - return true; - } - return false; - } - -#ifdef GR_CTRLPORT - /*! - * \brief Add an RPC variable (get or set). - * - * Using controlport, we create new getters/setters and need to - * store them. Each block has a vector to do this, and these never - * need to be accessed again once they are registered with the RPC - * backend. This function takes a - * boost::shared_sptr<rpcbasic_base> so that when the block is - * deleted, all RPC registered variables are cleaned up. - * - * \param s an rpcbasic_sptr of the new RPC variable register to store. - */ - void add_rpc_variable(rpcbasic_sptr s) - { - d_rpc_vars.push_back(s); - } -#endif /* GR_CTRLPORT */ - - /*! - * \brief Set up the RPC registered variables. - * - * This must be overloaded by a block that wants to use - * controlport. This is where rpcbasic_register_{get,set} pointers - * are created, which then get wrapped as shared pointers - * (rpcbasic_sptr(...)) and stored using add_rpc_variable. - */ - virtual void setup_rpc() {}; - - /*! - * \brief Ask if this block has been registered to the RPC. - * - * We can only register a block once, so we use this to protect us - * from calling it multiple times. - */ - bool is_rpc_set() { return d_rpc_set; } - - /*! - * \brief When the block is registered with the RPC, set this. - */ - void rpc_set() { d_rpc_set = true; } - - /*! - * \brief Confirm that ninputs and noutputs is an acceptable combination. - * - * \param ninputs number of input streams connected - * \param noutputs number of output streams connected - * - * \returns true if this is a valid configuration for this block. - * - * This function is called by the runtime system whenever the - * topology changes. Most classes do not need to override this. - * This check is in addition to the constraints specified by the input - * and output gr_io_signatures. - */ - virtual bool check_topology(int ninputs, int noutputs) { (void) ninputs; (void) noutputs; return true; } - - /*! - * \brief Set the callback that is fired when messages are available. - * - * \p msg_handler can be any kind of function pointer or function object - * that has the signature: - * <pre> - * void msg_handler(pmt::pmt msg); - * </pre> - * - * (You may want to use boost::bind to massage your callable into - * the correct form. See gr::blocks::nop for an example that sets - * up a class method as the callback.) - * - * Blocks that desire to handle messages must call this method in their - * constructors to register the handler that will be invoked when messages - * are available. - * - * If the block inherits from gr_block, the runtime system will ensure that - * msg_handler is called in a thread-safe manner, such that work and - * msg_handler will never be called concurrently. This allows msg_handler - * to update state variables without having to worry about thread-safety - * issues with work, general_work or another invocation of msg_handler. - * - * If the block inherits from gr_hier_block2, the runtime system will - * ensure that no reentrant calls are made to msg_handler. - */ - template <typename T> void set_msg_handler(pmt::pmt_t which_port, T msg_handler){ - if(msg_queue.find(which_port) == msg_queue.end()){ - throw std::runtime_error("attempt to set_msg_handler() on bad input message port!"); } - d_msg_handlers[which_port] = msg_handler_t(msg_handler); - } -}; - -inline bool operator<(gr_basic_block_sptr lhs, gr_basic_block_sptr rhs) -{ - return lhs->unique_id() < rhs->unique_id(); -} - -typedef std::vector<gr_basic_block_sptr> gr_basic_block_vector_t; -typedef std::vector<gr_basic_block_sptr>::iterator gr_basic_block_viter_t; - -GR_RUNTIME_API long gr_basic_block_ncurrently_allocated(); - -inline std::ostream &operator << (std::ostream &os, gr_basic_block_sptr basic_block) -{ - os << basic_block->name() << "(" << basic_block->unique_id() << ")"; - return os; -} - -#endif /* INCLUDED_GR_BASIC_BLOCK_H */ diff --git a/gnuradio-runtime/include/gr_block.h b/gnuradio-runtime/include/gr_block.h deleted file mode 100644 index 77ca3f3f72..0000000000 --- a/gnuradio-runtime/include/gr_block.h +++ /dev/null @@ -1,700 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2007,2009,2010 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_BLOCK_H -#define INCLUDED_GR_BLOCK_H - -#include <gr_runtime_api.h> -#include <gr_basic_block.h> -#include <gr_tags.h> -#include <gr_logger.h> - -/*! - * \brief The abstract base class for all 'terminal' processing blocks. - * \ingroup base_blk - * - * A signal processing flow is constructed by creating a tree of - * hierarchical blocks, which at any level may also contain terminal nodes - * that actually implement signal processing functions. This is the base - * class for all such leaf nodes. - - * Blocks have a set of input streams and output streams. The - * input_signature and output_signature define the number of input - * streams and output streams respectively, and the type of the data - * items in each stream. - * - * Although blocks may consume data on each input stream at a - * different rate, all outputs streams must produce data at the same - * rate. That rate may be different from any of the input rates. - * - * User derived blocks override two methods, forecast and general_work, - * to implement their signal processing behavior. forecast is called - * by the system scheduler to determine how many items are required on - * each input stream in order to produce a given number of output - * items. - * - * general_work is called to perform the signal processing in the block. - * It reads the input items and writes the output items. - */ - -class GR_RUNTIME_API gr_block : public gr_basic_block { - - public: - - //! Magic return values from general_work - enum { - WORK_CALLED_PRODUCE = -2, - WORK_DONE = -1 - }; - - enum tag_propagation_policy_t { - TPP_DONT = 0, - TPP_ALL_TO_ALL = 1, - TPP_ONE_TO_ONE = 2 - }; - - virtual ~gr_block (); - - /*! - * Assume block computes y_i = f(x_i, x_i-1, x_i-2, x_i-3...) - * History is the number of x_i's that are examined to produce one y_i. - * This comes in handy for FIR filters, where we use history to - * ensure that our input contains the appropriate "history" for the - * filter. History should be equal to the number of filter taps. - */ - unsigned history () const { return d_history; } - void set_history (unsigned history) { d_history = history; } - - /*! - * \brief Return true if this block has a fixed input to output rate. - * - * If true, then fixed_rate_in_to_out and fixed_rate_out_to_in may be called. - */ - bool fixed_rate() const { return d_fixed_rate; } - - // ---------------------------------------------------------------- - // override these to define your behavior - // ---------------------------------------------------------------- - - /*! - * \brief Estimate input requirements given output request - * - * \param noutput_items number of output items to produce - * \param ninput_items_required number of input items required on each input stream - * - * Given a request to product \p noutput_items, estimate the number of - * data items required on each input stream. The estimate doesn't have - * to be exact, but should be close. - */ - virtual void forecast (int noutput_items, - gr_vector_int &ninput_items_required); - - /*! - * \brief compute output items from input items - * - * \param noutput_items number of output items to write on each output stream - * \param ninput_items number of input items available on each input stream - * \param input_items vector of pointers to the input items, one entry per input stream - * \param output_items vector of pointers to the output items, one entry per output stream - * - * \returns number of items actually written to each output stream, or -1 on EOF. - * It is OK to return a value less than noutput_items. -1 <= return value <= noutput_items - * - * general_work must call consume or consume_each to indicate how many items - * were consumed on each input stream. - */ - virtual int general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - /*! - * \brief Called to enable drivers, etc for i/o devices. - * - * This allows a block to enable an associated driver to begin - * transfering data just before we start to execute the scheduler. - * The end result is that this reduces latency in the pipeline when - * dealing with audio devices, usrps, etc. - */ - virtual bool start(); - - /*! - * \brief Called to disable drivers, etc for i/o devices. - */ - virtual bool stop(); - - // ---------------------------------------------------------------- - - /*! - * \brief Constrain the noutput_items argument passed to forecast and general_work - * - * set_output_multiple causes the scheduler to ensure that the noutput_items - * argument passed to forecast and general_work will be an integer multiple - * of \param multiple The default value of output multiple is 1. - */ - void set_output_multiple (int multiple); - int output_multiple () const { return d_output_multiple; } - bool output_multiple_set () const { return d_output_multiple_set; } - - /*! - * \brief Constrains buffers to work on a set item alignment (for SIMD) - * - * set_alignment_multiple causes the scheduler to ensure that the noutput_items - * argument passed to forecast and general_work will be an integer multiple - * of \param multiple The default value is 1. - * - * This control is similar to the output_multiple setting, except - * that if the number of items passed to the block is less than the - * output_multiple, this value is ignored and the block can produce - * like normal. The d_unaligned value is set to the number of items - * the block is off by. In the next call to general_work, the - * noutput_items is set to d_unaligned or less until - * d_unaligned==0. The buffers are now aligned again and the aligned - * calls can be performed again. - */ - void set_alignment (int multiple); - int alignment () const { return d_output_multiple; } - - void set_unaligned (int na); - int unaligned () const { return d_unaligned; } - void set_is_unaligned (bool u); - bool is_unaligned () const { return d_is_unaligned; } - - /*! - * \brief Tell the scheduler \p how_many_items of input stream \p which_input were consumed. - */ - void consume (int which_input, int how_many_items); - - /*! - * \brief Tell the scheduler \p how_many_items were consumed on each input stream. - */ - void consume_each (int how_many_items); - - /*! - * \brief Tell the scheduler \p how_many_items were produced on output stream \p which_output. - * - * If the block's general_work method calls produce, \p general_work must return WORK_CALLED_PRODUCE. - */ - void produce (int which_output, int how_many_items); - - /*! - * \brief Set the approximate output rate / input rate - * - * Provide a hint to the buffer allocator and scheduler. - * The default relative_rate is 1.0 - * - * decimators have relative_rates < 1.0 - * interpolators have relative_rates > 1.0 - */ - void set_relative_rate (double relative_rate); - - /*! - * \brief return the approximate output rate / input rate - */ - double relative_rate () const { return d_relative_rate; } - - /* - * The following two methods provide special case info to the - * scheduler in the event that a block has a fixed input to output - * ratio. gr_sync_block, gr_sync_decimator and gr_sync_interpolator - * override these. If you're fixed rate, subclass one of those. - */ - /*! - * \brief Given ninput samples, return number of output samples that will be produced. - * N.B. this is only defined if fixed_rate returns true. - * Generally speaking, you don't need to override this. - */ - virtual int fixed_rate_ninput_to_noutput(int ninput); - - /*! - * \brief Given noutput samples, return number of input samples required to produce noutput. - * N.B. this is only defined if fixed_rate returns true. - * Generally speaking, you don't need to override this. - */ - virtual int fixed_rate_noutput_to_ninput(int noutput); - - /*! - * \brief Return the number of items read on input stream which_input - */ - uint64_t nitems_read(unsigned int which_input); - - /*! - * \brief Return the number of items written on output stream which_output - */ - uint64_t nitems_written(unsigned int which_output); - - /*! - * \brief Asks for the policy used by the scheduler to moved tags downstream. - */ - tag_propagation_policy_t tag_propagation_policy(); - - /*! - * \brief Set the policy by the scheduler to determine how tags are moved downstream. - */ - void set_tag_propagation_policy(tag_propagation_policy_t p); - - /*! - * \brief Return the minimum number of output items this block can - * produce during a call to work. - * - * Should be 0 for most blocks. Useful if we're dealing with packets and - * the block produces one packet per call to work. - */ - int min_noutput_items() const { return d_min_noutput_items; } - - /*! - * \brief Set the minimum number of output items this block can - * produce during a call to work. - * - * \param m the minimum noutput_items this block can produce. - */ - void set_min_noutput_items(int m) { d_min_noutput_items = m; } - - /*! - * \brief Return the maximum number of output items this block will - * handle during a call to work. - */ - int max_noutput_items(); - - /*! - * \brief Set the maximum number of output items this block will - * handle during a call to work. - * - * \param m the maximum noutput_items this block will handle. - */ - void set_max_noutput_items(int m); - - /*! - * \brief Clear the switch for using the max_noutput_items value of this block. - * - * When is_set_max_noutput_items() returns 'true', the scheduler - * will use the value returned by max_noutput_items() to limit the - * size of the number of items possible for this block's work - * function. If is_set_max_notput_items() returns 'false', then the - * scheduler ignores the internal value and uses the value set - * globally in the top_block. - * - * Use this value to clear the 'is_set' flag so the scheduler will - * ignore this. Use the set_max_noutput_items(m) call to both set a - * new value for max_noutput_items and to reenable its use in the - * scheduler. - */ - void unset_max_noutput_items(); - - /*! - * \brief Ask the block if the flag is or is not set to use the - * internal value of max_noutput_items during a call to work. - */ - bool is_set_max_noutput_items(); - - /* - * Used to expand the vectors that hold the min/max buffer sizes. - * - * Specifically, when -1 is used, the vectors are just initialized - * with 1 value; this is used by the flat_flowgraph to expand when - * required to add a new value for new ports on these blocks. - */ - void expand_minmax_buffer(int port) { - if((size_t)port >= d_max_output_buffer.size()) - set_max_output_buffer(port, -1); - if((size_t)port >= d_min_output_buffer.size()) - set_min_output_buffer(port, -1); - } - - /*! - * \brief Returns max buffer size on output port \p i. - */ - long max_output_buffer(size_t i) { - if(i >= d_max_output_buffer.size()) - throw std::invalid_argument("gr_basic_block::max_output_buffer: port out of range."); - return d_max_output_buffer[i]; - } - - /*! - * \brief Sets max buffer size on all output ports. - */ - void set_max_output_buffer(long max_output_buffer) { - for(int i = 0; i < output_signature()->max_streams(); i++) { - set_max_output_buffer(i, max_output_buffer); - } - } - - /*! - * \brief Sets max buffer size on output port \p port. - */ - void set_max_output_buffer(int port, long max_output_buffer) { - if((size_t)port >= d_max_output_buffer.size()) - d_max_output_buffer.push_back(max_output_buffer); - else - d_max_output_buffer[port] = max_output_buffer; - } - - /*! - * \brief Returns min buffer size on output port \p i. - */ - long min_output_buffer(size_t i) { - if(i >= d_min_output_buffer.size()) - throw std::invalid_argument("gr_basic_block::min_output_buffer: port out of range."); - return d_min_output_buffer[i]; - } - - /*! - * \brief Sets min buffer size on all output ports. - */ - void set_min_output_buffer(long min_output_buffer) { - for(int i=0; i<output_signature()->max_streams(); i++) { - set_min_output_buffer(i, min_output_buffer); - } - } - - /*! - * \brief Sets min buffer size on output port \p port. - */ - void set_min_output_buffer(int port, long min_output_buffer) { - if((size_t)port >= d_min_output_buffer.size()) - d_min_output_buffer.push_back(min_output_buffer); - else - d_min_output_buffer[port] = min_output_buffer; - } - - // --------------- Performance counter functions ------------- - - /*! - * \brief Gets instantaneous noutput_items performance counter. - */ - float pc_noutput_items(); - - /*! - * \brief Gets average noutput_items performance counter. - */ - float pc_noutput_items_avg(); - - /*! - * \brief Gets variance of noutput_items performance counter. - */ - float pc_noutput_items_var(); - - /*! - * \brief Gets instantaneous num items produced performance counter. - */ - float pc_nproduced(); - - /*! - * \brief Gets average num items produced performance counter. - */ - float pc_nproduced_avg(); - - /*! - * \brief Gets variance of num items produced performance counter. - */ - float pc_nproduced_var(); - - /*! - * \brief Gets instantaneous fullness of \p which input buffer. - */ - float pc_input_buffers_full(int which); - - /*! - * \brief Gets average fullness of \p which input buffer. - */ - float pc_input_buffers_full_avg(int which); - - /*! - * \brief Gets variance of fullness of \p which input buffer. - */ - float pc_input_buffers_full_var(int which); - - /*! - * \brief Gets instantaneous fullness of all input buffers. - */ - std::vector<float> pc_input_buffers_full(); - - /*! - * \brief Gets average fullness of all input buffers. - */ - std::vector<float> pc_input_buffers_full_avg(); - - /*! - * \brief Gets variance of fullness of all input buffers. - */ - std::vector<float> pc_input_buffers_full_var(); - - /*! - * \brief Gets instantaneous fullness of \p which input buffer. - */ - float pc_output_buffers_full(int which); - - /*! - * \brief Gets average fullness of \p which input buffer. - */ - float pc_output_buffers_full_avg(int which); - - /*! - * \brief Gets variance of fullness of \p which input buffer. - */ - float pc_output_buffers_full_var(int which); - - /*! - * \brief Gets instantaneous fullness of all output buffers. - */ - std::vector<float> pc_output_buffers_full(); - - /*! - * \brief Gets average fullness of all output buffers. - */ - std::vector<float> pc_output_buffers_full_avg(); - - /*! - * \brief Gets variance of fullness of all output buffers. - */ - std::vector<float> pc_output_buffers_full_var(); - - /*! - * \brief Gets instantaneous clock cycles spent in work. - */ - float pc_work_time(); - - /*! - * \brief Gets average clock cycles spent in work. - */ - float pc_work_time_avg(); - - /*! - * \brief Gets average clock cycles spent in work. - */ - float pc_work_time_var(); - - /*! - * \brief Resets the performance counters - */ - void reset_perf_counters(); - - /*! - * \brief Sets up export of perf. counters to ControlPort. Only - * called by the scheduler. - */ - void setup_pc_rpc(); - - /*! - * \brief Checks if this block is already exporting perf. counters - * to ControlPort. - */ - bool is_pc_rpc_set() { return d_pc_rpc_set; } - - /*! - * \brief If the block calls this in its constructor, it's - * perf. counters will not be exported. - */ - void no_pc_rpc() { d_pc_rpc_set = true; } - - - // ---------------------------------------------------------------------------- - // Functions to handle thread affinity - - /*! - * \brief Set the thread's affinity to processor core \p n. - * - * \param mask a vector of ints of the core numbers available to this block. - */ - void set_processor_affinity(const std::vector<int> &mask); - - /*! - * \brief Remove processor affinity to a specific core. - */ - void unset_processor_affinity(); - - /*! - * \brief Get the current processor affinity. - */ - std::vector<int> processor_affinity() { return d_affinity; } - - // ---------------------------------------------------------------------------- - - private: - - int d_output_multiple; - bool d_output_multiple_set; - int d_unaligned; - bool d_is_unaligned; - double d_relative_rate; // approx output_rate / input_rate - gr_block_detail_sptr d_detail; // implementation details - unsigned d_history; - bool d_fixed_rate; - bool d_max_noutput_items_set; // if d_max_noutput_items is valid - int d_max_noutput_items; // value of max_noutput_items for this block - int d_min_noutput_items; - tag_propagation_policy_t d_tag_propagation_policy; // policy for moving tags downstream - std::vector<int> d_affinity; // thread affinity proc. mask - bool d_pc_rpc_set; - - protected: - gr_block (void){} //allows pure virtual interface sub-classes - gr_block (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature); - - void set_fixed_rate(bool fixed_rate){ d_fixed_rate = fixed_rate; } - - - /*! - * \brief Adds a new tag onto the given output buffer. - * - * \param which_output an integer of which output stream to attach the tag - * \param abs_offset a uint64 number of the absolute item number - * assicated with the tag. Can get from nitems_written. - * \param key the tag key as a PMT symbol - * \param value any PMT holding any value for the given key - * \param srcid optional source ID specifier; defaults to PMT_F - */ - inline void add_item_tag(unsigned int which_output, - uint64_t abs_offset, - const pmt::pmt_t &key, - const pmt::pmt_t &value, - const pmt::pmt_t &srcid=pmt::PMT_F) - { - gr_tag_t tag; - tag.offset = abs_offset; - tag.key = key; - tag.value = value; - tag.srcid = srcid; - this->add_item_tag(which_output, tag); - } - - /*! - * \brief Adds a new tag onto the given output buffer. - * - * \param which_output an integer of which output stream to attach the tag - * \param tag the tag object to add - */ - void add_item_tag(unsigned int which_output, const gr_tag_t &tag); - - /*! - * \brief Removes a tag from the given input buffer. - * - * \param which_input an integer of which input stream to remove the tag from - * \param abs_offset a uint64 number of the absolute item number - * assicated with the tag. Can get from nitems_written. - * \param key the tag key as a PMT symbol - * \param value any PMT holding any value for the given key - * \param srcid optional source ID specifier; defaults to PMT_F - * - * If no such tag is found, does nothing. - */ - inline void remove_item_tag(unsigned int which_input, - uint64_t abs_offset, - const pmt::pmt_t &key, - const pmt::pmt_t &value, - const pmt::pmt_t &srcid=pmt::PMT_F) - { - gr_tag_t tag; - tag.offset = abs_offset; - tag.key = key; - tag.value = value; - tag.srcid = srcid; - this->remove_item_tag(which_input, tag); - } - - /*! - * \brief Removes a tag from the given input buffer. - * - * If no such tag is found, does nothing. - * - * \param which_input an integer of which input stream to remove the tag from - * \param tag the tag object to remove - */ - void remove_item_tag(unsigned int which_input, const gr_tag_t &tag); - - /*! - * \brief Given a [start,end), returns a vector of all tags in the range. - * - * Range of counts is from start to end-1. - * - * Tags are tuples of: - * (item count, source id, key, value) - * - * \param v a vector reference to return tags into - * \param which_input an integer of which input stream to pull from - * \param abs_start a uint64 count of the start of the range of interest - * \param abs_end a uint64 count of the end of the range of interest - */ - void get_tags_in_range(std::vector<gr_tag_t> &v, - unsigned int which_input, - uint64_t abs_start, - uint64_t abs_end); - - /*! - * \brief Given a [start,end), returns a vector of all tags in the range - * with a given key. - * - * Range of counts is from start to end-1. - * - * Tags are tuples of: - * (item count, source id, key, value) - * - * \param v a vector reference to return tags into - * \param which_input an integer of which input stream to pull from - * \param abs_start a uint64 count of the start of the range of interest - * \param abs_end a uint64 count of the end of the range of interest - * \param key a PMT symbol key to filter only tags of this key - */ - void get_tags_in_range(std::vector<gr_tag_t> &v, - unsigned int which_input, - uint64_t abs_start, - uint64_t abs_end, - const pmt::pmt_t &key); - - std::vector<long> d_max_output_buffer; - std::vector<long> d_min_output_buffer; - - /*! Used by block's setters and work functions to make - * setting/resetting of parameters thread-safe. - * - * Used by calling gr::thread::scoped_lock l(d_setlock); - */ - gr::thread::mutex d_setlock; - - /*! Used by blocks to access the logger system. - */ - gr_logger_ptr d_logger; - gr_logger_ptr d_debug_logger; - - // These are really only for internal use, but leaving them public avoids - // having to work up an ever-varying list of friend GR_RUNTIME_APIs - - public: - gr_block_detail_sptr detail () const { return d_detail; } - void set_detail (gr_block_detail_sptr detail) { d_detail = detail; } -}; - -typedef std::vector<gr_block_sptr> gr_block_vector_t; -typedef std::vector<gr_block_sptr>::iterator gr_block_viter_t; - -inline gr_block_sptr cast_to_block_sptr(gr_basic_block_sptr p) -{ - return boost::dynamic_pointer_cast<gr_block, gr_basic_block>(p); -} - - -std::ostream& -operator << (std::ostream& os, const gr_block *m); - -#endif /* INCLUDED_GR_BLOCK_H */ diff --git a/gnuradio-runtime/include/gr_block_detail.h b/gnuradio-runtime/include/gr_block_detail.h deleted file mode 100644 index 14886c0a74..0000000000 --- a/gnuradio-runtime/include/gr_block_detail.h +++ /dev/null @@ -1,248 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2009,2010 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 3, 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 detail. - * - * You should have received a copy of the GNU General Public License - * along with GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_BLOCK_DETAIL_H -#define INCLUDED_GR_BLOCK_DETAIL_H - -#include <gr_runtime_api.h> -#include <gr_runtime_types.h> -#include <gr_tpb_detail.h> -#include <gr_tags.h> -#include <high_res_timer.h> -#include <stdexcept> - -/*! - * \brief Implementation details to support the signal processing abstraction - * \ingroup internal - * - * This class contains implementation detail that should be "out of sight" - * of almost all users of GNU Radio. This decoupling also means that - * we can make changes to the guts without having to recompile everything. - */ -class GR_RUNTIME_API gr_block_detail { - public: - ~gr_block_detail (); - - int ninputs () const { return d_ninputs; } - int noutputs () const { return d_noutputs; } - bool sink_p () const { return d_noutputs == 0; } - bool source_p () const { return d_ninputs == 0; } - - void set_done (bool done); - bool done () const { return d_done; } - - void set_input (unsigned int which, gr_buffer_reader_sptr reader); - gr_buffer_reader_sptr input (unsigned int which) - { - if (which >= d_ninputs) - throw std::invalid_argument ("gr_block_detail::input"); - return d_input[which]; - } - - void set_output (unsigned int which, gr_buffer_sptr buffer); - gr_buffer_sptr output (unsigned int which) - { - if (which >= d_noutputs) - throw std::invalid_argument ("gr_block_detail::output"); - return d_output[which]; - } - - /*! - * \brief Tell the scheduler \p how_many_items of input stream \p which_input were consumed. - */ - void consume (int which_input, int how_many_items); - - /*! - * \brief Tell the scheduler \p how_many_items were consumed on each input stream. - */ - void consume_each (int how_many_items); - - /*! - * \brief Tell the scheduler \p how_many_items were produced on output stream \p which_output. - */ - void produce (int which_output, int how_many_items); - - /*! - * \brief Tell the scheduler \p how_many_items were produced on each output stream. - */ - void produce_each (int how_many_items); - - // Return the number of items read on input stream which_input - uint64_t nitems_read(unsigned int which_input); - - // Return the number of items written on output stream which_output - uint64_t nitems_written(unsigned int which_output); - - - /*! - * \brief Adds a new tag to the given output stream. - * - * Calls gr_buffer::add_item_tag(), - * which appends the tag onto its deque. - * - * \param which_output an integer of which output stream to attach the tag - * \param tag the tag object to add - */ - void add_item_tag(unsigned int which_output, const gr_tag_t &tag); - - /*! - * \brief Removes a tag from the given input stream. - * - * Calls gr_buffer::remove_item_tag(), which removes the tag from its deque. - * - * \param which_input an integer of which input stream to remove the tag from - * \param tag the tag object to add - */ - void remove_item_tag(unsigned int which_input, const gr_tag_t &tag); - - /*! - * \brief Given a [start,end), returns a vector of all tags in the range. - * - * Pass-through function to gr_buffer_reader to get a vector of tags - * in given range. Range of counts is from start to end-1. - * - * Tags are tuples of: - * (item count, source id, key, value) - * - * \param v a vector reference to return tags into - * \param which_input an integer of which input stream to pull from - * \param abs_start a uint64 count of the start of the range of interest - * \param abs_end a uint64 count of the end of the range of interest - */ - void get_tags_in_range(std::vector<gr_tag_t> &v, - unsigned int which_input, - uint64_t abs_start, - uint64_t abs_end); - - /*! - * \brief Given a [start,end), returns a vector of all tags in the range - * with a given key. - * - * Calls get_tags_in_range(which_input, abs_start, abs_end) to get a vector of - * tags from the buffers. This function then provides a secondary filter to - * the tags to extract only tags with the given 'key'. - * - * Tags are tuples of: - * (item count, source id, key, value) - * - * \param v a vector reference to return tags into - * \param which_input an integer of which input stream to pull from - * \param abs_start a uint64 count of the start of the range of interest - * \param abs_end a uint64 count of the end of the range of interest - * \param key a PMT symbol to select only tags of this key - */ - void get_tags_in_range(std::vector<gr_tag_t> &v, - unsigned int which_input, - uint64_t abs_start, - uint64_t abs_end, - const pmt::pmt_t &key); - - /*! - * \brief Set core affinity of block to the cores in the vector mask. - * - * \param mask a vector of ints of the core numbers available to this block. - */ - void set_processor_affinity(const std::vector<int> &mask); - - /*! - * \brief Unset core affinity. - */ - void unset_processor_affinity(); - - bool threaded; // set if thread is currently running. - gr::thread::gr_thread_t thread; // portable thread handle - - void start_perf_counters(); - void stop_perf_counters(int noutput_items, int nproduced); - void reset_perf_counters(); - - // Calls to get performance counter items - float pc_noutput_items(); - float pc_nproduced(); - float pc_input_buffers_full(size_t which); - std::vector<float> pc_input_buffers_full(); - float pc_output_buffers_full(size_t which); - std::vector<float> pc_output_buffers_full(); - float pc_work_time(); - - float pc_noutput_items_avg(); - float pc_nproduced_avg(); - float pc_input_buffers_full_avg(size_t which); - std::vector<float> pc_input_buffers_full_avg(); - float pc_output_buffers_full_avg(size_t which); - std::vector<float> pc_output_buffers_full_avg(); - float pc_work_time_avg(); - - float pc_noutput_items_var(); - float pc_nproduced_var(); - float pc_input_buffers_full_var(size_t which); - std::vector<float> pc_input_buffers_full_var(); - float pc_output_buffers_full_var(size_t which); - std::vector<float> pc_output_buffers_full_var(); - float pc_work_time_var(); - - gr_tpb_detail d_tpb; // used by thread-per-block scheduler - int d_produce_or; - - // ---------------------------------------------------------------------------- - - private: - unsigned int d_ninputs; - unsigned int d_noutputs; - std::vector<gr_buffer_reader_sptr> d_input; - std::vector<gr_buffer_sptr> d_output; - bool d_done; - - // Performance counters - float d_ins_noutput_items; - float d_avg_noutput_items; - float d_var_noutput_items; - float d_ins_nproduced; - float d_avg_nproduced; - float d_var_nproduced; - std::vector<float> d_ins_input_buffers_full; - std::vector<float> d_avg_input_buffers_full; - std::vector<float> d_var_input_buffers_full; - std::vector<float> d_ins_output_buffers_full; - std::vector<float> d_avg_output_buffers_full; - std::vector<float> d_var_output_buffers_full; - gr::high_res_timer_type d_start_of_work, d_end_of_work; - float d_ins_work_time; - float d_avg_work_time; - float d_var_work_time; - float d_pc_counter; - - gr_block_detail (unsigned int ninputs, unsigned int noutputs); - - friend struct gr_tpb_detail; - - friend GR_RUNTIME_API gr_block_detail_sptr - gr_make_block_detail (unsigned int ninputs, unsigned int noutputs); -}; - -GR_RUNTIME_API gr_block_detail_sptr -gr_make_block_detail (unsigned int ninputs, unsigned int noutputs); - -GR_RUNTIME_API long -gr_block_detail_ncurrently_allocated (); - -#endif /* INCLUDED_GR_BLOCK_DETAIL_H */ diff --git a/gnuradio-runtime/include/gr_block_registry.h b/gnuradio-runtime/include/gr_block_registry.h deleted file mode 100644 index 9b038287bc..0000000000 --- a/gnuradio-runtime/include/gr_block_registry.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef GR_BLOCK_REGISTRY_H -#define GR_BLOCK_REGISTRY_H - -#include <gr_runtime_api.h> -#include <map> -#include <gr_basic_block.h> - -#ifndef GR_BASIC_BLOCK_H -class gr_basic_block; -class gr_block; -#endif - -class GR_RUNTIME_API gr_block_registry { - public: - gr_block_registry(); - - long block_register(gr_basic_block* block); - void block_unregister(gr_basic_block* block); - - std::string register_symbolic_name(gr_basic_block* block); - void register_symbolic_name(gr_basic_block* block, std::string name); - - gr_basic_block_sptr block_lookup(pmt::pmt_t symbol); - - void register_primitive(std::string blk, gr_block* ref); - void unregister_primitive(std::string blk); - void notify_blk(std::string blk); - - private: - - //typedef std::map< long, gr_basic_block_sptr > blocksubmap_t; - typedef std::map< long, gr_basic_block* > blocksubmap_t; - typedef std::map< std::string, blocksubmap_t > blockmap_t; - - blockmap_t d_map; - pmt::pmt_t d_ref_map; - std::map< std::string, gr_block*> primitive_map; - -}; - -GR_RUNTIME_API extern gr_block_registry global_block_registry; - -#endif - diff --git a/gnuradio-runtime/include/gr_buffer.h b/gnuradio-runtime/include/gr_buffer.h deleted file mode 100644 index 810879b7ea..0000000000 --- a/gnuradio-runtime/include/gr_buffer.h +++ /dev/null @@ -1,309 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2009,2010,2011 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_BUFFER_H -#define INCLUDED_GR_BUFFER_H - -#include <gr_runtime_api.h> -#include <gr_runtime_types.h> -#include <boost/weak_ptr.hpp> -#include <thread/thread.h> -#include <gr_tags.h> -#include <deque> - -class gr_vmcircbuf; - -/*! - * \brief Allocate a buffer that holds at least \p nitems of size \p sizeof_item. - * - * The total size of the buffer will be rounded up to a system - * dependent boundary. This is typically the system page size, but - * under MS windows is 64KB. - * - * \param nitems is the minimum number of items the buffer will hold. - * \param sizeof_item is the size of an item in bytes. - * \param link is the block that writes to this buffer. - */ -GR_RUNTIME_API gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item, gr_block_sptr link=gr_block_sptr()); - - -/*! - * \brief Single writer, multiple reader fifo. - * \ingroup internal - */ -class GR_RUNTIME_API gr_buffer { - public: - - virtual ~gr_buffer (); - - /*! - * \brief return number of items worth of space available for writing - */ - int space_available (); - - /*! - * \brief return size of this buffer in items - */ - int bufsize() const { return d_bufsize; } - - /*! - * \brief return pointer to write buffer. - * - * The return value points at space that can hold at least - * space_available() items. - */ - void *write_pointer (); - - /*! - * \brief tell buffer that we wrote \p nitems into it - */ - void update_write_pointer (int nitems); - - void set_done (bool done); - bool done () const { return d_done; } - - /*! - * \brief Return the block that writes to this buffer. - */ - gr_block_sptr link() { return gr_block_sptr(d_link); } - - size_t nreaders() const { return d_readers.size(); } - gr_buffer_reader* reader(size_t index) { return d_readers[index]; } - - gr::thread::mutex *mutex() { return &d_mutex; } - - uint64_t nitems_written() { return d_abs_write_offset; } - - size_t get_sizeof_item() { return d_sizeof_item; } - - /*! - * \brief Adds a new tag to the buffer. - * - * \param tag the new tag - */ - void add_item_tag(const gr_tag_t &tag); - - /*! - * \brief Removes an existing tag from the buffer. - * - * If no such tag is found, does nothing. - * - * \param tag the tag that needs to be removed - */ - void remove_item_tag(const gr_tag_t &tag); - - /*! - * \brief Removes all tags before \p max_time from buffer - * - * \param max_time the time (item number) to trim up until. - */ - void prune_tags(uint64_t max_time); - - std::deque<gr_tag_t>::iterator get_tags_begin() { return d_item_tags.begin(); } - std::deque<gr_tag_t>::iterator get_tags_end() { return d_item_tags.end(); } - - // ------------------------------------------------------------------------- - - private: - - friend class gr_buffer_reader; - friend GR_RUNTIME_API gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item, gr_block_sptr link); - friend GR_RUNTIME_API gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link); - - protected: - char *d_base; // base address of buffer - unsigned int d_bufsize; // in items - private: - gr_vmcircbuf *d_vmcircbuf; - size_t d_sizeof_item; // in bytes - std::vector<gr_buffer_reader *> d_readers; - boost::weak_ptr<gr_block> d_link; // block that writes to this buffer - - // - // The mutex protects d_write_index, d_abs_write_offset, d_done, d_item_tags - // and the d_read_index's and d_abs_read_offset's in the buffer readers. - // - gr::thread::mutex d_mutex; - unsigned int d_write_index; // in items [0,d_bufsize) - uint64_t d_abs_write_offset; // num items written since the start - bool d_done; - std::deque<gr_tag_t> d_item_tags; - uint64_t d_last_min_items_read; - - unsigned - index_add (unsigned a, unsigned b) - { - unsigned s = a + b; - - if (s >= d_bufsize) - s -= d_bufsize; - - assert (s < d_bufsize); - return s; - } - - unsigned - index_sub (unsigned a, unsigned b) - { - int s = a - b; - - if (s < 0) - s += d_bufsize; - - assert ((unsigned) s < d_bufsize); - return s; - } - - virtual bool allocate_buffer (int nitems, size_t sizeof_item); - - /*! - * \brief constructor is private. Use gr_make_buffer to create instances. - * - * Allocate a buffer that holds at least \p nitems of size \p sizeof_item. - * - * \param nitems is the minimum number of items the buffer will hold. - * \param sizeof_item is the size of an item in bytes. - * \param link is the block that writes to this buffer. - * - * The total size of the buffer will be rounded up to a system - * dependent boundary. This is typically the system page size, but - * under MS windows is 64KB. - */ - gr_buffer (int nitems, size_t sizeof_item, gr_block_sptr link); - - /*! - * \brief disassociate \p reader from this buffer - */ - void drop_reader (gr_buffer_reader *reader); - -}; - -/*! - * \brief Create a new gr_buffer_reader and attach it to buffer \p buf - * \param buf is the buffer the \p gr_buffer_reader reads from. - * \param nzero_preload -- number of zero items to "preload" into buffer. - * \param link is the block that reads from the buffer using this gr_buffer_reader. - */ -GR_RUNTIME_API gr_buffer_reader_sptr -gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link=gr_block_sptr()); - -//! returns # of gr_buffers currently allocated -GR_RUNTIME_API long gr_buffer_ncurrently_allocated (); - - -// --------------------------------------------------------------------------- - -/*! - * \brief How we keep track of the readers of a gr_buffer. - * \ingroup internal - */ - -class GR_RUNTIME_API gr_buffer_reader { - public: - - ~gr_buffer_reader (); - - /*! - * \brief Return number of items available for reading. - */ - int items_available () const; - - /*! - * \brief Return buffer this reader reads from. - */ - gr_buffer_sptr buffer () const { return d_buffer; } - - - /*! - * \brief Return maximum number of items that could ever be available for reading. - * This is used as a sanity check in the scheduler to avoid looping forever. - */ - int max_possible_items_available () const { return d_buffer->d_bufsize - 1; } - - /*! - * \brief return pointer to read buffer. - * - * The return value points to items_available() number of items - */ - const void *read_pointer (); - - /* - * \brief tell buffer we read \p items from it - */ - void update_read_pointer (int nitems); - - void set_done (bool done) { d_buffer->set_done (done); } - bool done () const { return d_buffer->done (); } - - gr::thread::mutex *mutex() { return d_buffer->mutex(); } - - - uint64_t nitems_read() { return d_abs_read_offset; } - - size_t get_sizeof_item() { return d_buffer->get_sizeof_item(); } - - /*! - * \brief Return the block that reads via this reader. - * - */ - gr_block_sptr link() { return gr_block_sptr(d_link); } - - - /*! - * \brief Given a [start,end), returns a vector all tags in the range. - * - * Get a vector of tags in given range. Range of counts is from start to end-1. - * - * Tags are tuples of: - * (item count, source id, key, value) - * - * \param v a vector reference to return tags into - * \param abs_start a uint64 count of the start of the range of interest - * \param abs_end a uint64 count of the end of the range of interest - */ - void get_tags_in_range(std::vector<gr_tag_t> &v, - uint64_t abs_start, - uint64_t abs_end); - - // ------------------------------------------------------------------------- - - private: - - friend class gr_buffer; - friend GR_RUNTIME_API gr_buffer_reader_sptr - gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link); - - - gr_buffer_sptr d_buffer; - unsigned int d_read_index; // in items [0,d->buffer.d_bufsize) - uint64_t d_abs_read_offset; // num items seen since the start - boost::weak_ptr<gr_block> d_link; // block that reads via this buffer reader - - //! constructor is private. Use gr_buffer::add_reader to create instances - gr_buffer_reader (gr_buffer_sptr buffer, unsigned int read_index, gr_block_sptr link); -}; - -//! returns # of gr_buffer_readers currently allocated -GR_RUNTIME_API long gr_buffer_reader_ncurrently_allocated (); - - -#endif /* INCLUDED_GR_BUFFER_H */ diff --git a/gnuradio-runtime/include/gr_dispatcher.h b/gnuradio-runtime/include/gr_dispatcher.h deleted file mode 100644 index 7a9e80c9fe..0000000000 --- a/gnuradio-runtime/include/gr_dispatcher.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_DISPATCHER_H -#define INCLUDED_GR_DISPATCHER_H - -#include <gr_runtime_api.h> -#include <gr_select_handler.h> -#include <vector> - -class gr_dispatcher; -typedef boost::shared_ptr<gr_dispatcher> gr_dispatcher_sptr; - -GR_RUNTIME_API gr_dispatcher_sptr gr_dispatcher_singleton(); -GR_RUNTIME_API gr_dispatcher_sptr gr_make_dispatcher(); - -/*! - * \brief invoke callbacks based on select. - * \ingroup internal - * - * \sa gr_select_handler - */ -class GR_RUNTIME_API gr_dispatcher -{ - gr_dispatcher(); - friend GR_RUNTIME_API gr_dispatcher_sptr gr_make_dispatcher(); - - std::vector<gr_select_handler_sptr> d_handler; - int d_max_index; - -public: - ~gr_dispatcher(); - - bool add_handler(gr_select_handler_sptr handler); - bool del_handler(gr_select_handler_sptr handler); - bool del_handler(gr_select_handler *handler); - - /*! - * \brief Event dispatching loop. - * - * Enter a polling loop that only terminates after all gr_select_handlers - * have been removed. \p timeout sets the timeout parameter to the select() - * call, measured in seconds. - * - * \param timeout maximum number of seconds to block in select. - */ - void loop(double timeout=10); -}; - -#endif /* INCLUDED_GR_DISPATCHER_H */ diff --git a/gnuradio-runtime/include/gr_error_handler.h b/gnuradio-runtime/include/gr_error_handler.h deleted file mode 100644 index 4d326a6ba1..0000000000 --- a/gnuradio-runtime/include/gr_error_handler.h +++ /dev/null @@ -1,117 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -/* - * This code is based on error.hh from the "Click Modular Router". - * Original copyright follows: - */ -/* - * error.{cc,hh} -- flexible classes for error reporting - * Eddie Kohler - * - * Copyright (c) 1999-2000 Massachusetts Institute of Technology - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, subject to the conditions - * listed in the Click LICENSE file. These conditions include: you must - * preserve this copyright notice, and you cannot mention the copyright - * holders in advertising related to the Software without their permission. - * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This - * notice is a summary of the Click LICENSE file; the license in that file is - * legally binding. - */ - -#ifndef INCLUDED_GR_ERROR_HANDLER_H -#define INCLUDED_GR_ERROR_HANDLER_H - -#include <gr_runtime_api.h> -#include <stdarg.h> -#include <string> -#include <cstdio> // for FILE - -/*! - * \brief abstract error handler - * \ingroup base - */ -class GR_RUNTIME_API gr_error_handler { -public: - enum seriousness { - ERR_DEBUG = 0x00000000, - ERR_MESSAGE = 0x00010000, - ERR_WARNING = 0x00020000, - ERR_ERROR = 0x00030000, - ERR_FATAL = 0x00040000 - }; - - gr_error_handler() {} - virtual ~gr_error_handler(); - - static gr_error_handler *default_handler(); - static gr_error_handler *silent_handler(); - - static bool has_default_handler(); - static void set_default_handler(gr_error_handler *errh); - - void debug(const char *format, ...); - void message(const char *format, ...); - void warning(const char *format, ...); - void error(const char *format, ...); - void fatal(const char *format, ...); - - virtual int nwarnings() const = 0; - virtual int nerrors() const = 0; - virtual void reset_counts() = 0; - - void verror(seriousness s, const char *format, va_list); - void verror_text(seriousness s, const std::string &text); - -protected: - virtual void count_error(seriousness s) = 0; - virtual void handle_text(seriousness s, const std::string &str) = 0; - std::string make_text(seriousness s, const char *format, va_list); -}; - - -class GR_RUNTIME_API gr_base_error_handler : public gr_error_handler { - int d_nwarnings; - int d_nerrors; - -public: - gr_base_error_handler() : d_nwarnings(0), d_nerrors(0) {} - int nwarnings() const { return d_nwarnings; } - int nerrors() const { return d_nerrors; } - void reset_counts() { d_nwarnings = d_nerrors = 0; } - void count_error(seriousness s); -}; - -class GR_RUNTIME_API gr_file_error_handler : public gr_base_error_handler { - FILE *d_file; - int d_fd; -public: - gr_file_error_handler(FILE *file); - gr_file_error_handler(int file_descriptor); - ~gr_file_error_handler(); - - void handle_text(seriousness s, const std::string &str); -}; - -#endif /* INCLUDED_GR_ERROR_HANDLER_H */ diff --git a/gnuradio-runtime/include/gr_feval.h b/gnuradio-runtime/include/gr_feval.h deleted file mode 100644 index 07df592e58..0000000000 --- a/gnuradio-runtime/include/gr_feval.h +++ /dev/null @@ -1,177 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_FEVAL_H -#define INCLUDED_GR_FEVAL_H - -#include <gr_runtime_api.h> -#include <gr_complex.h> -#include <pmt/pmt.h> - -/*! - * \brief base class for evaluating a function: double -> double - * \ingroup misc - * - * This class is designed to be subclassed in Python or C++ - * and is callable from both places. It uses SWIG's - * "director" feature to implement the magic. - * It's slow. Don't use it in a performance critical path. - * - * Override eval to define the behavior. - * Use calleval to invoke eval (this kludge is required to allow a - * python specific "shim" to be inserted. - */ -class GR_RUNTIME_API gr_feval_dd -{ -protected: - /*! - * \brief override this to define the function - */ - virtual double eval(double x); - -public: - gr_feval_dd() {} - virtual ~gr_feval_dd(); - - virtual double calleval(double x); // invoke "eval" -}; - -/*! - * \brief base class for evaluating a function: complex -> complex - * \ingroup misc - * - * This class is designed to be subclassed in Python or C++ - * and is callable from both places. It uses SWIG's - * "director" feature to implement the magic. - * It's slow. Don't use it in a performance critical path. - * - * Override eval to define the behavior. - * Use calleval to invoke eval (this kludge is required to allow a - * python specific "shim" to be inserted. - */ -class GR_RUNTIME_API gr_feval_cc -{ -protected: - /*! - * \brief override this to define the function - */ - virtual gr_complex eval(gr_complex x); - -public: - gr_feval_cc() {} - virtual ~gr_feval_cc(); - - virtual gr_complex calleval(gr_complex x); // invoke "eval" -}; - -/*! - * \brief base class for evaluating a function: long -> long - * \ingroup misc - * - * This class is designed to be subclassed in Python or C++ - * and is callable from both places. It uses SWIG's - * "director" feature to implement the magic. - * It's slow. Don't use it in a performance critical path. - * - * Override eval to define the behavior. - * Use calleval to invoke eval (this kludge is required to allow a - * python specific "shim" to be inserted. - */ -class GR_RUNTIME_API gr_feval_ll -{ -protected: - /*! - * \brief override this to define the function - */ - virtual long eval(long x); - -public: - gr_feval_ll() {} - virtual ~gr_feval_ll(); - - virtual long calleval(long x); // invoke "eval" -}; - -/*! - * \brief base class for evaluating a function: void -> void - * \ingroup misc - * - * This class is designed to be subclassed in Python or C++ - * and is callable from both places. It uses SWIG's - * "director" feature to implement the magic. - * It's slow. Don't use it in a performance critical path. - * - * Override eval to define the behavior. - * Use calleval to invoke eval (this kludge is required to allow a - * python specific "shim" to be inserted. - */ -class GR_RUNTIME_API gr_feval -{ -protected: - /*! - * \brief override this to define the function - */ - virtual void eval(); - -public: - gr_feval() {} - virtual ~gr_feval(); - - virtual void calleval(); // invoke "eval" -}; - -/*! - * \brief base class for evaluating a function: pmt -> void - * \ingroup misc - * - * This class is designed to be subclassed in Python or C++ - * and is callable from both places. It uses SWIG's - * "director" feature to implement the magic. - * It's slow. Don't use it in a performance critical path. - * - * Override eval to define the behavior. - * Use calleval to invoke eval (this kludge is required to allow a - * python specific "shim" to be inserted. - */ -class GR_RUNTIME_API gr_feval_p -{ -protected: - /*! - * \brief override this to define the function - */ - virtual void eval(pmt::pmt_t x); - -public: - gr_feval_p() {} - virtual ~gr_feval_p(); - - virtual void calleval(pmt::pmt_t x); // invoke "eval" -}; - -/*! - * \brief trivial examples / test cases showing C++ calling Python code - */ -GR_RUNTIME_API double gr_feval_dd_example(gr_feval_dd *f, double x); -GR_RUNTIME_API gr_complex gr_feval_cc_example(gr_feval_cc *f, gr_complex x); -GR_RUNTIME_API long gr_feval_ll_example(gr_feval_ll *f, long x); -GR_RUNTIME_API void gr_feval_example(gr_feval *f); - -#endif /* INCLUDED_GR_FEVAL_H */ diff --git a/gnuradio-runtime/include/gr_flowgraph.h b/gnuradio-runtime/include/gr_flowgraph.h deleted file mode 100644 index 107c50b7b6..0000000000 --- a/gnuradio-runtime/include/gr_flowgraph.h +++ /dev/null @@ -1,251 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_FLOWGRAPH_H -#define INCLUDED_GR_FLOWGRAPH_H - -#include <gr_runtime_api.h> -#include <gr_basic_block.h> -#include <iostream> - -/*! - * \brief Class representing a specific input or output graph endpoint - * \ingroup internal - */ -class GR_RUNTIME_API gr_endpoint -{ -private: - gr_basic_block_sptr d_basic_block; - int d_port; - -public: - gr_endpoint() : d_basic_block(), d_port(0) { } - gr_endpoint(gr_basic_block_sptr block, int port) { d_basic_block = block; d_port = port; } - gr_basic_block_sptr block() const { return d_basic_block; } - int port() const { return d_port; } - - bool operator==(const gr_endpoint &other) const; -}; - -inline bool gr_endpoint::operator==(const gr_endpoint &other) const -{ - return (d_basic_block == other.d_basic_block && - d_port == other.d_port); -} - -class GR_RUNTIME_API gr_msg_endpoint -{ -private: - gr_basic_block_sptr d_basic_block; - pmt::pmt_t d_port; - bool d_is_hier; -public: - gr_msg_endpoint() : d_basic_block(), d_port(pmt::PMT_NIL) { } - gr_msg_endpoint(gr_basic_block_sptr block, pmt::pmt_t port, bool is_hier=false){ d_basic_block = block; d_port = port; d_is_hier = is_hier;} - gr_basic_block_sptr block() const { return d_basic_block; } - pmt::pmt_t port() const { return d_port; } - bool is_hier() const { return d_is_hier; } - void set_hier(bool h) { d_is_hier = h; } - - bool operator==(const gr_msg_endpoint &other) const; - -}; - -inline bool gr_msg_endpoint::operator==(const gr_msg_endpoint &other) const -{ - return (d_basic_block == other.d_basic_block && - pmt::equal(d_port, other.d_port)); -} - - -// Hold vectors of gr_endpoint objects -typedef std::vector<gr_endpoint> gr_endpoint_vector_t; -typedef std::vector<gr_endpoint>::iterator gr_endpoint_viter_t; - -/*! - *\brief Class representing a connection between to graph endpoints - * - */ -class GR_RUNTIME_API gr_edge -{ -public: - gr_edge() : d_src(), d_dst() { }; - gr_edge(const gr_endpoint &src, const gr_endpoint &dst) : d_src(src), d_dst(dst) { } - ~gr_edge(); - - const gr_endpoint &src() const { return d_src; } - const gr_endpoint &dst() const { return d_dst; } - -private: - gr_endpoint d_src; - gr_endpoint d_dst; -}; - - -// Hold vectors of gr_edge objects -typedef std::vector<gr_edge> gr_edge_vector_t; -typedef std::vector<gr_edge>::iterator gr_edge_viter_t; - - -/*! - *\brief Class representing a msg connection between to graph msg endpoints - * - */ -class GR_RUNTIME_API gr_msg_edge -{ -public: - gr_msg_edge() : d_src(), d_dst() { }; - gr_msg_edge(const gr_msg_endpoint &src, const gr_msg_endpoint &dst) : d_src(src), d_dst(dst) { } - ~gr_msg_edge() {} - - const gr_msg_endpoint &src() const { return d_src; } - const gr_msg_endpoint &dst() const { return d_dst; } - -private: - gr_msg_endpoint d_src; - gr_msg_endpoint d_dst; -}; - -// Hold vectors of gr_edge objects -typedef std::vector<gr_msg_edge> gr_msg_edge_vector_t; -typedef std::vector<gr_msg_edge>::iterator gr_msg_edge_viter_t; - -// Create a shared pointer to a heap allocated flowgraph -// (types defined in gr_runtime_types.h) -GR_RUNTIME_API gr_flowgraph_sptr gr_make_flowgraph(); - -/*! - * \brief Class representing a directed, acyclic graph of basic blocks - * \ingroup internal - */ -class GR_RUNTIME_API gr_flowgraph -{ -public: - friend GR_RUNTIME_API gr_flowgraph_sptr gr_make_flowgraph(); - - // Destruct an arbitrary flowgraph - ~gr_flowgraph(); - - // Connect two endpoints - void connect(const gr_endpoint &src, const gr_endpoint &dst); - - // Disconnect two endpoints - void disconnect(const gr_endpoint &src, const gr_endpoint &dst); - - // Connect an output port to an input port (convenience) - void connect(gr_basic_block_sptr src_block, int src_port, - gr_basic_block_sptr dst_block, int dst_port); - - // Disconnect an input port from an output port (convenience) - void disconnect(gr_basic_block_sptr src_block, int src_port, - gr_basic_block_sptr dst_block, int dst_port); - - // Connect two msg endpoints - void connect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst); - - // Disconnect two msg endpoints - void disconnect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst); - - // Validate connectivity, raise exception if invalid - void validate(); - - // Clear existing flowgraph - void clear(); - - // Return vector of edges - const gr_edge_vector_t &edges() const { return d_edges; } - - // Return vector of msg edges - const gr_msg_edge_vector_t &msg_edges() const { return d_msg_edges; } - - // Return vector of connected blocks - gr_basic_block_vector_t calc_used_blocks(); - - // Return toplogically sorted vector of blocks. All the sources come first. - gr_basic_block_vector_t topological_sort(gr_basic_block_vector_t &blocks); - - // Return vector of vectors of disjointly connected blocks, topologically - // sorted. - std::vector<gr_basic_block_vector_t> partition(); - -protected: - gr_basic_block_vector_t d_blocks; - gr_edge_vector_t d_edges; - gr_msg_edge_vector_t d_msg_edges; - - gr_flowgraph(); - std::vector<int> calc_used_ports(gr_basic_block_sptr block, bool check_inputs); - gr_basic_block_vector_t calc_downstream_blocks(gr_basic_block_sptr block, int port); - gr_edge_vector_t calc_upstream_edges(gr_basic_block_sptr block); - bool has_block_p(gr_basic_block_sptr block); - gr_edge calc_upstream_edge(gr_basic_block_sptr block, int port); - -private: - - void check_valid_port(gr_io_signature_sptr sig, int port); - void check_valid_port(const gr_msg_endpoint &e); - void check_dst_not_used(const gr_endpoint &dst); - void check_type_match(const gr_endpoint &src, const gr_endpoint &dst); - gr_edge_vector_t calc_connections(gr_basic_block_sptr block, bool check_inputs); // false=use outputs - void check_contiguity(gr_basic_block_sptr block, const std::vector<int> &used_ports, bool check_inputs); - - gr_basic_block_vector_t calc_downstream_blocks(gr_basic_block_sptr block); - gr_basic_block_vector_t calc_reachable_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks); - void reachable_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks); - gr_basic_block_vector_t calc_adjacent_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks); - gr_basic_block_vector_t sort_sources_first(gr_basic_block_vector_t &blocks); - bool source_p(gr_basic_block_sptr block); - void topological_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &output); -}; - -// Convenience functions -inline -void gr_flowgraph::connect(gr_basic_block_sptr src_block, int src_port, - gr_basic_block_sptr dst_block, int dst_port) -{ - connect(gr_endpoint(src_block, src_port), - gr_endpoint(dst_block, dst_port)); -} - -inline -void gr_flowgraph::disconnect(gr_basic_block_sptr src_block, int src_port, - gr_basic_block_sptr dst_block, int dst_port) -{ - disconnect(gr_endpoint(src_block, src_port), - gr_endpoint(dst_block, dst_port)); -} - -inline std::ostream& -operator <<(std::ostream &os, const gr_endpoint endp) -{ - os << endp.block()->alias() << ":" << endp.port(); - return os; -} - -inline std::ostream& -operator <<(std::ostream &os, const gr_edge edge) -{ - os << edge.src() << "->" << edge.dst(); - return os; -} - -#endif /* INCLUDED_GR_FLOWGRAPH_H */ diff --git a/gnuradio-runtime/include/gr_fxpt.h b/gnuradio-runtime/include/gr_fxpt.h deleted file mode 100644 index b7e3518ffb..0000000000 --- a/gnuradio-runtime/include/gr_fxpt.h +++ /dev/null @@ -1,104 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_FXPT_H -#define INCLUDED_GR_FXPT_H - -#include <gr_runtime_api.h> -#include <gr_types.h> - -/*! - * \brief fixed point sine and cosine and friends. - * \ingroup misc - * - * fixed pt radians - * --------- -------- - * -2**31 -pi - * 0 0 - * 2**31-1 pi - epsilon - * - */ -class GR_RUNTIME_API gr_fxpt -{ - static const int WORDBITS = 32; - static const int NBITS = 10; - static const float s_sine_table[1 << NBITS][2]; - static const float PI; - static const float TWO_TO_THE_31; -public: - - static gr_int32 - float_to_fixed (float x) - { - // Fold x into -PI to PI. - int d = (int)floor(x/2/PI+0.5); - x -= d*2*PI; - // And convert to an integer. - return (gr_int32) ((float) x * TWO_TO_THE_31 / PI); - } - - static float - fixed_to_float (gr_int32 x) - { - return x * (PI / TWO_TO_THE_31); - } - - /*! - * \brief Given a fixed point angle x, return float sine (x) - */ - static float - sin (gr_int32 x) - { - gr_uint32 ux = x; - int index = ux >> (WORDBITS - NBITS); - return s_sine_table[index][0] * (ux >> 1) + s_sine_table[index][1]; - } - - /* - * \brief Given a fixed point angle x, return float cosine (x) - */ - static float - cos (gr_int32 x) - { - gr_uint32 ux = x + 0x40000000; - int index = ux >> (WORDBITS - NBITS); - return s_sine_table[index][0] * (ux >> 1) + s_sine_table[index][1]; - } - - /* - * \brief Given a fixedpoint angle x, return float cos(x) and sin (x) - */ - static void sincos(gr_int32 x, float *s, float *c) - { - gr_uint32 ux = x; - int sin_index = ux >> (WORDBITS - NBITS); - *s = s_sine_table[sin_index][0] * (ux >> 1) + s_sine_table[sin_index][1]; - - ux = x + 0x40000000; - int cos_index = ux >> (WORDBITS - NBITS); - *c = s_sine_table[cos_index][0] * (ux >> 1) + s_sine_table[cos_index][1]; - - return; - } - -}; - -#endif /* INCLUDED_GR_FXPT_H */ diff --git a/gnuradio-runtime/include/gr_fxpt_nco.h b/gnuradio-runtime/include/gr_fxpt_nco.h deleted file mode 100644 index 36b99ee132..0000000000 --- a/gnuradio-runtime/include/gr_fxpt_nco.h +++ /dev/null @@ -1,153 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2002,2004 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_FXPT_NCO_H -#define INCLUDED_GR_FXPT_NCO_H - -#include <gr_runtime_api.h> -#include <gr_fxpt.h> -#include <gr_complex.h> - -/*! - * \brief Numerically Controlled Oscillator (NCO) - * \ingroup misc - */ -class /*GR_RUNTIME_API*/ gr_fxpt_nco { - gr_uint32 d_phase; - gr_int32 d_phase_inc; - -public: - gr_fxpt_nco () : d_phase (0), d_phase_inc (0) {} - - ~gr_fxpt_nco () {} - - // radians - void set_phase (float angle) { - d_phase = gr_fxpt::float_to_fixed (angle); - } - - void adjust_phase (float delta_phase) { - d_phase += gr_fxpt::float_to_fixed (delta_phase); - } - - // angle_rate is in radians / step - void set_freq (float angle_rate){ - d_phase_inc = gr_fxpt::float_to_fixed (angle_rate); - } - - // angle_rate is a delta in radians / step - void adjust_freq (float delta_angle_rate) - { - d_phase_inc += gr_fxpt::float_to_fixed (delta_angle_rate); - } - - // increment current phase angle - - void step () - { - d_phase += d_phase_inc; - } - - void step (int n) - { - d_phase += d_phase_inc * n; - } - - // units are radians / step - float get_phase () const { return gr_fxpt::fixed_to_float (d_phase); } - float get_freq () const { return gr_fxpt::fixed_to_float (d_phase_inc); } - - // compute sin and cos for current phase angle - void sincos (float *sinx, float *cosx) const - { - *sinx = gr_fxpt::sin (d_phase); - *cosx = gr_fxpt::cos (d_phase); - } - - // compute cos and sin for a block of phase angles - void sincos (gr_complex *output, int noutput_items, double ampl=1.0) - { - for (int i = 0; i < noutput_items; i++){ - output[i] = gr_complex(gr_fxpt::cos (d_phase) * ampl, gr_fxpt::sin (d_phase) * ampl); - step (); - } - } - - // compute sin for a block of phase angles - void sin (float *output, int noutput_items, double ampl=1.0) - { - for (int i = 0; i < noutput_items; i++){ - output[i] = (float)(gr_fxpt::sin (d_phase) * ampl); - step (); - } - } - - // compute cos for a block of phase angles - void cos (float *output, int noutput_items, double ampl=1.0) - { - for (int i = 0; i < noutput_items; i++){ - output[i] = (float)(gr_fxpt::cos (d_phase) * ampl); - step (); - } - } - - // compute sin for a block of phase angles - void sin (short *output, int noutput_items, double ampl=1.0) - { - for (int i = 0; i < noutput_items; i++){ - output[i] = (short)(gr_fxpt::sin (d_phase) * ampl); - step (); - } - } - - // compute cos for a block of phase angles - void cos (short *output, int noutput_items, double ampl=1.0) - { - for (int i = 0; i < noutput_items; i++){ - output[i] = (short)(gr_fxpt::cos (d_phase) * ampl); - step (); - } - } - - // compute sin for a block of phase angles - void sin (int *output, int noutput_items, double ampl=1.0) - { - for (int i = 0; i < noutput_items; i++){ - output[i] = (int)(gr_fxpt::sin (d_phase) * ampl); - step (); - } - } - - // compute cos for a block of phase angles - void cos (int *output, int noutput_items, double ampl=1.0) - { - for (int i = 0; i < noutput_items; i++){ - output[i] = (int)(gr_fxpt::cos (d_phase) * ampl); - step (); - } - } - - // compute cos or sin for current phase angle - float cos () const { return gr_fxpt::cos (d_phase); } - float sin () const { return gr_fxpt::sin (d_phase); } -}; - -#endif /* INCLUDED_GR_FXPT_NCO_H */ diff --git a/gnuradio-runtime/include/gr_fxpt_vco.h b/gnuradio-runtime/include/gr_fxpt_vco.h deleted file mode 100644 index 15e7327f79..0000000000 --- a/gnuradio-runtime/include/gr_fxpt_vco.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2002,2004,2005 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_FXPT_VCO_H -#define INCLUDED_GR_FXPT_VCO_H - -#include <gr_runtime_api.h> -#include <gr_fxpt.h> -#include <gr_complex.h> - -/*! - * \brief Voltage Controlled Oscillator (VCO) - * \ingroup misc - */ -class /*GR_RUNTIME_API*/ gr_fxpt_vco { - gr_int32 d_phase; - -public: - gr_fxpt_vco () : d_phase (0) {} - - ~gr_fxpt_vco () {} - - // radians - void set_phase (float angle) { - d_phase = gr_fxpt::float_to_fixed (angle); - } - - void adjust_phase (float delta_phase) { - d_phase += gr_fxpt::float_to_fixed (delta_phase); - } - - float get_phase () const { return gr_fxpt::fixed_to_float (d_phase); } - - // compute sin and cos for current phase angle - void sincos (float *sinx, float *cosx) const - { - *sinx = gr_fxpt::sin (d_phase); - *cosx = gr_fxpt::cos (d_phase); - } - - // compute a block at a time - void cos (float *output, const float *input, int noutput_items, float k, float ampl = 1.0) - { - for (int i = 0; i < noutput_items; i++){ - output[i] = (float)(gr_fxpt::cos (d_phase) * ampl); - adjust_phase(input[i] * k); - } - } - - // compute cos or sin for current phase angle - float cos () const { return gr_fxpt::cos (d_phase); } - float sin () const { return gr_fxpt::sin (d_phase); } -}; - -#endif /* INCLUDED_GR_FXPT_VCO_H */ diff --git a/gnuradio-runtime/include/gr_hier_block2.h b/gnuradio-runtime/include/gr_hier_block2.h deleted file mode 100644 index c39a98f6d7..0000000000 --- a/gnuradio-runtime/include/gr_hier_block2.h +++ /dev/null @@ -1,208 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2007,2008,2009 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_HIER_BLOCK2_H -#define INCLUDED_GR_HIER_BLOCK2_H - -#include <gr_runtime_api.h> -#include <gr_basic_block.h> - -/*! - * \brief public constructor for gr_hier_block2 - - */ -GR_RUNTIME_API gr_hier_block2_sptr gr_make_hier_block2(const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature); - -class gr_hier_block2_detail; - -/*! - * \brief Hierarchical container class for gr_block's and gr_hier_block2's - * \ingroup container_blk - * \ingroup base_blk - * - */ -class GR_RUNTIME_API gr_hier_block2 : public gr_basic_block -{ -private: - friend class gr_hier_block2_detail; - friend GR_RUNTIME_API gr_hier_block2_sptr gr_make_hier_block2(const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature); - - /*! - * \brief Private implementation details of gr_hier_block2 - */ - gr_hier_block2_detail *d_detail; - -protected: - gr_hier_block2 (void){} //allows pure virtual interface sub-classes - gr_hier_block2(const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature); - -public: - virtual ~gr_hier_block2(); - - /*! - * \brief typedef for object returned from self(). - * - * This type is only guaranteed to be passable to connect and disconnect. - * No other assumptions should be made about it. - */ - typedef gr_basic_block_sptr opaque_self; - - /*! - * \brief Return an object, representing the current block, which can be passed to connect. - * - * The returned object may only be used as an argument to connect or disconnect. - * Any other use of self() results in unspecified (erroneous) behavior. - */ - opaque_self self(); - - /*! - * \brief Add a stand-alone (possibly hierarchical) block to internal graph - * - * This adds a gr-block or hierarchical block to the internal graph - * without wiring it to anything else. - */ - void connect(gr_basic_block_sptr block); - - /*! - * \brief Add gr-blocks or hierarchical blocks to internal graph and wire together - * - * This adds (if not done earlier by another connect) a pair of gr-blocks or - * hierarchical blocks to the internal flowgraph, and wires the specified output - * port to the specified input port. - */ - void connect(gr_basic_block_sptr src, int src_port, - gr_basic_block_sptr dst, int dst_port); - - /*! - * \brief Add gr-blocks or hierarchical blocks to internal graph and wire together - * - * This adds (if not done earlier by another connect) a pair of gr-blocks or - * hierarchical blocks to the internal message port subscription - */ - void msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, - gr_basic_block_sptr dst, pmt::pmt_t dstport); - void msg_connect(gr_basic_block_sptr src, std::string srcport, - gr_basic_block_sptr dst, std::string dstport); - void msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport, - gr_basic_block_sptr dst, pmt::pmt_t dstport); - void msg_disconnect(gr_basic_block_sptr src, std::string srcport, - gr_basic_block_sptr dst, std::string dstport); - - /*! - * \brief Remove a gr-block or hierarchical block from the internal flowgraph. - * - * This removes a gr-block or hierarchical block from the internal flowgraph, - * disconnecting it from other blocks as needed. - * - */ - void disconnect(gr_basic_block_sptr block); - - /*! - * \brief Disconnect a pair of gr-blocks or hierarchical blocks in internal - * flowgraph. - * - * This disconnects the specified input port from the specified output port - * of a pair of gr-blocks or hierarchical blocks. - */ - void disconnect(gr_basic_block_sptr src, int src_port, - gr_basic_block_sptr dst, int dst_port); - - /*! - * \brief Disconnect all connections in the internal flowgraph. - * - * This call removes all output port to input port connections in the internal - * flowgraph. - */ - void disconnect_all(); - - /*! - * Lock a flowgraph in preparation for reconfiguration. When an equal - * number of calls to lock() and unlock() have occurred, the flowgraph - * will be reconfigured. - * - * N.B. lock() and unlock() may not be called from a flowgraph thread - * (E.g., gr_block::work method) or deadlock will occur when - * reconfiguration happens. - */ - virtual void lock(); - - /*! - * Unlock a flowgraph in preparation for reconfiguration. When an equal - * number of calls to lock() and unlock() have occurred, the flowgraph - * will be reconfigured. - * - * N.B. lock() and unlock() may not be called from a flowgraph thread - * (E.g., gr_block::work method) or deadlock will occur when - * reconfiguration happens. - */ - virtual void unlock(); - - // This is a public method for ease of code organization, but should be - // ignored by the user. - gr_flat_flowgraph_sptr flatten() const; - - gr_hier_block2_sptr to_hier_block2(); // Needed for Python type coercion - - bool has_msg_port(pmt::pmt_t which_port){ - return message_port_is_hier(which_port) || gr_basic_block::has_msg_port(which_port); - } - - bool message_port_is_hier(pmt::pmt_t port_id){ - return message_port_is_hier_in(port_id) || message_port_is_hier_out(port_id); - } - bool message_port_is_hier_in(pmt::pmt_t port_id){ - return pmt::list_has(hier_message_ports_in, port_id); - } - bool message_port_is_hier_out(pmt::pmt_t port_id){ - return pmt::list_has(hier_message_ports_out, port_id); - } - - pmt::pmt_t hier_message_ports_in; - pmt::pmt_t hier_message_ports_out; - - void message_port_register_hier_in(pmt::pmt_t port_id){ - if(pmt::list_has(hier_message_ports_in, port_id)) - throw std::invalid_argument("hier msg in port by this name already registered"); - if(msg_queue.find(port_id) != msg_queue.end()) - throw std::invalid_argument("block already has a primitive input port by this name"); - hier_message_ports_in = pmt::list_add(hier_message_ports_in, port_id); - } - void message_port_register_hier_out(pmt::pmt_t port_id){ - if(pmt::list_has(hier_message_ports_out, port_id)) - throw std::invalid_argument("hier msg out port by this name already registered"); - if(pmt::dict_has_key(message_subscribers, port_id)) - throw std::invalid_argument("block already has a primitive output port by this name"); - hier_message_ports_out = pmt::list_add(hier_message_ports_out, port_id); - } - -}; - -inline gr_hier_block2_sptr cast_to_hier_block2_sptr(gr_basic_block_sptr block) { - return boost::dynamic_pointer_cast<gr_hier_block2, gr_basic_block>(block); -} - -#endif /* INCLUDED_GR_HIER_BLOCK2_H */ diff --git a/gnuradio-runtime/include/gr_io_signature.h b/gnuradio-runtime/include/gr_io_signature.h deleted file mode 100644 index 345cd6b9d2..0000000000 --- a/gnuradio-runtime/include/gr_io_signature.h +++ /dev/null @@ -1,117 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_IO_SIGNATURE_H -#define INCLUDED_IO_SIGNATURE_H - -#include <gr_runtime_api.h> -#include <gr_runtime_types.h> - -/*! - * \brief Create an i/o signature - * - * \ingroup internal - * \param min_streams specify minimum number of streams (>= 0) - * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite) - * \param sizeof_stream_item specify the size of the items in each stream - */ -GR_RUNTIME_API gr_io_signature_sptr -gr_make_io_signature(int min_streams, int max_streams, - int sizeof_stream_item); - -/*! - * \brief Create an i/o signature - * - * \param min_streams specify minimum number of streams (>= 0) - * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite) - * \param sizeof_stream_item1 specify the size of the items in the first stream - * \param sizeof_stream_item2 specify the size of the items in the second and subsequent streams - */ -GR_RUNTIME_API gr_io_signature_sptr -gr_make_io_signature2(int min_streams, int max_streams, - int sizeof_stream_item1, - int sizeof_stream_item2 - ); - -/*! - * \brief Create an i/o signature - * - * \param min_streams specify minimum number of streams (>= 0) - * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite) - * \param sizeof_stream_item1 specify the size of the items in the first stream - * \param sizeof_stream_item2 specify the size of the items in the second stream - * \param sizeof_stream_item3 specify the size of the items in the third and subsequent streams - */ -GR_RUNTIME_API gr_io_signature_sptr -gr_make_io_signature3(int min_streams, int max_streams, - int sizeof_stream_item1, - int sizeof_stream_item2, - int sizeof_stream_item3 - ); - -/*! - * \brief Create an i/o signature - * - * \param min_streams specify minimum number of streams (>= 0) - * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite) - * \param sizeof_stream_items specify the size of the items in the streams - * - * If there are more streams than there are entries in sizeof_stream_items, the - * value of the last entry in sizeof_stream_items is used for the missing values. - * sizeof_stream_items must contain at least 1 entry. - */ -GR_RUNTIME_API gr_io_signature_sptr -gr_make_io_signaturev(int min_streams, int max_streams, - const std::vector<int> &sizeof_stream_items); - - -/*! - * \brief i/o signature for input and output ports. - * \brief misc - */ -class GR_RUNTIME_API gr_io_signature { - int d_min_streams; - int d_max_streams; - std::vector<int> d_sizeof_stream_item; - - gr_io_signature(int min_streams, int max_streams, - const std::vector<int> &sizeof_stream_items); - - friend GR_RUNTIME_API gr_io_signature_sptr - gr_make_io_signaturev(int min_streams, - int max_streams, - const std::vector<int> &sizeof_stream_items); - - public: - - static const int IO_INFINITE = -1; - - ~gr_io_signature (); - - int min_streams () const { return d_min_streams; } - int max_streams () const { return d_max_streams; } - int sizeof_stream_item (int index) const; - std::vector<int> sizeof_stream_items() const; -}; - - -#endif /* INCLUDED_IO_SIGNATURE_H */ diff --git a/gnuradio-runtime/include/gr_logger.h b/gnuradio-runtime/include/gr_logger.h deleted file mode 100644 index 0e82c5134e..0000000000 --- a/gnuradio-runtime/include/gr_logger.h +++ /dev/null @@ -1,648 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2012-2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -/******************************************************************************* -* Author: Mark Plett -* Description: -* The gr_logger module wraps the log4cpp library for logging in gnuradio -*******************************************************************************/ - -#ifndef INCLUDED_GR_LOGGER_H -#define INCLUDED_GR_LOGGER_H - -/*! -* \file gr_logger.h -* \ingroup logging -* \brief GNURADIO logging wrapper for log4cpp library (C++ port of log4j) -* -*/ - -#include <gr_runtime_api.h> -#include <assert.h> -#include <iostream> -#include <boost/filesystem.hpp> -#include <boost/thread.hpp> -#include <boost/format.hpp> - -#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -typedef int mode_t; -#endif - -#ifdef ENABLE_GR_LOG - -// We have three configurations... first logging to stdout/stderr -#ifndef HAVE_LOG4CPP -//#warning GR logging Enabled and using std::cout - -typedef std::string gr_logger_ptr; - -#define GR_LOG_DECLARE_LOGPTR(logger) -#define GR_LOG_ASSIGN_LOGPTR(logger,name) -#define GR_CONFIG_LOGGER(config) -#define GR_CONFIG_AND_WATCH_LOGGER(config,period) -#define GR_LOG_GETLOGGER(logger, name) -#define GR_SET_LEVEL(name, level) -#define GR_LOG_SET_LEVEL(logger, level) -#define GR_GET_LEVEL(name, level) -#define GR_LOG_GET_LEVEL(logger, level) -#define GR_ADD_CONSOLE_APPENDER(logger,target,pattern) -#define GR_LOG_ADD_CONSOLE_APPENDER(logger,target,pattern) -#define GR_ADD_FILE_APPENDER(name,filename,append,pattern) -#define GR_LOG_ADD_FILE_APPENDER(logger,filename,append,pattern) -#define GR_ADD_ROLLINGFILE_APPENDER(name,filename,filesize,bkup_index,append,mode,pattern) -#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger,filename,filesize,bkup_index,append,mode,pattern) -#define GR_GET_LOGGER_NAMES(names) -#define GR_RESET_CONFIGURATION() -#define GR_DEBUG(name, msg) std::cout<<"DEBUG: "<<msg<<std::endl -#define GR_INFO(name, msg) std::cout<<"INFO: "<<msg<<std::endl -#define GR_NOTICE(name, msg) std::cout<<"NOTICE: "<<msg<<std::endl -#define GR_WARN(name, msg) std::cerr<<"WARN: "<<msg<<std::endl -#define GR_ERROR(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl -#define GR_ALERT(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl -#define GR_CRIT(name, msg) std::cerr<<"ERROR: "<<msg<<std::endl -#define GR_FATAL(name, msg) std::cerr<<"FATAL: "<<msg<<std::endl -#define GR_EMERG(name, msg) std::cerr<<"EMERG: "<<msg<<std::endl -#define GR_ERRORIF(name, cond, msg) {if((cond)) std::cerr<<"ERROR: "<<msg<<std::endl;} -#define GR_ASSERT(name, cond, msg) {if(!(cond)) std::cerr<<"FATAL: "<<msg<<std::endl; assert(cond);} -#define GR_LOG_DEBUG(logger, msg) std::cout<<"DEBUG: "<<msg<<std::endl -#define GR_LOG_INFO(logger, msg) std::cout<<"INFO: "<<msg<<std::endl -#define GR_LOG_NOTICE(logger, msg) std::cout<<"NOTICE: "<<msg<<std::endl -#define GR_LOG_WARN(logger, msg) std::cerr<<"WARN: "<<msg<<std::endl -#define GR_LOG_ERROR(logger, msg) std::cerr<<"ERROR: "<<msg<<std::endl -#define GR_LOG_ALERT(logger, msg) std::cerr<<"ALERT: "<<msg<<std::endl -#define GR_LOG_CRIT(logger, msg) std::cerr<<"CRIT: "<<msg<<std::endl -#define GR_LOG_FATAL(logger, msg) std::cerr<<"FATAL: "<<msg<<std::endl -#define GR_LOG_EMERG(logger, msg) std::cerr<<"EMERG: "<<msg<<std::endl -#define GR_LOG_ERRORIF(logger, cond, msg) {\ - if((cond)) std::cerr<<"ERROR: "<<msg<<std::endl;} -#define GR_LOG_ASSERT(logger, cond, msg) {\ - if(!(cond)) {std::cerr<<"FATAL: "<<msg<<std::endl; assert(cond);};} - -#else /* HAVE_LOG4CPP */ -// Second configuration...logging to log4cpp - -#include <log4cpp/Category.hh> -#include <log4cpp/PropertyConfigurator.hh> -#include <log4cpp/FileAppender.hh> -#include <log4cpp/RollingFileAppender.hh> -#include <log4cpp/OstreamAppender.hh> -#include <log4cpp/PatternLayout.hh> - -/*! - * \brief GR_LOG macros - * \ingroup logging - * - * These macros wrap the standard LOG4CPP_LEVEL macros. The availablie macros - * are: - * GR_LOG_DEBUG - * GR_LOG_INFO - * GR_LOG_WARN - * GR_LOG_TRACE - * GR_LOG_ERROR - * GR_LOG_ALERT - * GR_LOG_CRIT - * GR_LOG_FATAL - * GR_LOG_EMERG - */ -typedef log4cpp::Category* gr_logger_ptr; - -/* Macros for Programmatic Configuration */ -#define GR_LOG_DECLARE_LOGPTR(logger) \ - gr_logger_ptr logger; - -#define GR_LOG_ASSIGN_LOGPTR(logger,name) \ - logger = logger_get_logger(name); - -#define GR_CONFIG_LOGGER(config) \ - logger_config::load_config(config) - -#define GR_CONFIG_AND_WATCH_LOGGER(config,period) \ - logger_config::load_config(config,period) - -#define GR_LOG_GETLOGGER(logger, name) \ - gr_logger_ptr logger = logger_get_logger(name); - -#define GR_SET_LEVEL(name, level){ \ - gr_logger_ptr logger = logger_get_logger(name);\ - logger_set_level(logger,level);} - -#define GR_LOG_SET_LEVEL(logger, level) \ - logger_set_level(logger, level); - -#define GR_GET_LEVEL(name, level){ \ - gr_logger_ptr logger = logger_get_logger(name);\ - logger_get_level(logger,level);} - -#define GR_LOG_GET_LEVEL(logger, level) \ - logger_get_level(logger,level); - -#define GR_ADD_CONSOLE_APPENDER(name,target,pattern){\ - gr_logger_ptr logger = logger_get_logger(name);\ - logger_add_console_appender(logger,target,pattern);} - -#define GR_LOG_ADD_CONSOLE_APPENDER(logger,target,pattern){\ - logger_add_console_appender(logger,target,pattern);} - -#define GR_ADD_FILE_APPENDER(name,filename,append,pattern){\ - gr_logger_ptr logger = logger_get_logger(name);\ - logger_add_file_appender(logger,filename,append,pattern);} - -#define GR_LOG_ADD_FILE_APPENDER(logger,filename,append,pattern){\ - logger_add_file_appender(logger,filename,append,pattern);} - -#define GR_ADD_ROLLINGFILE_APPENDER(name,filename,filesize,bkup_index,append,mode,pattern){\ - gr_logger_ptr logger = logger_get_logger(name);\ - logger_add_rollingfile_appender(logger,filename,filesize,bkup_index,append,mode,pattern);} - -#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger,filename,filesize,bkup_index,append,mode,pattern){\ - logger_add_rollingfile_appender(logger,filename,filesize,bkup_index,append,mode,pattern);} - -#define GR_GET_LOGGER_NAMES(names){ \ - names = logger_get_logger_names();} - -#define GR_RESET_CONFIGURATION(){ \ - logger_config::reset_config();} - -/* Logger name referenced macros */ -#define GR_DEBUG(name, msg) { \ - gr_logger_ptr logger = logger_get_logger(name);\ - *logger<< log4cpp::Priority::DEBUG << msg << log4cpp::eol;} - -#define GR_INFO(name, msg) { \ - gr_logger_ptr logger = logger_get_logger(name);\ - *logger<< log4cpp::Priority::INFO << msg << log4cpp::eol;} - -#define GR_NOTICE(name, msg) { \ - gr_logger_ptr logger = logger_get_logger(name);\ - *logger << log4cpp::Priority::NOTICE << msg;} - -#define GR_WARN(name, msg) { \ - gr_logger_ptr logger = logger_get_logger(name);\ - *logger<< log4cpp::Priority::WARN << msg << log4cpp::eol;} - -#define GR_ERROR(name, msg) { \ - gr_logger_ptr logger = logger_get_logger(name);\ - *logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;} - -#define GR_CRIT(name, msg) { \ - gr_logger_ptr logger = logger_get_logger(name);\ - *logger<< log4cpp::Priority::CRIT << msg << log4cpp::eol;} - -#define GR_ALERT(name, msg) { \ - gr_logger_ptr logger = logger_get_logger(name);\ - *logger<< log4cpp::Priority::ALERT << msg << log4cpp::eol;} - -#define GR_FATAL(name, msg) { \ - gr_logger_ptr logger = logger_get_logger(name);\ - *logger<< log4cpp::Priority::FATAL << msg << log4cpp::eol;} - -#define GR_EMERG(name, msg) { \ - gr_logger_ptr logger = logger_get_logger(name);\ - *logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol;} - -#define GR_ERRORIF(name, cond, msg) { \ -if((cond)){\ - gr_logger_ptr logger = logger_get_logger(name);\ - *logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;};\ -}; - -#define GR_ASSERT(name, cond, msg) { \ -if(!(cond)){\ - gr_logger_ptr logger = logger_get_logger(name);\ - *logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol;};\ - assert(0);\ -}; - -/* LoggerPtr Referenced Macros */ -#define GR_LOG_DEBUG(logger, msg) { \ - *logger << log4cpp::Priority::DEBUG << msg << log4cpp::eol;} - -#define GR_LOG_INFO(logger, msg) { \ - *logger << log4cpp::Priority::INFO << msg << log4cpp::eol;} - -#define GR_LOG_NOTICE(logger, msg) { \ - *logger << log4cpp::Priority::NOTICE << msg << log4cpp::eol;} - -#define GR_LOG_WARN(logger, msg) { \ - *logger << log4cpp::Priority::WARN << msg << log4cpp::eol;} - -#define GR_LOG_ERROR(logger, msg) { \ - *logger << log4cpp::Priority::ERROR << msg << log4cpp::eol;} - -#define GR_LOG_CRIT(logger, msg) { \ - *logger << log4cpp::Priority::CRIT << msg << log4cpp::eol;} - -#define GR_LOG_ALERT(logger, msg) { \ - *logger << log4cpp::Priority::ALERT << msg << log4cpp::eol;} - -#define GR_LOG_FATAL(logger, msg) { \ - *logger << log4cpp::Priority::FATAL << msg << log4cpp::eol;} - -#define GR_LOG_EMERG(logger, msg) { \ - *logger << log4cpp::Priority::EMERG << msg << log4cpp::eol;} - -#define GR_LOG_ERRORIF(logger,cond, msg) { \ -if((cond)){\ - *logger<< log4cpp::Priority::ERROR << msg << log4cpp::eol;};\ -}; - -#define GR_LOG_ASSERT(logger, cond, msg) { \ -if(!(cond)){\ - *logger<< log4cpp::Priority::EMERG << msg << log4cpp::eol;\ - assert(0);};\ -}; - -/*! - * \brief Class to control configuration of logger. - * This is a singleton that cna launch a thread to wathc a config file for changes - * \ingroup logging - */ -class logger_config { -private: - /*! \brief filename of logger config file */ - std::string filename; - /*! \brief Period (seconds) over which watcher thread checks config file for changes */ - unsigned int watch_period; - /*! \brief Pointer to watch thread for config file changes */ - boost::thread *watch_thread; - - /*! \brief Watcher thread method - * /param filename Name of configuration file - * /param watch_period Seconds between checks for changes in config file - */ - static void watch_file(std::string filename,unsigned int watch_period); - - logger_config(){}; //!< Constructor - logger_config(logger_config const&); //!<Copy constructor - void operator=(logger_config const&); //!<Assignment Operator - - /*! \brief destrcutor stops watch thread before exits */ - ~logger_config(){ - stop_watch(); - }; - - /*! \brief Instance getter for singleton. Only used by class. */ - static logger_config& get_instance(void); - -public: - /*! \brief Getter for config filename */ - static std::string get_filename(); - /*! \brief Getter for watch period */ - static unsigned int get_watch_period(); - /*! \brief Method to load configuration - * /param filename Name of configuration file - * /param watch_period Seconds between checks for changes in config file - */ - static void load_config(std::string filename,unsigned int watch_period=0); - /*! \brief Method to stop watcher thread */ - static void stop_watch(); - /*! \brief method to reset logger configuration */ - static void reset_config(void); -}; - -/*! - * \brief Retrieve a pointer to a logger by name - * - * Retrives a logger pointer - * \p name. - * - * \param name Name of the logger for which a pointer is requested - */ -GR_RUNTIME_API gr_logger_ptr logger_get_logger(std::string name); - -/*! - * \brief Load logger's configuration file. - * - * Initialize the GNU Radio logger by loading the configuration file - * \p config_filename. - * - * \param config_filename The configuration file. Set to "" for the - * basic logger that outputs to the console. - */ -GR_RUNTIME_API void logger_load_config(const std::string &config_filename=""); - -/*! - * \brief Reset logger's configuration file. - * - * Remove all appenders from loggers - */ -GR_RUNTIME_API void logger_reset_config(void); - -GR_RUNTIME_API void logger_load_config_and_watch(const std::string &config_filename, - unsigned int watch_period); - - -/*! - * \brief Set the logger's output level. - * - * Sets the level of the logger. This takes a string that is - * translated to the standard levels and can be (case insensitive): - * - * \li off , notset - * \li debug - * \li info - * \li notice - * \li warn - * \li error - * \li crit - * \li alert - * \li fatal - * \li emerg - * - * \param logger the logger to set the level of. - * \param level string to set the level to. - */ -GR_RUNTIME_API void logger_set_level(gr_logger_ptr logger, const std::string &level); - -/*! - * \brief Set the logger's output level. - * - * Sets the level of the logger. This takes the actual Log4cpp::Priority - * data type, which can be: - * - * \li log4cpp::Priority::NOTSET - * \li log4cpp::Priority::DEBUG - * \li log4cpp::Priority::INFO - * \li log4cpp::Priority::NOTICE - * \li log4cpp::Priority::WARN - * \li log4cpp::Priority::ERROR - * \li log4cpp::Priority::CRIT - * \li log4cpp::Priority::ALERT - * \li log4cpp::Priority::FATAL - * \li log4cpp::Priority::EMERG - * - * \param logger the logger to set the level of. - * \param level new logger level of type Log4cpp::Priority - */ -GR_RUNTIME_API void logger_set_level(gr_logger_ptr logger, log4cpp::Priority::Value level); - - -/*! - * \brief Get the logger's output level. - * - * Gets the level of the logger. This returns a string that - * corresponds to the standard levels and can be (case insensitive): - * - * \li notset - * \li debug - * \li info - * \li notice - * \li warn - * \li error - * \li crit - * \li alert - * \li fatal - * \li emerg - * - * \param logger the logger to get the level of. - * \param level string to get the level into. - */ -GR_RUNTIME_API void logger_get_level(gr_logger_ptr logger, std::string &level); - -/*! - * \brief Get the logger's output level. - * - * Gets the level of the logger. This returns the actual Log4cpp::Level - * data type, which can be: - * - * \li log4cpp::Priority::NOTSET - * \li log4cpp::Priority::DEBUG - * \li log4cpp::Priority::INFO - * \li log4cpp::Priority::NOTICE - * \li log4cpp::Priority::WARN - * \li log4cpp::Priority::ERROR - * \li log4cpp::Priority::CRIT - * \li log4cpp::Priority::ALERT - * \li log4cpp::Priority::FATAL - * \li log4cpp::Priority::EMERG - * - * \param logger the logger to get the level of. - * \param level of the logger. - */ -GR_RUNTIME_API void logger_get_level(gr_logger_ptr logger, log4cpp::Priority::Value &level); - -/*! - * \brief Add console appender to a given logger - * - * Add console appender to a given logger - * - * \param logger Logger to which appender will be added - * \param target Std target to write 'cout' or 'cerr' (default is cout) - * \param pattern Formating pattern for log messages - */ -GR_RUNTIME_API void logger_add_console_appender(gr_logger_ptr logger,std::string target,std::string pattern); - -/*! - * \brief Add file appender to a given logger - * - * Add file appender to a given logger - * - * \param logger Logger to which appender will be added - * \param filename File to which log will be written - * \param append Overwrite or append to log file - * \param pattern Formating pattern for log messages - */ -GR_RUNTIME_API void logger_add_file_appender(gr_logger_ptr logger,std::string filename,bool append,std::string pattern); - -/*! - * \brief Add rolling file appender to a given logger - * - * Add rolling file appender to a given logger - * - * \param logger Logger to which appender will be added - * \param filename File to which log will be written - * \param filesize Sizez of files to write - * \param bkup_index Number of files to write - * \param append Overwrite or append to log file - * \param mode Permissions to set on log file - * \param pattern Formating pattern for log messages - */ -GR_RUNTIME_API void logger_add_rollingfile_appender(gr_logger_ptr logger,std::string filename, - size_t filesize,int bkup_index,bool append,mode_t mode,std::string pattern); - - -/*! - * \brief Add rolling file appender to a given logger - * - * Add rolling file appender to a given logger - * - * \return vector of string names of loggers - */ -GR_RUNTIME_API std::vector<std::string> logger_get_logger_names(void); - -#endif /* HAVE_LOG4CPP */ - - -// If Logger disable do nothing -#else /* ENABLE_GR_LOG */ - -typedef void* gr_logger_ptr; - -#define GR_LOG_DECLARE_LOGPTR(logger) -#define GR_LOG_ASSIGN_LOGPTR(logger,name) -#define GR_CONFIG_LOGGER(config) -#define GR_CONFIG_AND_WATCH_LOGGER(config,period) -#define GR_LOG_GETLOGGER(logger, name) -#define GR_SET_LEVEL(name, level) -#define GR_LOG_SET_LEVEL(logger, level) -#define GR_GET_LEVEL(name, level) -#define GR_LOG_GET_LEVEL(logger, level) -#define GR_ADD_CONSOLE_APPENDER(logger,target,pattern) -#define GR_LOG_ADD_CONSOLE_APPENDER(logger,target,pattern) -#define GR_ADD_FILE_APPENDER(name,filename,append,pattern) -#define GR_LOG_ADD_FILE_APPENDER(logger,filename,append,pattern) -#define GR_ADD_ROLLINGFILE_APPENDER(name,filename,filesize,bkup_index,append,mode,pattern) -#define GR_LOG_ADD_ROLLINGFILE_APPENDER(logger,filename,filesize,bkup_index,append,mode,pattern) -#define GR_GET_LOGGER_NAMES(names) -#define GR_RESET_CONFIGURATION() -#define GR_DEBUG(name, msg) -#define GR_INFO(name, msg) -#define GR_NOTICE(name, msg) -#define GR_WARN(name, msg) -#define GR_ERROR(name, msg) -#define GR_ALERT(name, msg) -#define GR_CRIT(name, msg) -#define GR_FATAL(name, msg) -#define GR_EMERG(name, msg) -#define GR_ERRORIF(name, cond, msg) -#define GR_ASSERT(name, cond, msg) -#define GR_LOG_DEBUG(logger, msg) -#define GR_LOG_INFO(logger, msg) -#define GR_LOG_NOTICE(logger, msg) -#define GR_LOG_WARN(logger, msg) -#define GR_LOG_ERROR(logger, msg) -#define GR_LOG_ALERT(logger, msg) -#define GR_LOG_CRIT(logger, msg) -#define GR_LOG_FATAL(logger, msg) -#define GR_LOG_EMERG(logger, msg) -#define GR_LOG_ERRORIF(logger, cond, msg) -#define GR_LOG_ASSERT(logger, cond, msg) - -#endif /* ENABLE_GR_LOG */ - -// Even if logger is disabled we'll need for methods below to exist in python. -// The macros these call will be disabled if ENABLE_GR_LOG is undefined - -/********************* Start Classes and Methods for Python ******************/ -/*! - * \brief Logger class for referencing loggers in python. Not needed in C++ (use macros) - * Wraps and manipulates loggers for python as python has no macros - * \ingroup logging - * - */ -class gr_logger -{ - private: - /*! \brief logger pointer to logger associated wiith this wrapper class */ - gr_logger_ptr d_logger; - public: - /*! - * \brief contructor Provide name of logger to associate with this class - * \param logger_name Name of logger associated with class - */ - gr_logger(std::string logger_name) { - GR_LOG_ASSIGN_LOGPTR(d_logger,logger_name); - }; - - /*! \brief Destructor */ - ~gr_logger(){;}; - - // Wrappers for logging macros - /*! \brief inline function, wrapper to set the logger level */ - void set_level(std::string level){GR_LOG_SET_LEVEL(d_logger,level);} - - /*! \brief inline function, wrapper to get the logger level */ - void get_level(std::string &level){GR_LOG_GET_LEVEL(d_logger,level);} - - /*! \brief inline function, wrapper for LOG4CPP_DEBUG for DEBUG message */ - void debug(std::string msg){GR_LOG_DEBUG(d_logger,msg);}; - - /*! \brief inline function, wrapper for LOG4CPP_INFO for INFO message */ - void info(std::string msg){GR_LOG_INFO(d_logger,msg);}; - - /*! \brief inline function, wrapper for NOTICE message */ - void notice(std::string msg){GR_LOG_NOTICE(d_logger,msg);}; - - /*! \brief inline function, wrapper for LOG4CPP_WARN for WARN message */ - void warn(std::string msg){GR_LOG_WARN(d_logger,msg);}; - - /*! \brief inline function, wrapper for LOG4CPP_ERROR for ERROR message */ - void error(std::string msg){GR_LOG_ERROR(d_logger,msg);}; - - /*! \brief inline function, wrapper for NOTICE message */ - void crit(std::string msg){GR_LOG_CRIT(d_logger,msg);}; - - /*! \brief inline function, wrapper for ALERT message */ - void alert(std::string msg){GR_LOG_ALERT(d_logger,msg);}; - - /*! \brief inline function, wrapper for FATAL message */ - void fatal(std::string msg){GR_LOG_FATAL(d_logger,msg);}; - - /*! \brief inline function, wrapper for EMERG message */ - void emerg(std::string msg){GR_LOG_EMERG(d_logger,msg);}; - - /*! \brief inline function, wrapper for LOG4CPP_ASSERT for conditional ERROR message */ - void errorIF(bool cond,std::string msg){GR_LOG_ERRORIF(d_logger,cond,msg);}; - - /*! \brief inline function, wrapper for LOG4CPP_ASSERT for conditional ERROR message */ - void log_assert(bool cond,std::string msg){GR_LOG_ASSERT(d_logger,cond,msg);}; - - /*! \brief inline function, Method to add console appender to logger */ - void add_console_appender(std::string target,std::string pattern){ - GR_LOG_ADD_CONSOLE_APPENDER(d_logger,target,pattern); - }; - - /*! \brief inline function, Method to add file appender to logger */ - void add_file_appender(std::string filename,bool append,std::string pattern){ - GR_LOG_ADD_FILE_APPENDER(d_logger,filename,append,pattern); - }; - - /*! \brief inline function, Method to add rolling file appender to logger */ - void add_rollingfile_appender(std::string filename,size_t filesize, - int bkup_index,bool append,mode_t mode,std::string pattern){ - GR_LOG_ADD_ROLLINGFILE_APPENDER(d_logger,filename,filesize, - bkup_index,append,mode,pattern); - }; -}; - -/**************** Start Configuration Class and Methods for Python ************/ -/*! - * \brief Function to call configuration macro from python. - * Note: Configuration is only updated if filename or watch_period has changed. - * \param config_filename Name of configuration file - * \param watch_period Seconds to wait between checking for changes in conf file. - * Watch_period defaults to 0 in which case the file is not watched for changes - */ -GR_RUNTIME_API void gr_logger_config(const std::string config_filename, unsigned int watch_period = 0); -/*! - * \brief Function to return logger names to python - * \return Vector of name strings - * - */ -GR_RUNTIME_API std::vector<std::string> gr_logger_get_logger_names(void); -/*! - * \brief Function to reset logger configuration from python - * - */ -GR_RUNTIME_API void gr_logger_reset_config(void); - -#endif /* INCLUDED_GR_LOGGER_H */ diff --git a/gnuradio-runtime/include/gr_math.h b/gnuradio-runtime/include/gr_math.h deleted file mode 100644 index c7efe8facb..0000000000 --- a/gnuradio-runtime/include/gr_math.h +++ /dev/null @@ -1,209 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003,2005,2008 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -/* - * mathematical odds and ends. - */ - -#ifndef _GR_MATH_H_ -#define _GR_MATH_H_ - -#include <gr_runtime_api.h> -#include <gr_complex.h> - -static inline bool -gr_is_power_of_2(long x) -{ - return x != 0 && (x & (x-1)) == 0; -} - -/*! - * \brief Fast arc tangent using table lookup and linear interpolation - * \ingroup misc - * - * \param y component of input vector - * \param x component of input vector - * \returns float angle angle of vector (x, y) in radians - * - * This function calculates the angle of the vector (x,y) based on a - * table lookup and linear interpolation. The table uses a 256 point - * table covering -45 to +45 degrees and uses symetry to determine the - * final angle value in the range of -180 to 180 degrees. Note that - * this function uses the small angle approximation for values close - * to zero. This routine calculates the arc tangent with an average - * error of +/- 0.045 degrees. - */ -GR_RUNTIME_API float gr_fast_atan2f(float y, float x); - -static inline float gr_fast_atan2f(gr_complex z) -{ - return gr_fast_atan2f(z.imag(), z.real()); -} - -/* This bounds x by +/- clip without a branch */ -static inline float gr_branchless_clip(float x, float clip) -{ - float x1 = fabsf(x+clip); - float x2 = fabsf(x-clip); - x1 -= x2; - return 0.5*x1; -} - -static inline float gr_clip(float x, float clip) -{ - float y = x; - if(x > clip) - y = clip; - else if(x < -clip) - y = -clip; - return y; -} - -// Slicer Functions -static inline unsigned int gr_binary_slicer(float x) -{ - if(x >= 0) - return 1; - else - return 0; -} - -static inline unsigned int gr_quad_45deg_slicer(float r, float i) -{ - unsigned int ret = 0; - if((r >= 0) && (i >= 0)) - ret = 0; - else if((r < 0) && (i >= 0)) - ret = 1; - else if((r < 0) && (i < 0)) - ret = 2; - else - ret = 3; - return ret; -} - -static inline unsigned int gr_quad_0deg_slicer(float r, float i) -{ - unsigned int ret = 0; - if(fabsf(r) > fabsf(i)) { - if(r > 0) - ret = 0; - else - ret = 2; - } - else { - if(i > 0) - ret = 1; - else - ret = 3; - } - - return ret; -} - -static inline unsigned int gr_quad_45deg_slicer(gr_complex x) -{ - return gr_quad_45deg_slicer(x.real(), x.imag()); -} - -static inline unsigned int gr_quad_0deg_slicer(gr_complex x) -{ - return gr_quad_0deg_slicer(x.real(), x.imag()); -} - -// Branchless Slicer Functions -static inline unsigned int gr_branchless_binary_slicer(float x) -{ - return (x >= 0); -} - -static inline unsigned int gr_branchless_quad_0deg_slicer(float r, float i) -{ - unsigned int ret = 0; - ret = (fabsf(r) > fabsf(i)) * (((r < 0) << 0x1)); // either 0 (00) or 2 (10) - ret |= (fabsf(i) > fabsf(r)) * (((i < 0) << 0x1) | 0x1); // either 1 (01) or 3 (11) - - return ret; -} - -static inline unsigned int gr_branchless_quad_0deg_slicer(gr_complex x) -{ - return gr_branchless_quad_0deg_slicer(x.real(), x.imag()); -} - -static inline unsigned int gr_branchless_quad_45deg_slicer(float r, float i) -{ - char ret = (r <= 0); - ret |= ((i <= 0) << 1); - return (ret ^ ((ret & 0x2) >> 0x1)); -} - -static inline unsigned int gr_branchless_quad_45deg_slicer(gr_complex x) -{ - return gr_branchless_quad_45deg_slicer(x.real(), x.imag()); -} - -/*! - * \param x any value - * \param pow2 must be a power of 2 - * \returns \p x rounded down to a multiple of \p pow2. - */ -static inline size_t -gr_p2_round_down(size_t x, size_t pow2) -{ - return x & -pow2; -} - -/*! - * \param x any value - * \param pow2 must be a power of 2 - * \returns \p x rounded up to a multiple of \p pow2. - */ -static inline size_t -gr_p2_round_up(size_t x, size_t pow2) -{ - return gr_p2_round_down(x + pow2 - 1, pow2); -} - -/*! - * \param x any value - * \param pow2 must be a power of 2 - * \returns \p x modulo \p pow2. - */ -static inline size_t -gr_p2_modulo(size_t x, size_t pow2) -{ - return x & (pow2 - 1); -} - -/*! - * \param x any value - * \param pow2 must be a power of 2 - * \returns \p pow2 - (\p x modulo \p pow2). - */ -static inline size_t -gr_p2_modulo_neg(size_t x, size_t pow2) -{ - return pow2 - gr_p2_modulo(x, pow2); -} - -#endif /* _GR_MATH_H_ */ diff --git a/gnuradio-runtime/include/gr_message.h b/gnuradio-runtime/include/gr_message.h deleted file mode 100644 index 941821617b..0000000000 --- a/gnuradio-runtime/include/gr_message.h +++ /dev/null @@ -1,91 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_MESSAGE_H -#define INCLUDED_GR_MESSAGE_H - -#include <gr_runtime_api.h> -#include <gr_types.h> -#include <string> - -class gr_message; -typedef boost::shared_ptr<gr_message> gr_message_sptr; - -/*! - * \brief public constructor for gr_message - */ -GR_RUNTIME_API gr_message_sptr -gr_make_message(long type = 0, double arg1 = 0, double arg2 = 0, size_t length = 0); - -GR_RUNTIME_API gr_message_sptr -gr_make_message_from_string(const std::string s, long type = 0, double arg1 = 0, double arg2 = 0); - -/*! - * \brief Message class. - * - * \ingroup misc - * The ideas and method names for adjustable message length were - * lifted from the click modular router "Packet" class. - */ -class GR_RUNTIME_API gr_message { - gr_message_sptr d_next; // link field for msg queue - long d_type; // type of the message - double d_arg1; // optional arg1 - double d_arg2; // optional arg2 - - unsigned char *d_buf_start; // start of allocated buffer - unsigned char *d_msg_start; // where the msg starts - unsigned char *d_msg_end; // one beyond end of msg - unsigned char *d_buf_end; // one beyond end of allocated buffer - - gr_message (long type, double arg1, double arg2, size_t length); - - friend GR_RUNTIME_API gr_message_sptr - gr_make_message (long type, double arg1, double arg2, size_t length); - - friend GR_RUNTIME_API gr_message_sptr - gr_make_message_from_string (const std::string s, long type, double arg1, double arg2); - - friend class gr_msg_queue; - - unsigned char *buf_data() const { return d_buf_start; } - size_t buf_len() const { return d_buf_end - d_buf_start; } - -public: - ~gr_message (); - - long type() const { return d_type; } - double arg1() const { return d_arg1; } - double arg2() const { return d_arg2; } - - void set_type(long type) { d_type = type; } - void set_arg1(double arg1) { d_arg1 = arg1; } - void set_arg2(double arg2) { d_arg2 = arg2; } - - unsigned char *msg() const { return d_msg_start; } - size_t length() const { return d_msg_end - d_msg_start; } - std::string to_string() const; - -}; - -GR_RUNTIME_API long gr_message_ncurrently_allocated (); - -#endif /* INCLUDED_GR_MESSAGE_H */ diff --git a/gnuradio-runtime/include/gr_msg_queue.h b/gnuradio-runtime/include/gr_msg_queue.h deleted file mode 100644 index ac85729c81..0000000000 --- a/gnuradio-runtime/include/gr_msg_queue.h +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005,2009 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_MSG_QUEUE_H -#define INCLUDED_GR_MSG_QUEUE_H - -#include <gr_runtime_api.h> -#include <gr_msg_handler.h> -#include <thread/thread.h> - -class gr_msg_queue; -typedef boost::shared_ptr<gr_msg_queue> gr_msg_queue_sptr; - -GR_RUNTIME_API gr_msg_queue_sptr gr_make_msg_queue(unsigned int limit=0); - -/*! - * \brief thread-safe message queue - * \ingroup misc - */ -class GR_RUNTIME_API gr_msg_queue : public gr_msg_handler { - - gr::thread::mutex d_mutex; - gr::thread::condition_variable d_not_empty; - gr::thread::condition_variable d_not_full; - gr_message_sptr d_head; - gr_message_sptr d_tail; - unsigned int d_count; // # of messages in queue. - unsigned int d_limit; // max # of messages in queue. 0 -> unbounded - -public: - gr_msg_queue(unsigned int limit); - ~gr_msg_queue(); - - //! Generic msg_handler method: insert the message. - void handle(gr_message_sptr msg) { insert_tail (msg); } - - /*! - * \brief Insert message at tail of queue. - * \param msg message - * - * Block if queue if full. - */ - void insert_tail(gr_message_sptr msg); - - /*! - * \brief Delete message from head of queue and return it. - * Block if no message is available. - */ - gr_message_sptr delete_head(); - - /*! - * \brief If there's a message in the q, delete it and return it. - * If no message is available, return 0. - */ - gr_message_sptr delete_head_nowait(); - - //! Delete all messages from the queue - void flush(); - - //! is the queue empty? - bool empty_p() const { return d_count == 0; } - - //! is the queue full? - bool full_p() const { return d_limit != 0 && d_count >= d_limit; } - - //! return number of messages in queue - unsigned int count() const { return d_count; } - - //! return limit on number of message in queue. 0 -> unbounded - unsigned int limit() const { return d_limit; } - -}; - -#endif /* INCLUDED_GR_MSG_QUEUE_H */ diff --git a/gnuradio-runtime/include/gr_nco.h b/gnuradio-runtime/include/gr_nco.h deleted file mode 100644 index fb51106aab..0000000000 --- a/gnuradio-runtime/include/gr_nco.h +++ /dev/null @@ -1,198 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2002 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef _GR_NCO_H_ -#define _GR_NCO_H_ - - -#include <vector> -#include <gr_sincos.h> -#include <cmath> -#include <gr_complex.h> - -/*! - * \brief base class template for Numerically Controlled Oscillator (NCO) - * \ingroup misc - */ - - -//FIXME Eventually generalize this to fixed point - -template<class o_type, class i_type> -class gr_nco { -public: - gr_nco () : phase (0), phase_inc(0) {} - - virtual ~gr_nco () {} - - // radians - void set_phase (double angle) { - phase = angle; - } - - void adjust_phase (double delta_phase) { - phase += delta_phase; - } - - - // angle_rate is in radians / step - void set_freq (double angle_rate){ - phase_inc = angle_rate; - } - - // angle_rate is a delta in radians / step - void adjust_freq (double delta_angle_rate) - { - phase_inc += delta_angle_rate; - } - - // increment current phase angle - - void step () - { - phase += phase_inc; - if (fabs (phase) > M_PI){ - - while (phase > M_PI) - phase -= 2*M_PI; - - while (phase < -M_PI) - phase += 2*M_PI; - } - } - - void step (int n) - { - phase += phase_inc * n; - if (fabs (phase) > M_PI){ - - while (phase > M_PI) - phase -= 2*M_PI; - - while (phase < -M_PI) - phase += 2*M_PI; - } - } - - // units are radians / step - double get_phase () const { return phase; } - double get_freq () const { return phase_inc; } - - // compute sin and cos for current phase angle - void sincos (float *sinx, float *cosx) const; - - // compute cos or sin for current phase angle - float cos () const { return std::cos (phase); } - float sin () const { return std::sin (phase); } - - // compute a block at a time - void sin (float *output, int noutput_items, double ampl = 1.0); - void cos (float *output, int noutput_items, double ampl = 1.0); - void sincos (gr_complex *output, int noutput_items, double ampl = 1.0); - void sin (short *output, int noutput_items, double ampl = 1.0); - void cos (short *output, int noutput_items, double ampl = 1.0); - void sin (int *output, int noutput_items, double ampl = 1.0); - void cos (int *output, int noutput_items, double ampl = 1.0); - -protected: - double phase; - double phase_inc; -}; - -template<class o_type, class i_type> -void -gr_nco<o_type,i_type>::sincos (float *sinx, float *cosx) const -{ - gr_sincosf (phase, sinx, cosx); -} - -template<class o_type, class i_type> -void -gr_nco<o_type,i_type>::sin (float *output, int noutput_items, double ampl) -{ - for (int i = 0; i < noutput_items; i++){ - output[i] = (float)(sin () * ampl); - step (); - } -} - -template<class o_type, class i_type> -void -gr_nco<o_type,i_type>::cos (float *output, int noutput_items, double ampl) -{ - for (int i = 0; i < noutput_items; i++){ - output[i] = (float)(cos () * ampl); - step (); - } -} - -template<class o_type, class i_type> -void -gr_nco<o_type,i_type>::sin (short *output, int noutput_items, double ampl) -{ - for (int i = 0; i < noutput_items; i++){ - output[i] = (short)(sin() * ampl); - step (); - } -} - -template<class o_type, class i_type> -void -gr_nco<o_type,i_type>::cos (short *output, int noutput_items, double ampl) -{ - for (int i = 0; i < noutput_items; i++){ - output[i] = (short)(cos () * ampl); - step (); - } -} - -template<class o_type, class i_type> -void -gr_nco<o_type,i_type>::sin (int *output, int noutput_items, double ampl) -{ - for (int i = 0; i < noutput_items; i++){ - output[i] = (int)(sin () * ampl); - step (); - } -} - -template<class o_type, class i_type> -void -gr_nco<o_type,i_type>::cos (int *output, int noutput_items, double ampl) -{ - for (int i = 0; i < noutput_items; i++){ - output[i] = (int)(cos () * ampl); - step (); - } -} - -template<class o_type, class i_type> -void -gr_nco<o_type,i_type>::sincos (gr_complex *output, int noutput_items, double ampl) -{ - for (int i = 0; i < noutput_items; i++){ - float cosx, sinx; - sincos (&sinx, &cosx); - output[i] = gr_complex(cosx * ampl, sinx * ampl); - step (); - } -} -#endif /* _NCO_H_ */ diff --git a/gnuradio-runtime/include/gr_prefs.h b/gnuradio-runtime/include/gr_prefs.h deleted file mode 100644 index 0f82c46fae..0000000000 --- a/gnuradio-runtime/include/gr_prefs.h +++ /dev/null @@ -1,143 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_PREFS_H -#define INCLUDED_GR_PREFS_H - -#include <gr_runtime_api.h> -#include <string> -#include <map> -#include <thread/thread.h> - -typedef std::map< std::string, std::map<std::string, std::string> > gr_config_map_t; -typedef std::map< std::string, std::map<std::string, std::string> >::iterator gr_config_map_itr; -typedef std::map<std::string, std::string> gr_config_map_elem_t; -typedef std::map<std::string, std::string>::iterator gr_config_map_elem_itr; - -/*! - * \brief Base class for representing user preferences a la windows INI files. - * \ingroup misc - * - * The real implementation is in Python, and is accessable from C++ - * via the magic of SWIG directors. - */ - -class GR_RUNTIME_API gr_prefs -{ -public: - static gr_prefs *singleton(); - static void set_singleton(gr_prefs *p); - - gr_prefs(); - virtual ~gr_prefs(); - - /*! - * \brief Returns the configuration options as a string. - */ - std::string to_string(); - - /*! - * \brief Saves the configuration settings to ${HOME}/.gnuradio/config.conf. - * - * WARNING: this will overwrite your current config.conf file. - */ - void save(); - - /*! - * \brief Does \p section exist? - */ - virtual bool has_section(const std::string §ion); - - /*! - * \brief Does \p option exist? - */ - virtual bool has_option(const std::string §ion, const std::string &option); - - /*! - * \brief If option exists return associated value; else default_val. - */ - virtual const std::string get_string(const std::string §ion, - const std::string &option, - const std::string &default_val); - - /*! - * \brief Set or add a string \p option to \p section with value \p val. - */ - virtual void set_string(const std::string §ion, - const std::string &option, - const std::string &val); - - /*! - * \brief If option exists and value can be converted to bool, return it; else default_val. - */ - virtual bool get_bool(const std::string §ion, - const std::string &option, - bool default_val); - - /*! - * \brief Set or add a bool \p option to \p section with value \p val. - */ - virtual void set_bool(const std::string §ion, - const std::string &option, - bool val); - - /*! - * \brief If option exists and value can be converted to long, return it; else default_val. - */ - virtual long get_long(const std::string §ion, - const std::string &option, - long default_val); - - /*! - * \brief Set or add a long \p option to \p section with value \p val. - */ - virtual void set_long(const std::string §ion, - const std::string &option, - long val); - - /*! - * \brief If option exists and value can be converted to double, return it; else default_val. - */ - virtual double get_double(const std::string §ion, - const std::string &option, - double default_val); - - /*! - * \brief Set or add a double \p option to \p section with value \p val. - */ - virtual void set_double(const std::string §ion, - const std::string &option, - double val); - - protected: - virtual std::vector<std::string> _sys_prefs_filenames(); - virtual void _read_files(); - virtual void _convert_to_map(const std::string &conf); - virtual char * option_to_env(std::string section, std::string option); - - private: - gr::thread::mutex d_mutex; - gr_config_map_t d_config_map; -}; - - -#endif /* INCLUDED_GR_PREFS_H */ diff --git a/gnuradio-runtime/include/gr_py_feval.h b/gnuradio-runtime/include/gr_py_feval.h deleted file mode 100644 index f2f6c801a8..0000000000 --- a/gnuradio-runtime/include/gr_py_feval.h +++ /dev/null @@ -1,51 +0,0 @@ -#include <pmt/pmt.h> - -class gr_py_feval_dd : public gr_feval_dd -{ - public: - double calleval(double x) - { - ensure_py_gil_state _lock; - return eval(x); - } -}; - -class gr_py_feval_cc : public gr_feval_cc -{ - public: - gr_complex calleval(gr_complex x) - { - ensure_py_gil_state _lock; - return eval(x); - } -}; - -class gr_py_feval_ll : public gr_feval_ll -{ - public: - long calleval(long x) - { - ensure_py_gil_state _lock; - return eval(x); - } -}; - -class gr_py_feval : public gr_feval -{ - public: - void calleval() - { - ensure_py_gil_state _lock; - eval(); - } -}; - -class gr_py_feval_p : public gr_feval_p -{ - public: - void calleval(pmt::pmt_t x) - { - ensure_py_gil_state _lock; - eval(x); - } -}; diff --git a/gnuradio-runtime/include/gr_random.h b/gnuradio-runtime/include/gr_random.h deleted file mode 100644 index 783c05f920..0000000000 --- a/gnuradio-runtime/include/gr_random.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2002 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_RANDOM_H -#define INCLUDED_GR_RANDOM_H - -#include <gr_runtime_api.h> -#include <gr_complex.h> - -/*! - * \brief pseudo random number generator - * \ingroup math_blk - */ -class GR_RUNTIME_API gr_random { -protected: - static const int NTAB = 32; - long d_seed; - long d_iy; - long d_iv[NTAB]; - int d_iset; - float d_gset; - - -public: - gr_random (long seed=3021); - - void reseed (long seed); - - /*! - * \brief uniform random deviate in the range [0.0, 1.0) - */ - float ran1 (); - - /*! - * \brief normally distributed deviate with zero mean and variance 1 - */ - float gasdev (); - - float laplacian (); - float impulse (float factor); - float rayleigh (); - gr_complex rayleigh_complex (); -}; - -#endif /* INCLUDED_GR_RANDOM_H */ - diff --git a/gnuradio-runtime/include/gr_runtime_types.h b/gnuradio-runtime/include/gr_runtime_types.h deleted file mode 100644 index 9af745b3fa..0000000000 --- a/gnuradio-runtime/include/gr_runtime_types.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_RUNTIME_TYPES_H -#define INCLUDED_GR_RUNTIME_TYPES_H - -#include <gr_runtime_api.h> -#include <gr_types.h> - -/* - * typedefs for smart pointers we use throughout the runtime system - */ - -class gr_basic_block; -class gr_block; -class gr_block_detail; -class gr_hier_block2; -class gr_io_signature; -class gr_buffer; -class gr_buffer_reader; -class gr_flowgraph; -class gr_flat_flowgraph; -class gr_top_block; -class gr_top_block_detail; - -typedef boost::shared_ptr<gr_basic_block> gr_basic_block_sptr; -typedef boost::shared_ptr<gr_block> gr_block_sptr; -typedef boost::shared_ptr<gr_block_detail> gr_block_detail_sptr; -typedef boost::shared_ptr<gr_hier_block2> gr_hier_block2_sptr; -typedef boost::shared_ptr<gr_io_signature> gr_io_signature_sptr; -typedef boost::shared_ptr<gr_buffer> gr_buffer_sptr; -typedef boost::shared_ptr<gr_buffer_reader> gr_buffer_reader_sptr; -typedef boost::shared_ptr<gr_flowgraph> gr_flowgraph_sptr; -typedef boost::shared_ptr<gr_flat_flowgraph> gr_flat_flowgraph_sptr; -typedef boost::shared_ptr<gr_top_block> gr_top_block_sptr; - -#endif /* INCLUDED_GR_RUNTIME_TYPES_H */ diff --git a/gnuradio-runtime/include/gr_select_handler.h b/gnuradio-runtime/include/gr_select_handler.h deleted file mode 100644 index ae4b9dfdb1..0000000000 --- a/gnuradio-runtime/include/gr_select_handler.h +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_SELECT_HANDLER_H -#define INCLUDED_GR_SELECT_HANDLER_H - -#include <gr_runtime_api.h> -#include <boost/shared_ptr.hpp> - -class gr_select_handler; -typedef boost::shared_ptr<gr_select_handler> gr_select_handler_sptr; - - -/*! - * \brief Abstract handler for select based notification. - * \ingroup base - * - * \sa gr_dispatcher - */ -class GR_RUNTIME_API gr_select_handler -{ - int d_fd; - -protected: - gr_select_handler(int file_descriptor); - -public: - virtual ~gr_select_handler(); - - int fd() const { return d_fd; } - int file_descriptor() const { return d_fd; } - - /*! - * \brief Called when file_descriptor is readable. - * - * Called when the dispatcher detects that file_descriptor can - * be read without blocking. - */ - virtual void handle_read() = 0; - - /*! - * \brief Called when file_descriptor is writable. - * - * Called when dispatcher detects that file descriptor can be - * written without blocking. - */ - virtual void handle_write() = 0; - - /*! - * Called each time around the dispatcher loop to determine whether - * this handler's file descriptor should be added to the list on which - * read events can occur. The default method returns true, indicating - * that by default, all handlers are interested in read events. - */ - virtual bool readable() { return true; } - - /*! - * Called each time around the dispatcher loop to determine whether - * this handler's file descriptor should be added to the list on which - * write events can occur. The default method returns true, indicating - * that by default, all handlers are interested in write events. - */ - virtual bool writable() { return true; } -}; - -#endif /* INCLUDED_GR_SELECT_HANDLER_H */ diff --git a/gnuradio-runtime/include/gr_sync_block.h b/gnuradio-runtime/include/gr_sync_block.h deleted file mode 100644 index 01eb646143..0000000000 --- a/gnuradio-runtime/include/gr_sync_block.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_SYNC_BLOCK_H -#define INCLUDED_GR_SYNC_BLOCK_H - -#include <gr_runtime_api.h> -#include <gr_block.h> - -/*! - * \brief synchronous 1:1 input to output with history - * \ingroup base_blk - * - * Override work to provide the signal processing implementation. - */ -class GR_RUNTIME_API gr_sync_block : public gr_block -{ - protected: - gr_sync_block (void){} //allows pure virtual interface sub-classes - gr_sync_block (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature); - - public: - - /*! - * \brief just like gr_block::general_work, only this arranges to call consume_each for you - * - * The user must override work to define the signal processing code - */ - virtual int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) = 0; - - - // gr_sync_block overrides these to assist work - void forecast (int noutput_items, gr_vector_int &ninput_items_required); - int general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - int fixed_rate_ninput_to_noutput(int ninput); - int fixed_rate_noutput_to_ninput(int noutput); -}; - -#endif /* INCLUDED_GR_SYNC_BLOCK_H */ diff --git a/gnuradio-runtime/include/gr_sync_decimator.h b/gnuradio-runtime/include/gr_sync_decimator.h deleted file mode 100644 index c799ee0f7c..0000000000 --- a/gnuradio-runtime/include/gr_sync_decimator.h +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_SYNC_DECIMATOR_H -#define INCLUDED_GR_SYNC_DECIMATOR_H - -#include <gr_runtime_api.h> -#include <gr_sync_block.h> - -/*! - * \brief synchronous N:1 input to output with history - * \ingroup base_blk - * - * Override work to provide the signal processing implementation. - */ -class GR_RUNTIME_API gr_sync_decimator : public gr_sync_block -{ - private: - unsigned d_decimation; - - protected: - gr_sync_decimator (void){} //allows pure virtual interface sub-classes - gr_sync_decimator (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature, - unsigned decimation); - public: - - unsigned decimation () const { return d_decimation; } - void set_decimation (unsigned decimation) - { - d_decimation = decimation; - set_relative_rate (1.0 / decimation); - } - - // gr_sync_decimator overrides these to assist work - void forecast (int noutput_items, gr_vector_int &ninput_items_required); - int general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - // derived classes should override work - - int fixed_rate_ninput_to_noutput(int ninput); - int fixed_rate_noutput_to_ninput(int noutput); -}; - - -#endif /* INCLUDED_GR_SYNC_DECIMATOR_H */ diff --git a/gnuradio-runtime/include/gr_sync_interpolator.h b/gnuradio-runtime/include/gr_sync_interpolator.h deleted file mode 100644 index f219916743..0000000000 --- a/gnuradio-runtime/include/gr_sync_interpolator.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2008 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_SYNC_INTERPOLATOR_H -#define INCLUDED_GR_SYNC_INTERPOLATOR_H - -#include <gr_runtime_api.h> -#include <gr_sync_block.h> - -/*! - * \brief synchronous 1:N input to output with history - * \ingroup base_blk - * - * Override work to provide the signal processing implementation. - */ -class GR_RUNTIME_API gr_sync_interpolator : public gr_sync_block -{ - private: - unsigned d_interpolation; - - protected: - gr_sync_interpolator (void){} //allows pure virtual interface sub-classes - gr_sync_interpolator (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature, - unsigned interpolation); - public: - - unsigned interpolation () const { return d_interpolation; } - void set_interpolation (unsigned interpolation) - { - d_interpolation = interpolation; - set_relative_rate (1.0 * interpolation); - set_output_multiple (interpolation); - } - - // gr_sync_interpolator overrides these to assist work - void forecast (int noutput_items, gr_vector_int &ninput_items_required); - int general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - // derived classes should override work - - int fixed_rate_ninput_to_noutput(int ninput); - int fixed_rate_noutput_to_ninput(int noutput); -}; - - -#endif /* INCLUDED_GR_SYNC_INTERPOLATOR_H */ diff --git a/gnuradio-runtime/include/gr_tagged_stream_block.h b/gnuradio-runtime/include/gr_tagged_stream_block.h deleted file mode 100644 index 67b144fb66..0000000000 --- a/gnuradio-runtime/include/gr_tagged_stream_block.h +++ /dev/null @@ -1,142 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_TAGGED_STREAM_BLOCK_H -#define INCLUDED_GR_TAGGED_STREAM_BLOCK_H - -#include <gr_runtime_api.h> -#include <gr_block.h> - -/*! - * \brief Block that operates on PDUs in form of tagged streams - * \ingroup base_blk - * - * Override work to provide the signal processing implementation. - */ -class GR_RUNTIME_API gr_tagged_stream_block : public gr_block -{ - private: - pmt::pmt_t d_length_tag_key; //!< This is the key for the tag that stores the PDU length - gr_vector_int d_n_input_items_reqd; //!< How many input items do I need to process the next PDU? - - protected: - std::string d_length_tag_key_str; - gr_tagged_stream_block (void){} //allows pure virtual interface sub-classes - gr_tagged_stream_block (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature, - const std::string &length_tag_key); - - /*! - * \brief Parse all tags on the first sample of a PDU, return the number of items per input - * and prune the length tags. - * - * In most cases, you don't need to override this, unless the number of items read - * is not directly coded in one single tag. - * - * Default behaviour: - * - Go through all input ports - * - On every input port, search for the tag with the key specified in \p length_tag_key - * - Copy that value as an int to the corresponding position in \p n_input_items_reqd - * - Remove the length tag. - * - * \param[in] tags All the tags found on the first item of every input port. - * \param[out] n_input_items_reqd Number of items which will be read from every input - */ - virtual void parse_length_tags( - const std::vector<std::vector<gr_tag_t> > &tags, - gr_vector_int &n_input_items_reqd - ); - - /*! - * \brief Calculate the number of output items. - * - * This is basically the inverse function to forecast(): Given a number of input - * items, it returns the maximum number of output items. - * - * You most likely need to override this function, unless your block is a sync - * block or integer interpolator/decimator. - * - */ - virtual int calculate_output_stream_length(const gr_vector_int &ninput_items); - - /*! - * \brief Set the new length tags on the output stream - * - * Default behaviour: Set a tag with key \p length_tag_key and - * the number of produced items on every output port. - * - * For anything else, override this. - * - * \param n_produced Length of the new PDU - * \param n_ports Number of output ports - */ - virtual void update_length_tags(int n_produced, int n_ports); - - public: - - /*! \brief Don't override this. - */ - void /* final */ forecast (int noutput_items, gr_vector_int &ninput_items_required); - - /*! - * - Reads the number of input items from the tags using parse_length_tags() - * - Checks there's enough data on the input and output buffers - * - If not, inform the scheduler and do nothing - * - Calls work() with the exact number of items per PDU - * - Updates the tags using update_length_tags() - */ - int general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - /*! - * \brief Just like gr_block::general_work, but makes sure the input is valid - * - * The user must override work to define the signal processing code. - * Check the documentation for general_work() to see what happens here. - * - * Like gr_sync_block, this calls consume() for you (it consumes ninput_items[i] - * items from the i-th port). - * - * A note on tag propagation: The PDU length tags are handled by other functions, - * but all other tags are handled just as in any other \p gr_block. So, most likely, - * you either set the tag propagation policy to TPP_DONT and handle the tag - * propagation manually, or you propagate tags through the scheduler and don't - * do anything here. - * - * \param noutput_items The size of the writable output buffer - * \param ninput_items The exact size of the items on every input for this particular PDU. - * These will be consumed if a length tag key is provided! - * \param input_items See gr_block - * \param output_items See gr_block - */ - virtual int work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) = 0; - -}; - -#endif /* INCLUDED_GR_TAGGED_STREAM_BLOCK_H */ - diff --git a/gnuradio-runtime/include/gr_top_block.h b/gnuradio-runtime/include/gr_top_block.h deleted file mode 100644 index f523442cd0..0000000000 --- a/gnuradio-runtime/include/gr_top_block.h +++ /dev/null @@ -1,141 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007-2009 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_TOP_BLOCK_H -#define INCLUDED_GR_TOP_BLOCK_H - -#include <gr_runtime_api.h> -#include <gr_hier_block2.h> - -class gr_top_block_impl; - -GR_RUNTIME_API gr_top_block_sptr gr_make_top_block(const std::string &name); - -/*! - *\brief Top-level hierarchical block representing a flowgraph - * \ingroup container_blk - * - */ -class GR_RUNTIME_API gr_top_block : public gr_hier_block2 -{ -private: - friend GR_RUNTIME_API gr_top_block_sptr gr_make_top_block(const std::string &name); - - gr_top_block_impl *d_impl; - -protected: - gr_top_block(const std::string &name); - -public: - ~gr_top_block(); - - /*! - * \brief The simple interface to running a flowgraph. - * - * Calls start() then wait(). Used to run a flowgraph that will stop - * on its own, or when another thread will call stop(). - * - * \param max_noutput_items the maximum number of output items - * allowed for any block in the flowgraph. This passes through to - * the start function; see that function for more details. - */ - void run(int max_noutput_items=100000000); - - /*! - * Start the contained flowgraph. Creates one or more threads to - * execute the flow graph. Returns to the caller once the threads - * are created. Calling start() on a top_block that is already - * started IS an error. - * - * \param max_noutput_items the maximum number of output items - * allowed for any block in the flowgraph; the noutput_items can - * always be less than this, but this will cap it as a maximum. Use - * this to adjust the maximum latency a flowgraph can exhibit. - */ - void start(int max_noutput_items=100000000); - - /*! - * Stop the running flowgraph. Notifies each thread created by the - * scheduler to shutdown, then returns to caller. Calling stop() on - * a top_block that is already stopped IS NOT an error. - */ - void stop(); - - /*! - * Wait for a flowgraph to complete. Flowgraphs complete when - * either (1) all blocks indicate that they are done (typically only - * when using blocks.file_source, or blocks.head, or (2) after stop() has been - * called to request shutdown. Calling wait on a top_block that is - * not running IS NOT an error (wait returns w/o blocking). - */ - void wait(); - - /*! - * Lock a flowgraph in preparation for reconfiguration. When an equal - * number of calls to lock() and unlock() have occurred, the flowgraph - * will be reconfigured. - * - * N.B. lock() and unlock() may not be called from a flowgraph thread - * (E.g., gr_block::work method) or deadlock will occur when - * reconfiguration happens. - */ - virtual void lock(); - - /*! - * Unlock a flowgraph in preparation for reconfiguration. When an equal - * number of calls to lock() and unlock() have occurred, the flowgraph - * will be reconfigured. - * - * N.B. lock() and unlock() may not be called from a flowgraph thread - * (E.g., gr_block::work method) or deadlock will occur when - * reconfiguration happens. - */ - virtual void unlock(); - - /*! - * Returns a string that lists the edge connections in the flattened - * flowgraph. - */ - std::string edge_list(); - - /*! - * Displays flattened flowgraph edges and block connectivity - */ - void dump(); - - //! Get the number of max noutput_items in the flowgraph - int max_noutput_items(); - - //! Set the maximum number of noutput_items in the flowgraph - void set_max_noutput_items(int nmax); - - gr_top_block_sptr to_top_block(); // Needed for Python type coercion - - void setup_rpc(); -}; - -inline gr_top_block_sptr cast_to_top_block_sptr(gr_basic_block_sptr block) { - return boost::dynamic_pointer_cast<gr_top_block, gr_basic_block>(block); -} - - -#endif /* INCLUDED_GR_TOP_BLOCK_H */ diff --git a/gnuradio-runtime/include/gr_tpb_detail.h b/gnuradio-runtime/include/gr_tpb_detail.h deleted file mode 100644 index f6f20917c9..0000000000 --- a/gnuradio-runtime/include/gr_tpb_detail.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2009 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 3, 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_GR_TPB_DETAIL_H -#define INCLUDED_GR_TPB_DETAIL_H - -#include <gr_runtime_api.h> -#include <thread/thread.h> -#include <deque> -#include <pmt/pmt.h> - -class gr_block_detail; - -/*! - * \brief used by thread-per-block scheduler - */ -struct GR_RUNTIME_API gr_tpb_detail { - - gr::thread::mutex mutex; //< protects all vars - bool input_changed; - gr::thread::condition_variable input_cond; - bool output_changed; - gr::thread::condition_variable output_cond; - -public: - gr_tpb_detail() - : input_changed(false), output_changed(false) { } - - //! Called by us to tell all our upstream blocks that their output may have changed. - void notify_upstream(gr_block_detail *d); - - //! Called by us to tell all our downstream blocks that their input may have changed. - void notify_downstream(gr_block_detail *d); - - //! Called by us to notify both upstream and downstream - void notify_neighbors(gr_block_detail *d); - - //! Called by pmt msg posters - void notify_msg(){ - input_cond.notify_one(); - output_cond.notify_one(); - } - - //! Called by us - void clear_changed() - { - gr::thread::scoped_lock guard(mutex); - input_changed = false; - output_changed = false; - } - -private: - - //! Used by notify_downstream - void set_input_changed() - { - gr::thread::scoped_lock guard(mutex); - input_changed = true; - input_cond.notify_one(); - } - - //! Used by notify_upstream - void set_output_changed() - { - gr::thread::scoped_lock guard(mutex); - output_changed = true; - output_cond.notify_one(); - } - -}; - -#endif /* INCLUDED_GR_TPB_DETAIL_H */ diff --git a/gnuradio-runtime/include/pmt/api.h b/gnuradio-runtime/include/pmt/api.h index 96f1f8c26b..69674dbd77 100644 --- a/gnuradio-runtime/include/pmt/api.h +++ b/gnuradio-runtime/include/pmt/api.h @@ -22,7 +22,7 @@ #ifndef INCLUDED_PMT_API_H #define INCLUDED_PMT_API_H -#include <attributes.h> +#include <gnuradio/attributes.h> #ifdef gnuradio_pmt_EXPORTS # define PMT_API __GR_ATTR_EXPORT diff --git a/gnuradio-runtime/include/pmt/pmt_sugar.h b/gnuradio-runtime/include/pmt/pmt_sugar.h index 09c9a5e3e4..870b81902e 100644 --- a/gnuradio-runtime/include/pmt/pmt_sugar.h +++ b/gnuradio-runtime/include/pmt/pmt_sugar.h @@ -27,7 +27,7 @@ * shorthand for making pmt objects */ -#include <messages/msg_accepter.h> +#include <gnuradio/messages/msg_accepter.h> namespace pmt { diff --git a/gnuradio-runtime/include/realtime.h b/gnuradio-runtime/include/realtime.h deleted file mode 100644 index 9a51a6ba1d..0000000000 --- a/gnuradio-runtime/include/realtime.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2008,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GNURADIO_REALTIME_H -#define INCLUDED_GNURADIO_REALTIME_H - -#include <gr_runtime_api.h> -#include <stdexcept> - -/*! - * \brief System independent way to ask for realtime scheduling - * - * \sa sys_pri.h - */ - -namespace gr { - - typedef enum { - RT_OK = 0, - RT_NOT_IMPLEMENTED, - RT_NO_PRIVS, - RT_OTHER_ERROR - } rt_status_t; - - - enum rt_sched_policy { - RT_SCHED_RR = 0, // round robin - RT_SCHED_FIFO = 1, // first in first out - }; - - /* - * Define the range for our virtual priorities (don't change these) - * - * Processes (or threads) with numerically higher priority values - * are scheduled before processes with numerically lower priority - * values. Thus, the value returned by rt_priority_max() will be - * greater than the value returned by rt_priority_min(). - */ - static inline int rt_priority_min() { return 0; } - static inline int rt_priority_max() { return 15; } - static inline int rt_priority_default() { return 1; } - - struct GR_RUNTIME_API rt_sched_param { - int priority; - rt_sched_policy policy; - - rt_sched_param() - : priority(rt_priority_default()), policy(RT_SCHED_RR){} - - rt_sched_param(int priority_, rt_sched_policy policy_ = RT_SCHED_RR) - { - if (priority_ < rt_priority_min() || priority_ > rt_priority_max()) - throw std::invalid_argument("rt_sched_param: priority out of range"); - - priority = priority_; - policy = policy_; - } - }; - - /*! - * \brief If possible, enable "realtime" scheduling. - * \ingroup misc - * - * In general, this means that the code will be scheduled before any - * non-realtime (normal) processes. Note that if your code contains - * an non-blocking infinite loop and you enable realtime scheduling, - * it's possible to hang the system. - */ - - // NOTE: If you change this, you need to change the code in - // gnuradio-core/src/lib/runtime/gr_realtime.i, see note there. - rt_status_t - GR_RUNTIME_API enable_realtime_scheduling(rt_sched_param = rt_sched_param()); - -} // namespace gr - -#endif /* INCLUDED_GNURADIO_REALTIME_H */ diff --git a/gnuradio-runtime/include/runtime_block_gateway.h b/gnuradio-runtime/include/runtime_block_gateway.h deleted file mode 100644 index 390864376f..0000000000 --- a/gnuradio-runtime/include/runtime_block_gateway.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright 2011-2012 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_RUNTIME_BLOCK_GATEWAY_H -#define INCLUDED_RUNTIME_BLOCK_GATEWAY_H - -#include <gr_runtime_api.h> -#include <gr_block.h> -#include <gr_feval.h> - -/*! - * The work type enum tells the gateway what kind of block to implement. - * The choices are familiar gnuradio block overloads (sync, decim, interp). - */ -enum gr_block_gw_work_type{ - GR_BLOCK_GW_WORK_GENERAL, - GR_BLOCK_GW_WORK_SYNC, - GR_BLOCK_GW_WORK_DECIM, - GR_BLOCK_GW_WORK_INTERP, -}; - -/*! - * Shared message structure between python and gateway. - * Each action type represents a scheduler-called function. - */ -struct gr_block_gw_message_type{ - enum action_type{ - ACTION_GENERAL_WORK, //dispatch work - ACTION_WORK, //dispatch work - ACTION_FORECAST, //dispatch forecast - ACTION_START, //dispatch start - ACTION_STOP, //dispatch stop - }; - - action_type action; - - int general_work_args_noutput_items; - std::vector<int> general_work_args_ninput_items; - std::vector<void *> general_work_args_input_items; //TODO this should be const void*, but swig cant int cast it right - std::vector<void *> general_work_args_output_items; - int general_work_args_return_value; - - int work_args_ninput_items; - int work_args_noutput_items; - std::vector<void *> work_args_input_items; //TODO this should be const void*, but swig cant int cast it right - std::vector<void *> work_args_output_items; - int work_args_return_value; - - int forecast_args_noutput_items; - std::vector<int> forecast_args_ninput_items_required; - - bool start_args_return_value; - - bool stop_args_return_value; -}; - -/*! - * The gateway block which performs all the magic. - * - * The gateway provides access to all the gr_block routines. - * The methods prefixed with gr_block__ are renamed - * to class methods without the prefix in python. - */ -class GR_RUNTIME_API runtime_block_gateway : virtual public gr_block{ -public: - //! Provide access to the shared message object - virtual gr_block_gw_message_type &gr_block_message(void) = 0; - - long gr_block__unique_id(void) const{ - return gr_block::unique_id(); - } - - std::string gr_block__name(void) const{ - return gr_block::name(); - } - - unsigned gr_block__history(void) const{ - return gr_block::history(); - } - - void gr_block__set_history(unsigned history){ - return gr_block::set_history(history); - } - - void gr_block__set_fixed_rate(bool fixed_rate){ - return gr_block::set_fixed_rate(fixed_rate); - } - - bool gr_block__fixed_rate(void) const{ - return gr_block::fixed_rate(); - } - - void gr_block__set_output_multiple(int multiple){ - return gr_block::set_output_multiple(multiple); - } - - int gr_block__output_multiple(void) const{ - return gr_block::output_multiple(); - } - - void gr_block__consume(int which_input, int how_many_items){ - return gr_block::consume(which_input, how_many_items); - } - - void gr_block__consume_each(int how_many_items){ - return gr_block::consume_each(how_many_items); - } - - void gr_block__produce(int which_output, int how_many_items){ - return gr_block::produce(which_output, how_many_items); - } - - void gr_block__set_relative_rate(double relative_rate){ - return gr_block::set_relative_rate(relative_rate); - } - - double gr_block__relative_rate(void) const{ - return gr_block::relative_rate(); - } - - uint64_t gr_block__nitems_read(unsigned int which_input){ - return gr_block::nitems_read(which_input); - } - - uint64_t gr_block__nitems_written(unsigned int which_output){ - return gr_block::nitems_written(which_output); - } - - gr_block::tag_propagation_policy_t gr_block__tag_propagation_policy(void){ - return gr_block::tag_propagation_policy(); - } - - void gr_block__set_tag_propagation_policy(gr_block::tag_propagation_policy_t p){ - return gr_block::set_tag_propagation_policy(p); - } - - void gr_block__add_item_tag( - unsigned int which_output, const gr_tag_t &tag - ){ - return gr_block::add_item_tag(which_output, tag); - } - - void gr_block__add_item_tag( - unsigned int which_output, - uint64_t abs_offset, - const pmt::pmt_t &key, - const pmt::pmt_t &value, - const pmt::pmt_t &srcid=pmt::PMT_F - ){ - return gr_block::add_item_tag(which_output, abs_offset, key, value, srcid); - } - - std::vector<gr_tag_t> gr_block__get_tags_in_range( - unsigned int which_input, - uint64_t abs_start, - uint64_t abs_end - ){ - std::vector<gr_tag_t> tags; - gr_block::get_tags_in_range(tags, which_input, abs_start, abs_end); - return tags; - } - - std::vector<gr_tag_t> gr_block__get_tags_in_range( - unsigned int which_input, - uint64_t abs_start, - uint64_t abs_end, - const pmt::pmt_t &key - ){ - std::vector<gr_tag_t> tags; - gr_block::get_tags_in_range(tags, which_input, abs_start, abs_end, key); - return tags; - } - - /* Message passing interface */ - void gr_block__message_port_register_in(pmt::pmt_t port_id){ - gr_basic_block::message_port_register_in(port_id); - } - - void gr_block__message_port_register_out(pmt::pmt_t port_id){ - gr_basic_block::message_port_register_out(port_id); - } - - void gr_block__message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg){ - gr_basic_block::message_port_pub(port_id, msg); - } - - void gr_block__message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target){ - gr_basic_block::message_port_sub(port_id, target); - } - - void gr_block__message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target){ - gr_basic_block::message_port_unsub(port_id, target); - } - - pmt::pmt_t gr_block__message_ports_in(){ - return gr_basic_block::message_ports_in(); - } - - pmt::pmt_t gr_block__message_ports_out(){ - return gr_basic_block::message_ports_out(); - } - - void set_msg_handler_feval(pmt::pmt_t which_port, gr_feval_p *msg_handler) - { - if(msg_queue.find(which_port) == msg_queue.end()){ - throw std::runtime_error("attempt to set_msg_handler_feval() on bad input message port!"); - } - d_msg_handlers_feval[which_port] = msg_handler; - } - -protected: - typedef std::map<pmt::pmt_t, gr_feval_p *, pmt::comperator> msg_handlers_feval_t; - msg_handlers_feval_t d_msg_handlers_feval; - - void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg){ - // Is there a handler? - if (d_msg_handlers_feval.find(which_port) != d_msg_handlers_feval.end()){ - d_msg_handlers_feval[which_port]->calleval(msg); // Yes, invoke it. - } - else { - // Pass to generic dispatcher if not found - gr_basic_block::dispatch_msg(which_port, msg); - } - } -}; - -/*! - * Make a new gateway block. - * \param handler the swig director object with callback - * \param name the name of the block (Ex: "Shirley") - * \param in_sig the input signature for this block - * \param out_sig the output signature for this block - * \param work_type the type of block overload to implement - * \param factor the decimation or interpolation factor - * \return a new gateway block - */ -GR_RUNTIME_API boost::shared_ptr<runtime_block_gateway> -runtime_make_block_gateway( - gr_feval_ll *handler, - const std::string &name, - gr_io_signature_sptr in_sig, - gr_io_signature_sptr out_sig, - const gr_block_gw_work_type work_type, - const unsigned factor -); - -#endif /* INCLUDED_RUNTIME_BLOCK_GATEWAY_H */ diff --git a/gnuradio-runtime/lib/CMakeLists.txt b/gnuradio-runtime/lib/CMakeLists.txt index 98db673f5d..5193b98f57 100644 --- a/gnuradio-runtime/lib/CMakeLists.txt +++ b/gnuradio-runtime/lib/CMakeLists.txt @@ -27,8 +27,8 @@ execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import time;print time.strftime('%a, %d %b %Y %H:%M:%S', time.gmtime())" OUTPUT_VARIABLE BUILD_DATE OUTPUT_STRIP_TRAILING_WHITESPACE ) -message(STATUS "Loading build date ${BUILD_DATE} into gr_constants...") -message(STATUS "Loading version ${VERSION} into gr_constants...") +message(STATUS "Loading build date ${BUILD_DATE} into constants...") +message(STATUS "Loading version ${VERSION} into constants...") #double escape for windows backslash path separators string(REPLACE "\\" "\\\\" prefix ${prefix}) @@ -36,11 +36,11 @@ string(REPLACE "\\" "\\\\" SYSCONFDIR ${SYSCONFDIR}) string(REPLACE "\\" "\\\\" GR_PREFSDIR ${GR_PREFSDIR}) configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/gr_constants.cc.in - ${CMAKE_CURRENT_BINARY_DIR}/gr_constants.cc + ${CMAKE_CURRENT_SOURCE_DIR}/constants.cc.in + ${CMAKE_CURRENT_BINARY_DIR}/constants.cc @ONLY) -list(APPEND gnuradio_runtime_sources ${CMAKE_CURRENT_BINARY_DIR}/gr_constants.cc) +list(APPEND gnuradio_runtime_sources ${CMAKE_CURRENT_BINARY_DIR}/constants.cc) ######################################################################## # Include subdirs rather to populate to the sources lists. @@ -63,67 +63,62 @@ include_directories(${GNURADIO_RUNTIME_INCLUDE_DIRS} GR_INCLUDE_SUBDIRECTORY(pmt) GR_INCLUDE_SUBDIRECTORY(messages) GR_INCLUDE_SUBDIRECTORY(thread) +GR_INCLUDE_SUBDIRECTORY(math) ######################################################################## # Setup library ######################################################################## list(APPEND gnuradio_runtime_sources complex_vec_test.cc - gr_basic_block.cc - gr_block.cc - gr_block_detail.cc - gr_block_executor.cc - gr_block_registry.cc - gr_buffer.cc - gr_circular_file.cc - gr_dispatcher.cc - gr_error_handler.cc - gr_fast_atan2f.cc - gr_feval.cc - gr_flat_flowgraph.cc - gr_flowgraph.cc - gr_fxpt.cc - gr_hier_block2.cc - gr_hier_block2_detail.cc - gri_debugger_hook.cc - gr_io_signature.cc - gr_local_sighandler.cc - gr_logger.cc - gr_message.cc - gr_misc.cc - gr_msg_accepter.cc - gr_msg_handler.cc - gr_msg_queue.cc - gr_pagesize.cc - gr_preferences.cc - gr_prefs.cc - gr_random.cc - gr_realtime.cc - gr_reverse.cc - gr_scheduler.cc - gr_scheduler_sts.cc - gr_scheduler_tpb.cc - gr_select_handler.cc - gr_sincos.c - gr_single_threaded_scheduler.cc - gr_sptr_magic.cc - gr_sync_block.cc - gr_sync_decimator.cc - gr_sync_interpolator.cc - gr_sys_paths.cc - gr_tagged_stream_block.cc - gr_test.cc - gr_top_block.cc - gr_top_block_impl.cc - gr_tpb_detail.cc - gr_tpb_thread_body.cc - gr_vmcircbuf.cc - gr_vmcircbuf_createfilemapping.cc - gr_vmcircbuf_mmap_shm_open.cc - gr_vmcircbuf_mmap_tmpfile.cc - gr_vmcircbuf_sysv_shm.cc malloc16.c - runtime_block_gateway.cc + basic_block.cc + block.cc + block_detail.cc + block_executor.cc + block_gateway_impl.cc + block_registry.cc + buffer.cc + circular_file.cc + dispatcher.cc + error_handler.cc + feval.cc + flat_flowgraph.cc + flowgraph.cc + hier_block2.cc + hier_block2_detail.cc + io_signature.cc + local_sighandler.cc + logger.cc + message.cc + misc.cc + msg_accepter.cc + msg_handler.cc + msg_queue.cc + pagesize.cc + prefs.cc + tagged_stream_block.cc + test.cc + top_block.cc + top_block_impl.cc + realtime.cc + scheduler.cc + scheduler_sts.cc + scheduler_tpb.cc + select_handler.cc + single_threaded_scheduler.cc + sptr_magic.cc + sync_block.cc + sync_decimator.cc + sync_interpolator.cc + sys_paths.cc + tpb_detail.cc + tpb_thread_body.cc + vmcircbuf.cc + vmcircbuf_createfilemapping.cc + vmcircbuf_mmap_shm_open.cc + vmcircbuf_mmap_tmpfile.cc + vmcircbuf_prefs.cc + vmcircbuf_sysv_shm.cc ) # PowerPC workaround for posix_memalign @@ -154,50 +149,7 @@ if(LINUX) list(APPEND gnuradio_runtime_libs rt) endif() -if(ENABLE_GR_CTRLPORT) - -include_directories(${ICE_INCLUDE_DIR}) - -# Add definition so we can compile in ControlPort to the blocks. -ADD_DEFINITIONS(-DGR_CTRLPORT) - -######################################################################## -# Run ICE To compile Slice files -######################################################################## -EXECUTE_PROCESS( - COMMAND "${ICE_SLICE2CPP}" "-I${CMAKE_CURRENT_SOURCE_DIR}" - "--output-dir=${CMAKE_CURRENT_BINARY_DIR}" - "${CMAKE_CURRENT_SOURCE_DIR}/gnuradio.ice" - ) - -list(APPEND gnuradio_runtime_sources - ice_application_base.cc - rpcmanager.cc - rpcpmtconverters_ice.cc - rpcserver_aggregator.cc - rpcserver_booter_aggregator.cc - rpcserver_booter_ice.cc - rpcserver_ice.cc - rpcserver_selector.cc - rpcpmtconverters_ice.cc -) - -# Append generated file in build directory -list(APPEND gnuradio_runtime_sources - ${CMAKE_CURRENT_BINARY_DIR}/gnuradio.cpp -) - -######################################################################## -# Add controlport stuff to gnuradio-runtime -######################################################################## - -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - -list(APPEND gnuradio_runtime_libs - ${ICE_LIBRARIES} -) - -endif(ENABLE_GR_CTRLPORT) +GR_INCLUDE_SUBDIRECTORY(controlport) ######################################################################## # Add DLL resource file when using MSVC @@ -257,23 +209,23 @@ include(GrTest) # Append gnuradio-runtime test sources ######################################################################## list(APPEND test_gnuradio_runtime_sources - qa_gr_buffer.cc - qa_gr_circular_file.cc - qa_gr_fxpt.cc - qa_gr_fxpt_nco.cc - qa_gr_fxpt_vco.cc - qa_gr_io_signature.cc - qa_gr_logger.cc - qa_gr_math.cc - qa_gr_vmcircbuf.cc - qa_runtime.cc - qa_sincos.cc + math/qa_fxpt.cc + math/qa_fxpt_nco.cc + math/qa_fxpt_vco.cc + math/qa_math.cc + math/qa_sincos.cc pmt/qa_pmt.cc pmt/qa_pmt_prims.cc + qa_buffer.cc + qa_io_signature.cc + qa_circular_file.cc + qa_logger.cc + qa_vmcircbuf.cc + qa_runtime.cc ${CMAKE_CURRENT_BINARY_DIR}/pmt/qa_pmt_unv.cc ) -include_directories(${CPPUNIT_INCLUDE_DIRS}) +include_directories(${CPPUNIT_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/math) link_directories(${CPPUNIT_LIBRARY_DIRS}) add_library(test-gnuradio-runtime SHARED ${test_gnuradio_runtime_sources}) diff --git a/gnuradio-runtime/lib/basic_block.cc b/gnuradio-runtime/lib/basic_block.cc new file mode 100644 index 0000000000..8060c5355c --- /dev/null +++ b/gnuradio-runtime/lib/basic_block.cc @@ -0,0 +1,233 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2012-2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/basic_block.h> +#include <gnuradio/block_registry.h> +#include <stdexcept> +#include <sstream> +#include <iostream> + +namespace gr { + + static long s_next_id = 0; + static long s_ncurrently_allocated = 0; + + long + basic_block_ncurrently_allocated() + { + return s_ncurrently_allocated; + } + + basic_block::basic_block(const std::string &name, + io_signature::sptr input_signature, + io_signature::sptr output_signature) + : d_name(name), + d_input_signature(input_signature), + d_output_signature(output_signature), + d_unique_id(s_next_id++), + d_symbolic_id(global_block_registry.block_register(this)), + d_symbol_name(global_block_registry.register_symbolic_name(this)), + d_color(WHITE), + d_rpc_set(false), + message_subscribers(pmt::make_dict()) + { + s_ncurrently_allocated++; + } + + basic_block::~basic_block() + { + s_ncurrently_allocated--; + global_block_registry.block_unregister(this); + } + + basic_block_sptr + basic_block::to_basic_block() + { + return shared_from_this(); + } + + void + basic_block::set_block_alias(std::string name) + { + global_block_registry.register_symbolic_name(this, name); + } + + // ** Message passing interface ** + + // - register a new input message port + void + basic_block::message_port_register_in(pmt::pmt_t port_id) + { + if(!pmt::is_symbol(port_id)) { + throw std::runtime_error("message_port_register_in: bad port id"); + } + msg_queue[port_id] = msg_queue_t(); + msg_queue_ready[port_id] = boost::shared_ptr<boost::condition_variable>(new boost::condition_variable()); + } + + pmt::pmt_t + basic_block::message_ports_in() + { + pmt::pmt_t port_names = pmt::make_vector(msg_queue.size(), pmt::PMT_NIL); + msg_queue_map_itr itr = msg_queue.begin(); + for(size_t i = 0; i < msg_queue.size(); i++) { + pmt::vector_set(port_names, i, (*itr).first); + itr++; + } + return port_names; + } + + // - register a new output message port + void + basic_block::message_port_register_out(pmt::pmt_t port_id) + { + if(!pmt::is_symbol(port_id)) { + throw std::runtime_error("message_port_register_out: bad port id"); + } + if(pmt::dict_has_key(message_subscribers, port_id)) { + throw std::runtime_error("message_port_register_out: port already in use"); + } + message_subscribers = pmt::dict_add(message_subscribers, port_id, pmt::PMT_NIL); + } + + pmt::pmt_t + basic_block::message_ports_out() + { + size_t len = pmt::length(message_subscribers); + pmt::pmt_t port_names = pmt::make_vector(len, pmt::PMT_NIL); + pmt::pmt_t keys = pmt::dict_keys(message_subscribers); + for(size_t i = 0; i < len; i++) { + pmt::vector_set(port_names, i, pmt::nth(i, keys)); + } + return port_names; + } + + // - publish a message on a message port + void basic_block::message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg) + { + if(!pmt::dict_has_key(message_subscribers, port_id)) { + throw std::runtime_error("port does not exist"); + } + + pmt::pmt_t currlist = pmt::dict_ref(message_subscribers, port_id, pmt::PMT_NIL); + // iterate through subscribers on port + while(pmt::is_pair(currlist)) { + pmt::pmt_t target = pmt::car(currlist); + + pmt::pmt_t block = pmt::car(target); + pmt::pmt_t port = pmt::cdr(target); + + currlist = pmt::cdr(currlist); + basic_block_sptr blk = global_block_registry.block_lookup(block); + //blk->post(msg); + blk->post(port, msg); + } + } + + // - subscribe to a message port + void + basic_block::message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target){ + if(!pmt::dict_has_key(message_subscribers, port_id)){ + std::stringstream ss; + ss << "Port does not exist: \"" << pmt::write_string(port_id) << "\" on block: " + << pmt::write_string(target) << std::endl; + throw std::runtime_error(ss.str()); + } + pmt::pmt_t currlist = pmt::dict_ref(message_subscribers,port_id,pmt::PMT_NIL); + + // ignore re-adds of the same target + if(!pmt::list_has(currlist, target)) + message_subscribers = pmt::dict_add(message_subscribers,port_id,pmt::list_add(currlist,target)); + } + + void + basic_block::message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target) + { + if(!pmt::dict_has_key(message_subscribers, port_id)) { + std::stringstream ss; + ss << "Port does not exist: \"" << pmt::write_string(port_id) << "\" on block: " + << pmt::write_string(target) << std::endl; + throw std::runtime_error(ss.str()); + } + + // ignore unsubs of unknown targets + pmt::pmt_t currlist = pmt::dict_ref(message_subscribers,port_id,pmt::PMT_NIL); + message_subscribers = pmt::dict_add(message_subscribers,port_id,pmt::list_rm(currlist,target)); + } + + void + basic_block::_post(pmt::pmt_t which_port, pmt::pmt_t msg) + { + insert_tail(which_port, msg); + } + + void + basic_block::insert_tail(pmt::pmt_t which_port, pmt::pmt_t msg) + { + gr::thread::scoped_lock guard(mutex); + + if((msg_queue.find(which_port) == msg_queue.end()) || (msg_queue_ready.find(which_port) == msg_queue_ready.end())) { + std::cout << "target port = " << pmt::symbol_to_string(which_port) << std::endl; + throw std::runtime_error("attempted to insert_tail on invalid queue!"); + } + + msg_queue[which_port].push_back(msg); + msg_queue_ready[which_port]->notify_one(); + + // wake up thread if BLKD_IN or BLKD_OUT + global_block_registry.notify_blk(alias()); + } + + pmt::pmt_t + basic_block::delete_head_nowait(pmt::pmt_t which_port) + { + gr::thread::scoped_lock guard(mutex); + + if(empty_p(which_port)) { + return pmt::pmt_t(); + } + + pmt::pmt_t m(msg_queue[which_port].front()); + msg_queue[which_port].pop_front(); + + return m; + } + + pmt::pmt_t + basic_block::delete_head_blocking(pmt::pmt_t which_port) + { + gr::thread::scoped_lock guard(mutex); + + while(empty_p(which_port)) { + msg_queue_ready[which_port]->wait(guard); + } + + pmt::pmt_t m(msg_queue[which_port].front()); + msg_queue[which_port].pop_front(); + return m; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/block.cc b/gnuradio-runtime/lib/block.cc new file mode 100644 index 0000000000..b38377e856 --- /dev/null +++ b/gnuradio-runtime/lib/block.cc @@ -0,0 +1,689 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2009,2010,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/block.h> +#include <gnuradio/block_registry.h> +#include <gnuradio/block_detail.h> +#include <gnuradio/prefs.h> +#include <stdexcept> +#include <iostream> + +namespace gr { + + block::block(const std::string &name, + io_signature::sptr input_signature, + io_signature::sptr output_signature) + : basic_block(name, input_signature, output_signature), + d_output_multiple (1), + d_output_multiple_set(false), + d_unaligned(0), + d_is_unaligned(false), + d_relative_rate (1.0), + d_history(1), + d_fixed_rate(false), + d_max_noutput_items_set(false), + d_max_noutput_items(0), + d_min_noutput_items(0), + d_tag_propagation_policy(TPP_ALL_TO_ALL), + d_pc_rpc_set(false), + d_max_output_buffer(std::max(output_signature->max_streams(),1), -1), + d_min_output_buffer(std::max(output_signature->max_streams(),1), -1) + { + global_block_registry.register_primitive(alias(), this); + +#ifdef ENABLE_GR_LOG +#ifdef HAVE_LOG4CPP + prefs *p = prefs::singleton(); + std::string config_file = p->get_string("LOG", "log_config", ""); + std::string log_level = p->get_string("LOG", "log_level", "off"); + std::string log_file = p->get_string("LOG", "log_file", ""); + std::string debug_level = p->get_string("LOG", "debug_level", "off"); + std::string debug_file = p->get_string("LOG", "debug_file", ""); + + GR_CONFIG_LOGGER(config_file); + + GR_LOG_GETLOGGER(LOG, "gr_log." + alias()); + GR_LOG_SET_LEVEL(LOG, log_level); + if(log_file.size() > 0) { + if(log_file == "stdout") { + GR_LOG_ADD_CONSOLE_APPENDER(LOG, "cout","gr::log :%p: %c{1} - %m%n"); + } + else if(log_file == "stderr") { + GR_LOG_ADD_CONSOLE_APPENDER(LOG, "cerr","gr::log :%p: %c{1} - %m%n"); + } + else { + GR_LOG_ADD_FILE_APPENDER(LOG, log_file , true,"%r :%p: %c{1} - %m%n"); + } + } + d_logger = LOG; + + GR_LOG_GETLOGGER(DLOG, "gr_log_debug." + alias()); + GR_LOG_SET_LEVEL(DLOG, debug_level); + if(debug_file.size() > 0) { + if(debug_file == "stdout") { + GR_LOG_ADD_CONSOLE_APPENDER(DLOG, "cout","gr::debug :%p: %c{1} - %m%n"); + } + else if(debug_file == "stderr") { + GR_LOG_ADD_CONSOLE_APPENDER(DLOG, "cerr", "gr::debug :%p: %c{1} - %m%n"); + } + else { + GR_LOG_ADD_FILE_APPENDER(DLOG, debug_file, true, "%r :%p: %c{1} - %m%n"); + } + } + d_debug_logger = DLOG; +#endif /* HAVE_LOG4CPP */ +#else /* ENABLE_GR_LOG */ + d_logger = NULL; + d_debug_logger = NULL; +#endif /* ENABLE_GR_LOG */ + } + + block::~block() + { + global_block_registry.unregister_primitive(alias()); + } + + // stub implementation: 1:1 + + void + block::forecast(int noutput_items, gr_vector_int &ninput_items_required) + { + unsigned ninputs = ninput_items_required.size (); + for(unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = noutput_items + history() - 1; + } + + // default implementation + + bool + block::start() + { + return true; + } + + bool + block::stop() + { + return true; + } + + void + block::set_output_multiple(int multiple) + { + if(multiple < 1) + throw std::invalid_argument("block::set_output_multiple"); + + d_output_multiple_set = true; + d_output_multiple = multiple; + } + + void + block::set_alignment(int multiple) + { + if(multiple < 1) + throw std::invalid_argument("block::set_alignment_multiple"); + + d_output_multiple = multiple; + } + + void + block::set_unaligned(int na) + { + // unaligned value must be less than 0 and it doesn't make sense + // that it's larger than the alignment value. + if((na < 0) || (na > d_output_multiple)) + throw std::invalid_argument("block::set_unaligned"); + + d_unaligned = na; + } + + void + block::set_is_unaligned(bool u) + { + d_is_unaligned = u; + } + + void + block::set_relative_rate(double relative_rate) + { + if(relative_rate < 0.0) + throw std::invalid_argument("block::set_relative_rate"); + + d_relative_rate = relative_rate; + } + + void + block::consume(int which_input, int how_many_items) + { + d_detail->consume(which_input, how_many_items); + } + + void + block::consume_each(int how_many_items) + { + d_detail->consume_each(how_many_items); + } + + void + block::produce(int which_output, int how_many_items) + { + d_detail->produce(which_output, how_many_items); + } + + int + block::fixed_rate_ninput_to_noutput(int ninput) + { + throw std::runtime_error("Unimplemented"); + } + + int + block::fixed_rate_noutput_to_ninput(int noutput) + { + throw std::runtime_error("Unimplemented"); + } + + uint64_t + block::nitems_read(unsigned int which_input) + { + if(d_detail) { + return d_detail->nitems_read(which_input); + } + else { + //throw std::runtime_error("No block_detail associated with block yet"); + return 0; + } + } + + uint64_t + block::nitems_written(unsigned int which_output) + { + if(d_detail) { + return d_detail->nitems_written(which_output); + } + else { + //throw std::runtime_error("No block_detail associated with block yet"); + return 0; + } + } + + void + block::add_item_tag(unsigned int which_output, + const tag_t &tag) + { + d_detail->add_item_tag(which_output, tag); + } + + void + block::remove_item_tag(unsigned int which_input, + const tag_t &tag) + { + d_detail->remove_item_tag(which_input, tag); + } + + void + block::get_tags_in_range(std::vector<tag_t> &v, + unsigned int which_output, + uint64_t start, uint64_t end) + { + d_detail->get_tags_in_range(v, which_output, start, end); + } + + void + block::get_tags_in_range(std::vector<tag_t> &v, + unsigned int which_output, + uint64_t start, uint64_t end, + const pmt::pmt_t &key) + { + d_detail->get_tags_in_range(v, which_output, start, end, key); + } + + block::tag_propagation_policy_t + block::tag_propagation_policy() + { + return d_tag_propagation_policy; + } + + void + block::set_tag_propagation_policy(tag_propagation_policy_t p) + { + d_tag_propagation_policy = p; + } + + int + block::max_noutput_items() + { + return d_max_noutput_items; + } + + void + block::set_max_noutput_items(int m) + { + if(m <= 0) + throw std::runtime_error("block::set_max_noutput_items: value for max_noutput_items must be greater than 0.\n"); + + d_max_noutput_items = m; + d_max_noutput_items_set = true; + } + + void + block::unset_max_noutput_items() + { + d_max_noutput_items_set = false; + } + + bool + block::is_set_max_noutput_items() + { + return d_max_noutput_items_set; + } + + void + block::set_processor_affinity(const std::vector<int> &mask) + { + d_affinity = mask; + if(d_detail) { + d_detail->set_processor_affinity(d_affinity); + } + } + + void + block::unset_processor_affinity() + { + d_affinity.clear(); + if(d_detail) { + d_detail->unset_processor_affinity(); + } + } + + float + block::pc_noutput_items() + { + if(d_detail) { + return d_detail->pc_noutput_items(); + } + else { + return 0; + } + } + + float + block::pc_noutput_items_avg() + { + if(d_detail) { + return d_detail->pc_noutput_items_avg(); + } + else { + return 0; + } + } + + float + block::pc_noutput_items_var() + { + if(d_detail) { + return d_detail->pc_noutput_items_var(); + } + else { + return 0; + } + } + + float + block::pc_nproduced() + { + if(d_detail) { + return d_detail->pc_nproduced(); + } + else { + return 0; + } + } + + float + block::pc_nproduced_avg() + { + if(d_detail) { + return d_detail->pc_nproduced_avg(); + } + else { + return 0; + } + } + + float + block::pc_nproduced_var() + { + if(d_detail) { + return d_detail->pc_nproduced_var(); + } + else { + return 0; + } + } + + float + block::pc_input_buffers_full(int which) + { + if(d_detail) { + return d_detail->pc_input_buffers_full(static_cast<size_t>(which)); + } + else { + return 0; + } + } + + float + block::pc_input_buffers_full_avg(int which) + { + if(d_detail) { + return d_detail->pc_input_buffers_full_avg(static_cast<size_t>(which)); + } + else { + return 0; + } + } + + float + block::pc_input_buffers_full_var(int which) + { + if(d_detail) { + return d_detail->pc_input_buffers_full_var(static_cast<size_t>(which)); + } + else { + return 0; + } + } + + std::vector<float> + block::pc_input_buffers_full() + { + if(d_detail) { + return d_detail->pc_input_buffers_full(); + } + else { + return std::vector<float>(1,0); + } + } + + std::vector<float> + block::pc_input_buffers_full_avg() + { + if(d_detail) { + return d_detail->pc_input_buffers_full_avg(); + } + else { + return std::vector<float>(1,0); + } + } + + std::vector<float> + block::pc_input_buffers_full_var() + { + if(d_detail) { + return d_detail->pc_input_buffers_full_var(); + } + else { + return std::vector<float>(1,0); + } + } + + float + block::pc_output_buffers_full(int which) + { + if(d_detail) { + return d_detail->pc_output_buffers_full(static_cast<size_t>(which)); + } + else { + return 0; + } + } + + float + block::pc_output_buffers_full_avg(int which) + { + if(d_detail) { + return d_detail->pc_output_buffers_full_avg(static_cast<size_t>(which)); + } + else { + return 0; + } + } + + float + block::pc_output_buffers_full_var(int which) + { + if(d_detail) { + return d_detail->pc_output_buffers_full_var(static_cast<size_t>(which)); + } + else { + return 0; + } + } + + std::vector<float> + block::pc_output_buffers_full() + { + if(d_detail) { + return d_detail->pc_output_buffers_full(); + } + else { + return std::vector<float>(1,0); + } + } + + std::vector<float> + block::pc_output_buffers_full_avg() + { + if(d_detail) { + return d_detail->pc_output_buffers_full_avg(); + } + else { + return std::vector<float>(1,0); + } + } + + std::vector<float> + block::pc_output_buffers_full_var() + { + if(d_detail) { + return d_detail->pc_output_buffers_full_var(); + } + else { + return std::vector<float>(1,0); + } + } + + float + block::pc_work_time() + { + if(d_detail) { + return d_detail->pc_work_time(); + } + else { + return 0; + } + } + + float + block::pc_work_time_avg() + { + if(d_detail) { + return d_detail->pc_work_time_avg(); + } + else { + return 0; + } + } + + float + block::pc_work_time_var() + { + if(d_detail) { + return d_detail->pc_work_time_var(); + } + else { + return 0; + } + } + + void + block::reset_perf_counters() + { + if(d_detail) { + d_detail->reset_perf_counters(); + } + } + + void + block::setup_pc_rpc() + { + d_pc_rpc_set = true; +#ifdef GR_CTRLPORT + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<block, float>( + alias(), "noutput_items", &block::pc_noutput_items, + pmt::mp(0), pmt::mp(32768), pmt::mp(0), + "", "noutput items", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP))); + + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<block, float>( + alias(), "avg noutput_items", &block::pc_noutput_items_avg, + pmt::mp(0), pmt::mp(32768), pmt::mp(0), + "", "Average noutput items", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP))); + + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<block, float>( + alias(), "var noutput_items", &block::pc_noutput_items_var, + pmt::mp(0), pmt::mp(32768), pmt::mp(0), + "", "Var. noutput items", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP))); + + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<block, float>( + alias(), "nproduced", &block::pc_nproduced, + pmt::mp(0), pmt::mp(32768), pmt::mp(0), + "", "items produced", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP))); + + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<block, float>( + alias(), "avg nproduced", &block::pc_nproduced_avg, + pmt::mp(0), pmt::mp(32768), pmt::mp(0), + "", "Average items produced", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP))); + + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<block, float>( + alias(), "var nproduced", &block::pc_nproduced_var, + pmt::mp(0), pmt::mp(32768), pmt::mp(0), + "", "Var. items produced", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP))); + + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<block, float>( + alias(), "work time", &block::pc_work_time, + pmt::mp(0), pmt::mp(1e9), pmt::mp(0), + "", "clock cycles in call to work", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP))); + + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<block, float>( + alias(), "avg work time", &block::pc_work_time_avg, + pmt::mp(0), pmt::mp(1e9), pmt::mp(0), + "", "Average clock cycles in call to work", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP))); + + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<block, float>( + alias(), "var work time", &block::pc_work_time_var, + pmt::mp(0), pmt::mp(1e9), pmt::mp(0), + "", "Var. clock cycles in call to work", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP))); + + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<block, std::vector<float> >( + alias(), "input \% full", &block::pc_input_buffers_full, + pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0), + "", "how full input buffers are", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP))); + + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<block, std::vector<float> >( + alias(), "avg input \% full", &block::pc_input_buffers_full_avg, + pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0), + "", "Average of how full input buffers are", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP))); + + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<block, std::vector<float> >( + alias(), "var input \% full", &block::pc_input_buffers_full_var, + pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0), + "", "Var. of how full input buffers are", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP))); + + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<block, std::vector<float> >( + alias(), "output \% full", &block::pc_output_buffers_full, + pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0), + "", "how full output buffers are", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP))); + + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<block, std::vector<float> >( + alias(), "avg output \% full", &block::pc_output_buffers_full_avg, + pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0), + "", "Average of how full output buffers are", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP))); + + d_rpc_vars.push_back( + rpcbasic_sptr(new rpcbasic_register_get<block, std::vector<float> >( + alias(), "var output \% full", &block::pc_output_buffers_full_var, + pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0), + "", "Var. of how full output buffers are", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTSTRIP))); +#endif /* GR_CTRLPORT */ + } + + std::ostream& + operator << (std::ostream& os, const block *m) + { + os << "<block " << m->name() << " (" << m->unique_id() << ")>"; + return os; + } + + int + block::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + throw std::runtime_error("block::general_work() not implemented"); + return 0; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/block_detail.cc b/gnuradio-runtime/lib/block_detail.cc new file mode 100644 index 0000000000..a3ab4b3f7b --- /dev/null +++ b/gnuradio-runtime/lib/block_detail.cc @@ -0,0 +1,474 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2009,2010,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/block_detail.h> +#include <gnuradio/buffer.h> +#include <iostream> + +namespace gr { + + static long s_ncurrently_allocated = 0; + + long + block_detail_ncurrently_allocated() + { + return s_ncurrently_allocated; + } + + block_detail::block_detail(unsigned int ninputs, unsigned int noutputs) + : d_produce_or(0), + d_ninputs(ninputs), d_noutputs(noutputs), + d_input(ninputs), d_output(noutputs), + d_done(false), + d_ins_noutput_items(0), + d_avg_noutput_items(0), + d_var_noutput_items(0), + d_ins_nproduced(0), + d_avg_nproduced(0), + d_var_nproduced(0), + d_ins_input_buffers_full(ninputs, 0), + d_avg_input_buffers_full(ninputs, 0), + d_var_input_buffers_full(ninputs, 0), + d_ins_output_buffers_full(noutputs, 0), + d_avg_output_buffers_full(noutputs, 0), + d_var_output_buffers_full(noutputs, 0), + d_ins_work_time(0), + d_avg_work_time(0), + d_var_work_time(0), + d_pc_counter(0) + { + s_ncurrently_allocated++; + } + + block_detail::~block_detail() + { + // should take care of itself + s_ncurrently_allocated--; + } + + void + block_detail::set_input(unsigned int which, buffer_reader_sptr reader) + { + if(which >= d_ninputs) + throw std::invalid_argument("block_detail::set_input"); + + d_input[which] = reader; + } + + void + block_detail::set_output(unsigned int which, buffer_sptr buffer) + { + if(which >= d_noutputs) + throw std::invalid_argument("block_detail::set_output"); + + d_output[which] = buffer; + } + + block_detail_sptr + make_block_detail(unsigned int ninputs, unsigned int noutputs) + { + return block_detail_sptr (new block_detail(ninputs, noutputs)); + } + + void + block_detail::set_done(bool done) + { + d_done = done; + for(unsigned int i = 0; i < d_noutputs; i++) + d_output[i]->set_done(done); + + for(unsigned int i = 0; i < d_ninputs; i++) + d_input[i]->set_done(done); + } + + void + block_detail::consume(int which_input, int how_many_items) + { + if(how_many_items > 0) { + input(which_input)->update_read_pointer(how_many_items); + } + } + + void + block_detail::consume_each(int how_many_items) + { + if(how_many_items > 0) { + for(int i = 0; i < ninputs (); i++) { + d_input[i]->update_read_pointer(how_many_items); + } + } + } + + void + block_detail::produce(int which_output, int how_many_items) + { + if(how_many_items > 0) { + d_output[which_output]->update_write_pointer(how_many_items); + d_produce_or |= how_many_items; + } + } + + void + block_detail::produce_each(int how_many_items) + { + if(how_many_items > 0) { + for(int i = 0; i < noutputs (); i++) { + d_output[i]->update_write_pointer (how_many_items); + } + d_produce_or |= how_many_items; + } + } + + uint64_t + block_detail::nitems_read(unsigned int which_input) + { + if(which_input >= d_ninputs) + throw std::invalid_argument ("block_detail::n_input_items"); + return d_input[which_input]->nitems_read(); + } + + uint64_t + block_detail::nitems_written(unsigned int which_output) + { + if(which_output >= d_noutputs) + throw std::invalid_argument ("block_detail::n_output_items"); + return d_output[which_output]->nitems_written(); + } + + void + block_detail::add_item_tag(unsigned int which_output, const tag_t &tag) + { + if(!pmt::is_symbol(tag.key)) { + throw pmt::wrong_type("block_detail::add_item_tag key", tag.key); + } + else { + // Add tag to gr_buffer's deque tags + d_output[which_output]->add_item_tag(tag); + } + } + + void + block_detail::remove_item_tag(unsigned int which_input, const tag_t &tag) + { + if(!pmt::is_symbol(tag.key)) { + throw pmt::wrong_type("block_detail::add_item_tag key", tag.key); + } + else { + // Add tag to gr_buffer's deque tags + d_input[which_input]->buffer()->remove_item_tag(tag); + } + } + + void + block_detail::get_tags_in_range(std::vector<tag_t> &v, + unsigned int which_input, + uint64_t abs_start, + uint64_t abs_end) + { + // get from gr_buffer_reader's deque of tags + d_input[which_input]->get_tags_in_range(v, abs_start, abs_end); + } + + void + block_detail::get_tags_in_range(std::vector<tag_t> &v, + unsigned int which_input, + uint64_t abs_start, + uint64_t abs_end, + const pmt::pmt_t &key) + { + std::vector<tag_t> found_items; + + v.resize(0); + + // get from gr_buffer_reader's deque of tags + d_input[which_input]->get_tags_in_range(found_items, abs_start, abs_end); + + // Filter further by key name + pmt::pmt_t itemkey; + std::vector<tag_t>::iterator itr; + for(itr = found_items.begin(); itr != found_items.end(); itr++) { + itemkey = (*itr).key; + if(pmt::eqv(key, itemkey)) { + v.push_back(*itr); + } + } + } + + void + block_detail::set_processor_affinity(const std::vector<int> &mask) + { + if(threaded) { + try { + gr::thread::thread_bind_to_processor(thread, mask); + } + catch (std::runtime_error e) { + std::cerr << "set_processor_affinity: invalid mask." << std::endl;; + } + } + } + + void + block_detail::unset_processor_affinity() + { + if(threaded) { + gr::thread::thread_unbind(thread); + } + } + + void + block_detail::start_perf_counters() + { + d_start_of_work = gr::high_res_timer_now(); + } + + void + block_detail::stop_perf_counters(int noutput_items, int nproduced) + { + d_end_of_work = gr::high_res_timer_now(); + gr::high_res_timer_type diff = d_end_of_work - d_start_of_work; + + if(d_pc_counter == 0) { + d_ins_work_time = diff; + d_avg_work_time = diff; + d_var_work_time = 0; + d_ins_nproduced = nproduced; + d_avg_nproduced = nproduced; + d_var_nproduced = 0; + d_ins_noutput_items = noutput_items; + d_avg_noutput_items = noutput_items; + d_var_noutput_items = 0; + for(size_t i=0; i < d_input.size(); i++) { + float pfull = static_cast<float>(d_input[i]->items_available()) / + static_cast<float>(d_input[i]->max_possible_items_available()); + d_ins_input_buffers_full[i] = pfull; + d_avg_input_buffers_full[i] = pfull; + d_var_input_buffers_full[i] = 0; + } + for(size_t i=0; i < d_output.size(); i++) { + float pfull = 1.0f - static_cast<float>(d_output[i]->space_available()) / + static_cast<float>(d_output[i]->bufsize()); + d_ins_output_buffers_full[i] = pfull; + d_avg_output_buffers_full[i] = pfull; + d_var_output_buffers_full[i] = 0; + } + } + else { + float d = diff - d_avg_work_time; + d_ins_work_time = diff; + d_avg_work_time = d_avg_work_time + d/d_pc_counter; + d_var_work_time = d_var_work_time + d*d; + + d = nproduced - d_avg_nproduced; + d_ins_nproduced = nproduced; + d_avg_nproduced = d_avg_nproduced + d/d_pc_counter; + d_var_nproduced = d_var_nproduced + d*d; + + d = noutput_items - d_avg_noutput_items; + d_ins_noutput_items = noutput_items; + d_avg_noutput_items = d_avg_noutput_items + d/d_pc_counter; + d_var_noutput_items = d_var_noutput_items + d*d; + + for(size_t i=0; i < d_input.size(); i++) { + float pfull = static_cast<float>(d_input[i]->items_available()) / + static_cast<float>(d_input[i]->max_possible_items_available()); + + d = pfull - d_avg_input_buffers_full[i]; + d_ins_input_buffers_full[i] = pfull; + d_avg_input_buffers_full[i] = d_avg_input_buffers_full[i] + d/d_pc_counter; + d_var_input_buffers_full[i] = d_var_input_buffers_full[i] + d*d; + } + + for(size_t i=0; i < d_output.size(); i++) { + float pfull = 1.0f - static_cast<float>(d_output[i]->space_available()) / + static_cast<float>(d_output[i]->bufsize()); + + d = pfull - d_avg_output_buffers_full[i]; + d_ins_output_buffers_full[i] = pfull; + d_avg_output_buffers_full[i] = d_avg_output_buffers_full[i] + d/d_pc_counter; + d_var_output_buffers_full[i] = d_var_output_buffers_full[i] + d*d; + } + } + + d_pc_counter++; + } + + void + block_detail::reset_perf_counters() + { + d_pc_counter = 0; + } + + float + block_detail::pc_noutput_items() + { + return d_ins_noutput_items; + } + + float + block_detail::pc_nproduced() + { + return d_ins_nproduced; + } + + float + block_detail::pc_input_buffers_full(size_t which) + { + if(which < d_ins_input_buffers_full.size()) + return d_ins_input_buffers_full[which]; + else + return 0; + } + + std::vector<float> + block_detail::pc_input_buffers_full() + { + return d_ins_input_buffers_full; + } + + float + block_detail::pc_output_buffers_full(size_t which) + { + if(which < d_ins_output_buffers_full.size()) + return d_ins_output_buffers_full[which]; + else + return 0; + } + + std::vector<float> + block_detail::pc_output_buffers_full() + { + return d_ins_output_buffers_full; + } + + float + block_detail::pc_work_time() + { + return d_ins_work_time; + } + + float + block_detail::pc_noutput_items_avg() + { + return d_avg_noutput_items; + } + + float + block_detail::pc_nproduced_avg() + { + return d_avg_nproduced; + } + + float + block_detail::pc_input_buffers_full_avg(size_t which) + { + if(which < d_avg_input_buffers_full.size()) + return d_avg_input_buffers_full[which]; + else + return 0; + } + + std::vector<float> + block_detail::pc_input_buffers_full_avg() + { + return d_avg_input_buffers_full; + } + + float + block_detail::pc_output_buffers_full_avg(size_t which) + { + if(which < d_avg_output_buffers_full.size()) + return d_avg_output_buffers_full[which]; + else + return 0; + } + + std::vector<float> + block_detail::pc_output_buffers_full_avg() + { + return d_avg_output_buffers_full; + } + + float + block_detail::pc_work_time_avg() + { + return d_avg_work_time; + } + + float + block_detail::pc_noutput_items_var() + { + return d_var_noutput_items/(d_pc_counter-1); + } + + float + block_detail::pc_nproduced_var() + { + return d_var_nproduced/(d_pc_counter-1); + } + + float + block_detail::pc_input_buffers_full_var(size_t which) + { + if(which < d_avg_input_buffers_full.size()) + return d_var_input_buffers_full[which]/(d_pc_counter-1); + else + return 0; + } + + std::vector<float> + block_detail::pc_input_buffers_full_var() + { + std::vector<float> var(d_avg_input_buffers_full.size(), 0); + for(size_t i = 0; i < d_avg_input_buffers_full.size(); i++) + var[i] = d_avg_input_buffers_full[i]/(d_pc_counter-1); + return var; + } + + float + block_detail::pc_output_buffers_full_var(size_t which) + { + if(which < d_avg_output_buffers_full.size()) + return d_var_output_buffers_full[which]/(d_pc_counter-1); + else + return 0; + } + + std::vector<float> + block_detail::pc_output_buffers_full_var() + { + std::vector<float> var(d_avg_output_buffers_full.size(), 0); + for(size_t i = 0; i < d_avg_output_buffers_full.size(); i++) + var[i] = d_avg_output_buffers_full[i]/(d_pc_counter-1); + return var; + } + + float + block_detail::pc_work_time_var() + { + return d_var_work_time/(d_pc_counter-1); + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/block_executor.cc b/gnuradio-runtime/lib/block_executor.cc new file mode 100644 index 0000000000..8059ea2d5a --- /dev/null +++ b/gnuradio-runtime/lib/block_executor.cc @@ -0,0 +1,489 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2008-2010,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <block_executor.h> +#include <gnuradio/block.h> +#include <gnuradio/block_detail.h> +#include <gnuradio/buffer.h> +#include <gnuradio/prefs.h> +#include <boost/thread.hpp> +#include <boost/format.hpp> +#include <iostream> +#include <limits> +#include <assert.h> +#include <stdio.h> + +namespace gr { + +// must be defined to either 0 or 1 +#define ENABLE_LOGGING 0 + +#if (ENABLE_LOGGING) +#define LOG(x) do { x; } while(0) +#else +#define LOG(x) do {;} while(0) +#endif + + static int which_scheduler = 0; + + inline static unsigned int + round_up(unsigned int n, unsigned int multiple) + { + return ((n + multiple - 1) / multiple) * multiple; + } + + inline static unsigned int + round_down(unsigned int n, unsigned int multiple) + { + return (n / multiple) * multiple; + } + + // + // Return minimum available write space in all our downstream + // buffers or -1 if we're output blocked and the output we're + // blocked on is done. + // + static int + min_available_space(block_detail *d, int output_multiple, int min_noutput_items) + { + int min_space = std::numeric_limits<int>::max(); + if(min_noutput_items == 0) + min_noutput_items = 1; + for(int i = 0; i < d->noutputs (); i++) { + gr::thread::scoped_lock guard(*d->output(i)->mutex()); + int avail_n = round_down(d->output(i)->space_available(), output_multiple); + int best_n = round_down(d->output(i)->bufsize()/2, output_multiple); + if(best_n < min_noutput_items) + throw std::runtime_error("Buffer too small for min_noutput_items"); + int n = std::min(avail_n, best_n); + if(n < min_noutput_items){ // We're blocked on output. + if(d->output(i)->done()){ // Downstream is done, therefore we're done. + return -1; + } + return 0; + } + min_space = std::min(min_space, n); + } + return min_space; + } + + static bool + propagate_tags(block::tag_propagation_policy_t policy, block_detail *d, + const std::vector<uint64_t> &start_nitems_read, double rrate, + std::vector<tag_t> &rtags) + { + // Move tags downstream + // if a sink, we don't need to move downstream + if(d->sink_p()) { + return true; + } + + switch(policy) { + case block::TPP_DONT: + return true; + break; + case block::TPP_ALL_TO_ALL: + // every tag on every input propogates to everyone downstream + for(int i = 0; i < d->ninputs(); i++) { + d->get_tags_in_range(rtags, i, start_nitems_read[i], + d->nitems_read(i)); + + std::vector<tag_t>::iterator t; + if(rrate == 1.0) { + for(t = rtags.begin(); t != rtags.end(); t++) { + for(int o = 0; o < d->noutputs(); o++) + d->output(o)->add_item_tag(*t); + } + } + else { + for(t = rtags.begin(); t != rtags.end(); t++) { + tag_t new_tag = *t; + new_tag.offset *= rrate; + for(int o = 0; o < d->noutputs(); o++) + d->output(o)->add_item_tag(new_tag); + } + } + } + break; + case block::TPP_ONE_TO_ONE: + // tags from input i only go to output i + // this requires d->ninputs() == d->noutputs; this is checked when this + // type of tag-propagation system is selected in block_detail + if(d->ninputs() == d->noutputs()) { + for(int i = 0; i < d->ninputs(); i++) { + d->get_tags_in_range(rtags, i, start_nitems_read[i], + d->nitems_read(i)); + + std::vector<tag_t>::iterator t; + for(t = rtags.begin(); t != rtags.end(); t++) { + tag_t new_tag = *t; + new_tag.offset *= rrate; + d->output(i)->add_item_tag(new_tag); + } + } + } + else { + std::cerr << "Error: block_executor: propagation_policy 'ONE-TO-ONE' requires ninputs == noutputs" << std::endl; + return false; + } + + break; + default: + return true; + } + return true; + } + + block_executor::block_executor(block_sptr block, int max_noutput_items) + : d_block(block), d_log(0), d_max_noutput_items(max_noutput_items) + { + if(ENABLE_LOGGING) { + std::string name = str(boost::format("sst-%03d.log") % which_scheduler++); + d_log = new std::ofstream(name.c_str()); + std::unitbuf(*d_log); // make it unbuffered... + *d_log << "block_executor: " + << d_block << std::endl; + } + +#ifdef GR_PERFORMANCE_COUNTERS + prefs *prefs = prefs::singleton(); + d_use_pc = prefs->get_bool("PerfCounters", "on", false); +#endif /* GR_PERFORMANCE_COUNTERS */ + + d_block->start(); // enable any drivers, etc. + } + + block_executor::~block_executor() + { + if(ENABLE_LOGGING) + delete d_log; + + d_block->stop(); // stop any drivers, etc. + } + + block_executor::state + block_executor::run_one_iteration() + { + int noutput_items; + int max_items_avail; + int max_noutput_items = d_max_noutput_items; + int new_alignment = 0; + int alignment_state = -1; + + block *m = d_block.get(); + block_detail *d = m->detail().get(); + + LOG(*d_log << std::endl << m); + + if(d->done()){ + assert(0); + return DONE; + } + + if(d->source_p ()) { + d_ninput_items_required.resize(0); + d_ninput_items.resize(0); + d_input_items.resize(0); + d_input_done.resize(0); + d_output_items.resize(d->noutputs()); + d_start_nitems_read.resize(0); + + // determine the minimum available output space + noutput_items = min_available_space(d, m->output_multiple (), m->min_noutput_items ()); + noutput_items = std::min(noutput_items, max_noutput_items); + LOG(*d_log << " source\n noutput_items = " << noutput_items << std::endl); + if(noutput_items == -1) // we're done + goto were_done; + + if(noutput_items == 0){ // we're output blocked + LOG(*d_log << " BLKD_OUT\n"); + return BLKD_OUT; + } + + goto setup_call_to_work; // jump to common code + } + + else if(d->sink_p ()) { + d_ninput_items_required.resize(d->ninputs ()); + d_ninput_items.resize(d->ninputs ()); + d_input_items.resize(d->ninputs ()); + d_input_done.resize(d->ninputs()); + d_output_items.resize (0); + d_start_nitems_read.resize(d->ninputs()); + LOG(*d_log << " sink\n"); + + max_items_avail = 0; + for(int i = 0; i < d->ninputs (); i++) { + { + /* + * Acquire the mutex and grab local copies of items_available and done. + */ + gr::thread::scoped_lock guard(*d->input(i)->mutex()); + d_ninput_items[i] = d->input(i)->items_available(); + d_input_done[i] = d->input(i)->done(); + } + + LOG(*d_log << " d_ninput_items[" << i << "] = " << d_ninput_items[i] << std::endl); + LOG(*d_log << " d_input_done[" << i << "] = " << d_input_done[i] << std::endl); + + if (d_ninput_items[i] < m->output_multiple() && d_input_done[i]) + goto were_done; + + max_items_avail = std::max (max_items_avail, d_ninput_items[i]); + } + + // take a swag at how much output we can sink + noutput_items = (int)(max_items_avail * m->relative_rate ()); + noutput_items = round_down(noutput_items, m->output_multiple ()); + noutput_items = std::min(noutput_items, max_noutput_items); + LOG(*d_log << " max_items_avail = " << max_items_avail << std::endl); + LOG(*d_log << " noutput_items = " << noutput_items << std::endl); + + if(noutput_items == 0) { // we're blocked on input + LOG(*d_log << " BLKD_IN\n"); + return BLKD_IN; + } + + goto try_again; // Jump to code shared with regular case. + } + + else { + // do the regular thing + d_ninput_items_required.resize (d->ninputs ()); + d_ninput_items.resize (d->ninputs ()); + d_input_items.resize (d->ninputs ()); + d_input_done.resize(d->ninputs()); + d_output_items.resize (d->noutputs ()); + d_start_nitems_read.resize(d->ninputs()); + + max_items_avail = 0; + for(int i = 0; i < d->ninputs (); i++) { + { + /* + * Acquire the mutex and grab local copies of items_available and done. + */ + gr::thread::scoped_lock guard(*d->input(i)->mutex()); + d_ninput_items[i] = d->input(i)->items_available (); + d_input_done[i] = d->input(i)->done(); + } + max_items_avail = std::max(max_items_avail, d_ninput_items[i]); + } + + // determine the minimum available output space + noutput_items = min_available_space(d, m->output_multiple(), m->min_noutput_items()); + if(ENABLE_LOGGING) { + *d_log << " regular "; + if(m->relative_rate() >= 1.0) + *d_log << "1:" << m->relative_rate() << std::endl; + else + *d_log << 1.0/m->relative_rate() << ":1\n"; + *d_log << " max_items_avail = " << max_items_avail << std::endl; + *d_log << " noutput_items = " << noutput_items << std::endl; + } + if(noutput_items == -1) // we're done + goto were_done; + + if(noutput_items == 0) { // we're output blocked + LOG(*d_log << " BLKD_OUT\n"); + return BLKD_OUT; + } + + try_again: + if(m->fixed_rate()) { + // try to work it forward starting with max_items_avail. + // We want to try to consume all the input we've got. + int reqd_noutput_items = m->fixed_rate_ninput_to_noutput(max_items_avail); + + // only test this if we specifically set the output_multiple + if(m->output_multiple_set()) + reqd_noutput_items = round_down(reqd_noutput_items, m->output_multiple()); + + if(reqd_noutput_items > 0 && reqd_noutput_items <= noutput_items) + noutput_items = reqd_noutput_items; + + // if we need this many outputs, overrule the max_noutput_items setting + max_noutput_items = std::max(m->output_multiple(), max_noutput_items); + } + noutput_items = std::min(noutput_items, max_noutput_items); + + // Check if we're still unaligned; use up items until we're + // aligned again. Otherwise, make sure we set the alignment + // requirement. + if(!m->output_multiple_set()) { + if(m->is_unaligned()) { + // When unaligned, don't just set noutput_items to the remaining + // samples to meet alignment; this causes too much overhead in + // requiring a premature call back here. Set the maximum amount + // of samples to handle unalignment and get us back aligned. + if(noutput_items >= m->unaligned()) { + noutput_items = round_up(noutput_items, m->alignment()) \ + - (m->alignment() - m->unaligned()); + new_alignment = 0; + } + else { + new_alignment = m->unaligned() - noutput_items; + } + alignment_state = 0; + } + else if(noutput_items < m->alignment()) { + // if we don't have enough for an aligned call, keep track of + // misalignment, set unaligned flag, and proceed. + new_alignment = m->alignment() - noutput_items; + m->set_unaligned(new_alignment); + m->set_is_unaligned(true); + alignment_state = 1; + } + else { + // enough to round down to the nearest alignment and process. + noutput_items = round_down(noutput_items, m->alignment()); + m->set_is_unaligned(false); + alignment_state = 2; + } + } + + // ask the block how much input they need to produce noutput_items + m->forecast (noutput_items, d_ninput_items_required); + + // See if we've got sufficient input available + int i; + for(i = 0; i < d->ninputs (); i++) + if(d_ninput_items_required[i] > d_ninput_items[i]) // not enough + break; + + if(i < d->ninputs()) { // not enough input on input[i] + // if we can, try reducing the size of our output request + if(noutput_items > m->output_multiple()) { + noutput_items /= 2; + noutput_items = round_up(noutput_items, m->output_multiple()); + goto try_again; + } + + // We're blocked on input + LOG(*d_log << " BLKD_IN\n"); + if(d_input_done[i]) // If the upstream block is done, we're done + goto were_done; + + // Is it possible to ever fulfill this request? + if(d_ninput_items_required[i] > d->input(i)->max_possible_items_available()) { + // Nope, never going to happen... + std::cerr << "\nsched: <block " << m->name() + << " (" << m->unique_id() << ")>" + << " is requesting more input data\n" + << " than we can provide.\n" + << " ninput_items_required = " + << d_ninput_items_required[i] << "\n" + << " max_possible_items_available = " + << d->input(i)->max_possible_items_available() << "\n" + << " If this is a filter, consider reducing the number of taps.\n"; + goto were_done; + } + + // If we were made unaligned in this round but return here without + // processing; reset the unalignment claim before next entry. + if(alignment_state == 1) { + m->set_unaligned(0); + m->set_is_unaligned(false); + } + return BLKD_IN; + } + + // We've got enough data on each input to produce noutput_items. + // Finish setting up the call to work. + for(int i = 0; i < d->ninputs (); i++) + d_input_items[i] = d->input(i)->read_pointer(); + + setup_call_to_work: + + d->d_produce_or = 0; + for(int i = 0; i < d->noutputs (); i++) + d_output_items[i] = d->output(i)->write_pointer(); + + // determine where to start looking for new tags + for(int i = 0; i < d->ninputs(); i++) + d_start_nitems_read[i] = d->nitems_read(i); + +#ifdef GR_PERFORMANCE_COUNTERS + if(d_use_pc) + d->start_perf_counters(); +#endif /* GR_PERFORMANCE_COUNTERS */ + + // Do the actual work of the block + int n = m->general_work(noutput_items, d_ninput_items, + d_input_items, d_output_items); + +#ifdef GR_PERFORMANCE_COUNTERS + if(d_use_pc) + d->stop_perf_counters(noutput_items, n); +#endif /* GR_PERFORMANCE_COUNTERS */ + + LOG(*d_log << " general_work: noutput_items = " << noutput_items + << " result = " << n << std::endl); + + // Adjust number of unaligned items left to process + if(m->is_unaligned()) { + m->set_unaligned(new_alignment); + m->set_is_unaligned(m->unaligned() != 0); + } + + if(!propagate_tags(m->tag_propagation_policy(), d, + d_start_nitems_read, m->relative_rate(), + d_returned_tags)) + goto were_done; + + if(n == block::WORK_DONE) + goto were_done; + + if(n != block::WORK_CALLED_PRODUCE) + d->produce_each (n); // advance write pointers + + if(d->d_produce_or > 0) // block produced something + return READY; + + // We didn't produce any output even though we called general_work. + // We have (most likely) consumed some input. + + /* + // If this is a source, it's broken. + if(d->source_p()) { + std::cerr << "block_executor: source " << m + << " produced no output. We're marking it DONE.\n"; + // FIXME maybe we ought to raise an exception... + goto were_done; + } + */ + + // Have the caller try again... + return READY_NO_OUTPUT; + } + assert(0); + + were_done: + LOG(*d_log << " were_done\n"); + d->set_done (true); + return DONE; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/block_executor.h b/gnuradio-runtime/lib/block_executor.h new file mode 100644 index 0000000000..4e1d2f1602 --- /dev/null +++ b/gnuradio-runtime/lib/block_executor.h @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2008,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_RUNTIME_BLOCK_EXECUTOR_H +#define INCLUDED_GR_RUNTIME_BLOCK_EXECUTOR_H + +#include <gnuradio/api.h> +#include <gnuradio/runtime_types.h> +#include <gnuradio/tags.h> +#include <fstream> + +namespace gr { + + /*! + * \brief Manage the execution of a single block. + * \ingroup internal + */ + class GR_RUNTIME_API block_executor + { + protected: + block_sptr d_block; // The block we're trying to run + std::ofstream *d_log; + + // These are allocated here so we don't have to on each iteration + + gr_vector_int d_ninput_items_required; + gr_vector_int d_ninput_items; + gr_vector_const_void_star d_input_items; + std::vector<bool> d_input_done; + gr_vector_void_star d_output_items; + std::vector<uint64_t> d_start_nitems_read; //stores where tag counts are before work + std::vector<tag_t> d_returned_tags; + int d_max_noutput_items; + +#ifdef GR_PERFORMANCE_COUNTERS + bool d_use_pc; +#endif /* GR_PERFORMANCE_COUNTERS */ + + public: + block_executor(block_sptr block, int max_noutput_items=100000); + ~block_executor(); + + enum state { + READY, // We made progress; everything's cool. + READY_NO_OUTPUT, // We consumed some input, but produced no output. + BLKD_IN, // no progress; we're blocked waiting for input data. + BLKD_OUT, // no progress; we're blocked waiting for output buffer space. + DONE, // we're done; don't call me again. + }; + + /* + * \brief Run one iteration. + */ + state run_one_iteration(); + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_RUNTIME_BLOCK_EXECUTOR_H */ diff --git a/gnuradio-runtime/lib/block_gateway_impl.cc b/gnuradio-runtime/lib/block_gateway_impl.cc new file mode 100644 index 0000000000..13f4326d7e --- /dev/null +++ b/gnuradio-runtime/lib/block_gateway_impl.cc @@ -0,0 +1,186 @@ +/* + * Copyright 2011-2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "block_gateway_impl.h" +#include <gnuradio/io_signature.h> +#include <iostream> +#include <boost/bind.hpp> + +namespace gr { + + /*********************************************************************** + * Helper routines + **********************************************************************/ + template <typename OutType, typename InType> + void + copy_pointers(OutType &out, const InType &in) + { + out.resize(in.size()); + for(size_t i = 0; i < in.size(); i++) { + out[i] = (void *)(in[i]); + } + } + + + block_gateway::sptr + block_gateway::make(feval_ll *handler, + const std::string &name, + gr::io_signature::sptr in_sig, + gr::io_signature::sptr out_sig, + const block_gw_work_type work_type, + const unsigned factor) + { + return block_gateway::sptr + (new block_gateway_impl(handler, name, in_sig, out_sig, + work_type, factor)); + } + + block_gateway_impl::block_gateway_impl(feval_ll *handler, + const std::string &name, + gr::io_signature::sptr in_sig, + gr::io_signature::sptr out_sig, + const block_gw_work_type work_type, + const unsigned factor) + : block(name, in_sig, out_sig), + _handler(handler), + _work_type(work_type) + { + switch(_work_type) { + case GR_BLOCK_GW_WORK_GENERAL: + _decim = 1; //not relevant, but set anyway + _interp = 1; //not relevant, but set anyway + break; + + case GR_BLOCK_GW_WORK_SYNC: + _decim = 1; + _interp = 1; + this->set_fixed_rate(true); + break; + + case GR_BLOCK_GW_WORK_DECIM: + _decim = factor; + _interp = 1; + break; + + case GR_BLOCK_GW_WORK_INTERP: + _decim = 1; + _interp = factor; + this->set_output_multiple(_interp); + break; + } + } + + void + block_gateway_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) + { + switch(_work_type) { + case GR_BLOCK_GW_WORK_GENERAL: + _message.action = block_gw_message_type::ACTION_FORECAST; + _message.forecast_args_noutput_items = noutput_items; + _message.forecast_args_ninput_items_required = ninput_items_required; + _handler->calleval(0); + ninput_items_required = _message.forecast_args_ninput_items_required; + return; + + default: + unsigned ninputs = ninput_items_required.size(); + for(unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items); + return; + } + } + + int + block_gateway_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + switch(_work_type) { + case GR_BLOCK_GW_WORK_GENERAL: + _message.action = block_gw_message_type::ACTION_GENERAL_WORK; + _message.general_work_args_noutput_items = noutput_items; + _message.general_work_args_ninput_items = ninput_items; + copy_pointers(_message.general_work_args_input_items, input_items); + _message.general_work_args_output_items = output_items; + _handler->calleval(0); + return _message.general_work_args_return_value; + + default: + int r = work (noutput_items, input_items, output_items); + if(r > 0) + consume_each(r*_decim/_interp); + return r; + } + } + + int + block_gateway_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + _message.action = block_gw_message_type::ACTION_WORK; + _message.work_args_ninput_items = fixed_rate_noutput_to_ninput(noutput_items); + if(_message.work_args_ninput_items == 0) + return -1; + _message.work_args_noutput_items = noutput_items; + copy_pointers(_message.work_args_input_items, input_items); + _message.work_args_output_items = output_items; + _handler->calleval(0); + return _message.work_args_return_value; + } + + int + block_gateway_impl::fixed_rate_noutput_to_ninput(int noutput_items) + { + return (noutput_items*_decim/_interp) + history() - 1; + } + + int + block_gateway_impl::fixed_rate_ninput_to_noutput(int ninput_items) + { + return std::max(0, ninput_items - (int)history() + 1)*_interp/_decim; + } + + bool + block_gateway_impl::start(void) + { + _message.action = block_gw_message_type::ACTION_START; + _handler->calleval(0); + return _message.start_args_return_value; + } + + bool + block_gateway_impl::stop(void) + { + _message.action = block_gw_message_type::ACTION_STOP; + _handler->calleval(0); + return _message.stop_args_return_value; + } + + block_gw_message_type& + block_gateway_impl::block_message(void) + { + return _message; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/block_gateway_impl.h b/gnuradio-runtime/lib/block_gateway_impl.h new file mode 100644 index 0000000000..1707ecf1c8 --- /dev/null +++ b/gnuradio-runtime/lib/block_gateway_impl.h @@ -0,0 +1,75 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_RUNTIME_BLOCK_GATEWAY_IMPL_H +#define INCLUDED_RUNTIME_BLOCK_GATEWAY_IMPL_H + +#include <gnuradio/block_gateway.h> + +namespace gr { + + /*********************************************************************** + * The gr::block gateway implementation class + **********************************************************************/ + class block_gateway_impl : public block_gateway + { + public: + block_gateway_impl(feval_ll *handler, + const std::string &name, + gr::io_signature::sptr in_sig, + gr::io_signature::sptr out_sig, + const block_gw_work_type work_type, + const unsigned factor); + + /******************************************************************* + * Overloads for various scheduler-called functions + ******************************************************************/ + void forecast(int noutput_items, + gr_vector_int &ninput_items_required); + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + int fixed_rate_noutput_to_ninput(int noutput_items); + int fixed_rate_ninput_to_noutput(int ninput_items); + + bool start(void); + bool stop(void); + + block_gw_message_type& block_message(void); + + private: + feval_ll *_handler; + block_gw_message_type _message; + const block_gw_work_type _work_type; + unsigned _decim, _interp; + }; + +} /* namespace gr */ + +#endif /* INCLUDED_RUNTIME_BLOCK_GATEWAY_H */ diff --git a/gnuradio-runtime/lib/block_registry.cc b/gnuradio-runtime/lib/block_registry.cc new file mode 100644 index 0000000000..f17e3e4af9 --- /dev/null +++ b/gnuradio-runtime/lib/block_registry.cc @@ -0,0 +1,120 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012-2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <gnuradio/basic_block.h> +#include <gnuradio/block.h> +#include <gnuradio/block_detail.h> +#include <gnuradio/block_registry.h> +#include <gnuradio/tpb_detail.h> +#include <stdio.h> + +gr::block_registry global_block_registry; + +namespace gr { + + block_registry::block_registry() + { + d_ref_map = pmt::make_dict(); + } + + long + block_registry::block_register(basic_block* block) + { + if(d_map.find(block->name()) == d_map.end()) { + d_map[block->name()] = blocksubmap_t(); + d_map[block->name()][0] = block; + return 0; + } + else { + for(size_t i=0; i<=d_map[block->name()].size(); i++){ + if(d_map[block->name()].find(i) == d_map[block->name()].end()){ + d_map[block->name()][i] = block; + return i; + } + } + } + throw std::runtime_error("should not reach this"); + } + + void + block_registry::block_unregister(basic_block* block) + { + d_map[block->name()].erase( d_map[block->name()].find(block->symbolic_id())); + d_ref_map = pmt::dict_delete(d_ref_map, pmt::intern(block->symbol_name())); + if(block->alias_set()) { + d_ref_map = pmt::dict_delete(d_ref_map, pmt::intern(block->alias())); + } + } + + std::string + block_registry::register_symbolic_name(basic_block* block) + { + std::stringstream ss; + ss << block->name() << block->symbolic_id(); + //std::cout << "register_symbolic_name: " << ss.str() << std::endl; + register_symbolic_name(block, ss.str()); + return ss.str(); + } + + void + block_registry::register_symbolic_name(basic_block* block, std::string name) + { + if(pmt::dict_has_key(d_ref_map, pmt::intern(name))) { + throw std::runtime_error("symbol already exists, can not re-use!"); + } + d_ref_map = pmt::dict_add(d_ref_map, pmt::intern(name), pmt::make_any(block)); + } + + basic_block_sptr + block_registry::block_lookup(pmt::pmt_t symbol) + { + pmt::pmt_t ref = pmt::dict_ref(d_ref_map, symbol, pmt::PMT_NIL); + if(pmt::eq(ref, pmt::PMT_NIL)) { + throw std::runtime_error("block lookup failed! block not found!"); + } + basic_block* blk = boost::any_cast<basic_block*>(pmt::any_ref(ref)); + return blk->shared_from_this(); + } + + void + block_registry::register_primitive(std::string blk, block* ref) + { + primitive_map[blk] = ref; + } + + void + block_registry::unregister_primitive(std::string blk) + { + primitive_map.erase(primitive_map.find(blk)); + } + + void + block_registry::notify_blk(std::string blk) + { + if(primitive_map.find(blk) == primitive_map.end()) { + return; + } + if(primitive_map[blk]->detail().get()) + primitive_map[blk]->detail()->d_tpb.notify_msg(); + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/buffer.cc b/gnuradio-runtime/lib/buffer.cc new file mode 100644 index 0000000000..1bcfc2a6e4 --- /dev/null +++ b/gnuradio-runtime/lib/buffer.cc @@ -0,0 +1,343 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2009,2010,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/buffer.h> +#include <gnuradio/math.h> +#include "vmcircbuf.h" +#include <stdexcept> +#include <iostream> +#include <assert.h> +#include <algorithm> +#include <boost/math/common_factor_rt.hpp> + +namespace gr { + + static long s_buffer_count = 0; // counts for debugging storage mgmt + static long s_buffer_reader_count = 0; + + /* ---------------------------------------------------------------------------- + Notes on storage management + + Pretty much all the fundamental classes are now using the + shared_ptr stuff for automatic reference counting. To ensure that + no mistakes are made, we make the constructors for classes private, + and then provide a free factory function that returns a smart + pointer to the desired class. + + gr::buffer and gr::buffer_reader are no exceptions. However, they + both want pointers to each other, and unless we do something, we'll + never delete any of them because of the circular structure. + They'll always have a reference count of at least one. We could + use boost::weak_ptr's from gr::buffer to gr::buffer_reader but that + introduces it's own problems. (gr::buffer_reader's destructor needs + to call gr::buffer::drop_reader, but has no easy way to get a + shared_ptr to itself.) + + Instead, we solve this problem by having gr::buffer hold a raw + pointer to gr::buffer_reader in its d_reader vector. + gr::buffer_reader's destructor calls gr::buffer::drop_reader, so + we're never left with an dangling pointer. gr::buffer_reader still + has a shared_ptr to the buffer ensuring that the buffer doesn't go + away under it. However, when the reference count of a + gr::buffer_reader goes to zero, we can successfully reclaim it. + ---------------------------------------------------------------------------- */ + + /* + * Compute the minimum number of buffer items that work (i.e., + * address space wrap-around works). To work is to satisfy this + * contraint for integer buffer_size and k: + * + * type_size * nitems == k * page_size + */ + static long + minimum_buffer_items(long type_size, long page_size) + { + return page_size / boost::math::gcd (type_size, page_size); + } + + + buffer::buffer(int nitems, size_t sizeof_item, block_sptr link) + : d_base(0), d_bufsize(0), d_vmcircbuf(0), + d_sizeof_item(sizeof_item), d_link(link), + d_write_index(0), d_abs_write_offset(0), d_done(false), + d_last_min_items_read(0) + { + if(!allocate_buffer (nitems, sizeof_item)) + throw std::bad_alloc (); + + s_buffer_count++; + } + + buffer_sptr + make_buffer(int nitems, size_t sizeof_item, block_sptr link) + { + return buffer_sptr(new buffer(nitems, sizeof_item, link)); + } + + buffer::~buffer() + { + delete d_vmcircbuf; + assert(d_readers.size() == 0); + s_buffer_count--; + } + + /*! + * sets d_vmcircbuf, d_base, d_bufsize. + * returns true iff successful. + */ + bool + buffer::allocate_buffer(int nitems, size_t sizeof_item) + { + int orig_nitems = nitems; + + // Any buffersize we come up with must be a multiple of min_nitems. + int granularity = gr::vmcircbuf_sysconfig::granularity(); + int min_nitems = minimum_buffer_items(sizeof_item, granularity); + + // Round-up nitems to a multiple of min_nitems. + if(nitems % min_nitems != 0) + nitems = ((nitems / min_nitems) + 1) * min_nitems; + + // If we rounded-up a whole bunch, give the user a heads up. + // This only happens if sizeof_item is not a power of two. + + if(nitems > 2 * orig_nitems && nitems * (int) sizeof_item > granularity){ + std::cerr << "gr::buffer::allocate_buffer: warning: tried to allocate\n" + << " " << orig_nitems << " items of size " + << sizeof_item << ". Due to alignment requirements\n" + << " " << nitems << " were allocated. If this isn't OK, consider padding\n" + << " your structure to a power-of-two bytes.\n" + << " On this platform, our allocation granularity is " << granularity << " bytes.\n"; + } + + d_bufsize = nitems; + d_vmcircbuf = gr::vmcircbuf_sysconfig::make(d_bufsize * d_sizeof_item); + if(d_vmcircbuf == 0){ + std::cerr << "gr::buffer::allocate_buffer: failed to allocate buffer of size " + << d_bufsize * d_sizeof_item / 1024 << " KB\n"; + return false; + } + + d_base = (char*)d_vmcircbuf->pointer_to_first_copy(); + return true; + } + + int + buffer::space_available() + { + if(d_readers.empty()) + return d_bufsize - 1; // See comment below + + else { + // Find out the maximum amount of data available to our readers + + int most_data = d_readers[0]->items_available(); + uint64_t min_items_read = d_readers[0]->nitems_read(); + for(size_t i = 1; i < d_readers.size (); i++) { + most_data = std::max(most_data, d_readers[i]->items_available()); + min_items_read = std::min(min_items_read, d_readers[i]->nitems_read()); + } + + if(min_items_read != d_last_min_items_read) { + prune_tags(d_last_min_items_read); + d_last_min_items_read = min_items_read; + } + + // The -1 ensures that the case d_write_index == d_read_index is + // unambiguous. It indicates that there is no data for the reader + return d_bufsize - most_data - 1; + } + } + + void * + buffer::write_pointer() + { + return &d_base[d_write_index * d_sizeof_item]; + } + + void + buffer::update_write_pointer(int nitems) + { + gr::thread::scoped_lock guard(*mutex()); + d_write_index = index_add(d_write_index, nitems); + d_abs_write_offset += nitems; + } + + void + buffer::set_done(bool done) + { + gr::thread::scoped_lock guard(*mutex()); + d_done = done; + } + + buffer_reader_sptr + buffer_add_reader(buffer_sptr buf, int nzero_preload, block_sptr link) + { + if(nzero_preload < 0) + throw std::invalid_argument("buffer_add_reader: nzero_preload must be >= 0"); + + buffer_reader_sptr r(new buffer_reader(buf, + buf->index_sub(buf->d_write_index, + nzero_preload), + link)); + buf->d_readers.push_back(r.get ()); + + return r; + } + + void + buffer::drop_reader(buffer_reader *reader) + { + std::vector<buffer_reader *>::iterator result = + std::find(d_readers.begin(), d_readers.end(), reader); + + if(result == d_readers.end()) + throw std::invalid_argument("buffer::drop_reader"); // we didn't find it... + + d_readers.erase(result); + } + + void + buffer::add_item_tag(const tag_t &tag) + { + gr::thread::scoped_lock guard(*mutex()); + d_item_tags.push_back(tag); + } + + void + buffer::remove_item_tag(const tag_t &tag) + { + gr::thread::scoped_lock guard(*mutex()); + for(std::deque<tag_t>::iterator it = d_item_tags.begin(); it != d_item_tags.end(); ++it) { + if(*it == tag) { + d_item_tags.erase(it); + break; + } + } + } + + void + buffer::prune_tags(uint64_t max_time) + { + /* NOTE: this function _should_ lock the mutex before editing + d_item_tags. In practice, this function is only called at + runtime by min_available_space in block_executor.cc, which + locks the mutex itself. + + If this function is used elsewhere, remember to lock the + buffer's mutex al la the scoped_lock line below. + */ + //gr::thread::scoped_lock guard(*mutex()); + std::deque<tag_t>::iterator itr = d_item_tags.begin(); + + uint64_t item_time; + + // Since tags are not guarenteed to be in any particular order, we + // need to erase here instead of pop_front. An erase in the middle + // invalidates all iterators; so this resets the iterator to find + // more. Mostly, we wil be erasing from the front and + // therefore lose little time this way. + while(itr != d_item_tags.end()) { + item_time = (*itr).offset; + if(item_time < max_time) { + d_item_tags.erase(itr); + itr = d_item_tags.begin(); + } + else + itr++; + } + } + + long + buffer_ncurrently_allocated() + { + return s_buffer_count; + } + + // ---------------------------------------------------------------------------- + + buffer_reader::buffer_reader(buffer_sptr buffer, unsigned int read_index, + block_sptr link) + : d_buffer(buffer), d_read_index(read_index), d_abs_read_offset(0), d_link(link) + { + s_buffer_reader_count++; + } + + buffer_reader::~buffer_reader() + { + d_buffer->drop_reader(this); + s_buffer_reader_count--; + } + + int + buffer_reader::items_available() const + { + return d_buffer->index_sub(d_buffer->d_write_index, d_read_index); + } + + const void * + buffer_reader::read_pointer() + { + return &d_buffer->d_base[d_read_index * d_buffer->d_sizeof_item]; + } + + void + buffer_reader::update_read_pointer(int nitems) + { + gr::thread::scoped_lock guard(*mutex()); + d_read_index = d_buffer->index_add (d_read_index, nitems); + d_abs_read_offset += nitems; + } + + void + buffer_reader::get_tags_in_range(std::vector<tag_t> &v, + uint64_t abs_start, + uint64_t abs_end) + { + gr::thread::scoped_lock guard(*mutex()); + + v.resize(0); + std::deque<tag_t>::iterator itr = d_buffer->get_tags_begin(); + + uint64_t item_time; + while(itr != d_buffer->get_tags_end()) { + item_time = (*itr).offset; + + if((item_time >= abs_start) && (item_time < abs_end)) { + v.push_back(*itr); + } + + itr++; + } + } + + long + buffer_reader_ncurrently_allocated() + { + return s_buffer_reader_count; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/circular_file.cc b/gnuradio-runtime/lib/circular_file.cc new file mode 100644 index 0000000000..4d7d06082a --- /dev/null +++ b/gnuradio-runtime/lib/circular_file.cc @@ -0,0 +1,208 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2010,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "circular_file.h" + +#include <unistd.h> +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdio.h> +#include <assert.h> +#include <stdlib.h> + +#include <algorithm> +#include <stdio.h> +#include <string.h> + +#ifdef HAVE_IO_H +#include <io.h> +#endif + +namespace gr { + + static const int HEADER_SIZE = 4096; + static const int HEADER_MAGIC = 0xEB021026; + + static const int HD_MAGIC = 0; + static const int HD_HEADER_SIZE = 1; // integer offsets into header + static const int HD_BUFFER_SIZE = 2; + static const int HD_BUFFER_BASE = 3; + static const int HD_BUFFER_CURRENT = 4; + + circular_file::circular_file(const char *filename, + bool writable, int size) + : d_fd(-1), d_header(0), d_buffer(0), d_mapped_size(0), d_bytes_read(0) + { + int mm_prot; + if(writable) { +#ifdef HAVE_MMAP + mm_prot = PROT_READ | PROT_WRITE; +#endif + d_fd = open(filename, O_CREAT | O_RDWR | O_TRUNC, 0664); + if(d_fd < 0) { + perror(filename); + exit(1); + } +#ifdef HAVE_MMAP /* FIXME */ + if(ftruncate(d_fd, size + HEADER_SIZE) != 0) { + perror(filename); + exit(1); + } +#endif + } + else { +#ifdef HAVE_MMAP + mm_prot = PROT_READ; +#endif + d_fd = open (filename, O_RDONLY); + if(d_fd < 0) { + perror(filename); + exit(1); + } + } + + struct stat statbuf; + if(fstat (d_fd, &statbuf) < 0) { + perror(filename); + exit(1); + } + + if(statbuf.st_size < HEADER_SIZE) { + fprintf(stderr, "%s: file too small to be circular buffer\n", filename); + exit(1); + } + + d_mapped_size = statbuf.st_size; +#ifdef HAVE_MMAP + void *p = mmap (0, d_mapped_size, mm_prot, MAP_SHARED, d_fd, 0); + if(p == MAP_FAILED) { + perror("gr::circular_file: mmap failed"); + exit(1); + } + + d_header = (int*)p; +#else + perror("gr::circular_file: mmap unsupported by this system"); + exit(1); +#endif + + if(writable) { // init header + + if(size < 0) { + fprintf(stderr, "gr::circular_buffer: size must be > 0 when writable\n"); + exit(1); + } + + d_header[HD_MAGIC] = HEADER_MAGIC; + d_header[HD_HEADER_SIZE] = HEADER_SIZE; + d_header[HD_BUFFER_SIZE] = size; + d_header[HD_BUFFER_BASE] = HEADER_SIZE; // right after header + d_header[HD_BUFFER_CURRENT] = 0; + } + + // sanity check (the asserts are a bit unforgiving...) + + assert(d_header[HD_MAGIC] == HEADER_MAGIC); + assert(d_header[HD_HEADER_SIZE] == HEADER_SIZE); + assert(d_header[HD_BUFFER_SIZE] > 0); + assert(d_header[HD_BUFFER_BASE] >= d_header[HD_HEADER_SIZE]); + assert(d_header[HD_BUFFER_BASE] + d_header[HD_BUFFER_SIZE] <= d_mapped_size); + assert(d_header[HD_BUFFER_CURRENT] >= 0 && + d_header[HD_BUFFER_CURRENT] < d_header[HD_BUFFER_SIZE]); + + d_bytes_read = 0; + d_buffer = (unsigned char*)d_header + d_header[HD_BUFFER_BASE]; + } + + circular_file::~circular_file() + { +#ifdef HAVE_MMAP + if(munmap ((char *) d_header, d_mapped_size) < 0) { + perror("gr::circular_file: munmap"); + exit(1); + } +#endif + close(d_fd); + } + + bool + circular_file::write(void *vdata, int nbytes) + { + unsigned char *data = (unsigned char*)vdata; + int buffer_size = d_header[HD_BUFFER_SIZE]; + int buffer_current = d_header[HD_BUFFER_CURRENT]; + + while(nbytes > 0) { + int n = std::min(nbytes, buffer_size - buffer_current); + memcpy(d_buffer + buffer_current, data, n); + + buffer_current += n; + if(buffer_current >= buffer_size) + buffer_current = 0; + + data += n; + nbytes -= n; + } + + d_header[HD_BUFFER_CURRENT] = buffer_current; + return true; + } + + int + circular_file::read(void *vdata, int nbytes) + { + unsigned char *data = (unsigned char *) vdata; + int buffer_current = d_header[HD_BUFFER_CURRENT]; + int buffer_size = d_header[HD_BUFFER_SIZE]; + int total = 0; + + nbytes = std::min(nbytes, buffer_size - d_bytes_read); + + while(nbytes > 0) { + int offset = (buffer_current + d_bytes_read) % buffer_size; + int n = std::min (nbytes, buffer_size - offset); + memcpy(data, d_buffer + offset, n); + data += n; + d_bytes_read += n; + total += n; + nbytes -= n; + } + return total; + } + + void + circular_file::reset_read_pointer() + { + d_bytes_read = 0; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/circular_file.h b/gnuradio-runtime/lib/circular_file.h new file mode 100644 index 0000000000..1dc431d69a --- /dev/null +++ b/gnuradio-runtime/lib/circular_file.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef GR_CIRCULAR_FILE_H +#define GR_CIRCULAR_FILE_H + +#include <gnuradio/api.h> + +namespace gr { + + /* + * writes input data into a circular buffer on disk. + * + * the file contains a fixed header: + * 0x0000: int32 magic (0xEB021026) + * 0x0004: int32 size in bytes of header (constant 4096) + * 0x0008: int32 size in bytes of circular buffer (not including header) + * 0x000C: int32 file offset to beginning of circular buffer + * 0x0010: int32 byte offset from beginning of circular buffer to + * current start of data + */ + class GR_RUNTIME_API circular_file + { + private: + int d_fd; + int *d_header; + unsigned char *d_buffer; + int d_mapped_size; + int d_bytes_read; + + public: + circular_file(const char *filename, bool writable = false, int size = 0); + ~circular_file(); + + bool write(void *data, int nbytes); + + // returns # of bytes actually read or 0 if end of buffer, or -1 on error. + int read(void *data, int nbytes); + + // reset read pointer to beginning of buffer. + void reset_read_pointer(); + }; + +} /* namespace gr */ + +#endif /* GR_CIRCULAR_FILE_H */ diff --git a/gnuradio-runtime/lib/complex_vec_test.h b/gnuradio-runtime/lib/complex_vec_test.h index bcfa732f41..d69d523374 100644 --- a/gnuradio-runtime/lib/complex_vec_test.h +++ b/gnuradio-runtime/lib/complex_vec_test.h @@ -1,4 +1,26 @@ -#include <gr_runtime_api.h> +/* -*- c++ -*- */ +/* + * Copyright 2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <gnuradio/api.h> #include <vector> #include <complex> diff --git a/gnuradio-runtime/lib/gr_constants.cc.in b/gnuradio-runtime/lib/constants.cc.in index b94f254d66..828c4397f7 100644 --- a/gnuradio-runtime/lib/gr_constants.cc.in +++ b/gnuradio-runtime/lib/constants.cc.in @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006,2009 Free Software Foundation, Inc. + * Copyright 2006,2009,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -24,34 +24,38 @@ #include <config.h> #endif -#include <gr_constants.h> - -const std::string -gr_prefix() -{ - return "@prefix@"; -} - -const std::string -gr_sysconfdir() -{ - return "@SYSCONFDIR@"; -} - -const std::string -gr_prefsdir() -{ - return "@GR_PREFSDIR@"; -} - -const std::string -gr_build_date() -{ - return "@BUILD_DATE@"; -} - -const std::string -gr_version() -{ - return "@VERSION@"; -} +#include <gnuradio/constants.h> + +namespace gr { + + const std::string + prefix() + { + return "@prefix@"; + } + + const std::string + sysconfdir() + { + return "@SYSCONFDIR@"; + } + + const std::string + prefsdir() + { + return "@GR_PREFSDIR@"; + } + + const std::string + build_date() + { + return "@BUILD_DATE@"; + } + + const std::string + version() + { + return "@VERSION@"; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/controlport/CMakeLists.txt b/gnuradio-runtime/lib/controlport/CMakeLists.txt new file mode 100644 index 0000000000..c05a82bf4f --- /dev/null +++ b/gnuradio-runtime/lib/controlport/CMakeLists.txt @@ -0,0 +1,62 @@ +# Copyright 2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +if(ENABLE_GR_CTRLPORT) + +include_directories(${ICE_INCLUDE_DIR}) + +# Add definition so we can compile in ControlPort to the blocks. +ADD_DEFINITIONS(-DGR_CTRLPORT) + +######################################################################## +# Run ICE To compile Slice files +######################################################################## +EXECUTE_PROCESS( + COMMAND "${ICE_SLICE2CPP}" "-I${CMAKE_CURRENT_SOURCE_DIR}" + "--output-dir=${CMAKE_CURRENT_BINARY_DIR}/" + "${CMAKE_CURRENT_SOURCE_DIR}/gnuradio.ice" + ) + +list(APPEND gnuradio_runtime_sources + ${CMAKE_CURRENT_SOURCE_DIR}/ice_application_base.cc + ${CMAKE_CURRENT_SOURCE_DIR}/rpcmanager.cc + ${CMAKE_CURRENT_SOURCE_DIR}/rpcpmtconverters_ice.cc + ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_aggregator.cc + ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_booter_aggregator.cc + ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_booter_ice.cc + ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_ice.cc + ${CMAKE_CURRENT_SOURCE_DIR}/rpcserver_selector.cc +) + +# Append generated file in build directory +list(APPEND gnuradio_runtime_sources + ${CMAKE_CURRENT_BINARY_DIR}/gnuradio.cpp +) + +######################################################################## +# Add controlport stuff to gnuradio-runtime +######################################################################## + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +list(APPEND gnuradio_runtime_libs + ${ICE_LIBRARIES} +) + +endif(ENABLE_GR_CTRLPORT) diff --git a/gnuradio-runtime/lib/ICE_LICENSE b/gnuradio-runtime/lib/controlport/ICE_LICENSE index 43ea7572d9..43ea7572d9 100644 --- a/gnuradio-runtime/lib/ICE_LICENSE +++ b/gnuradio-runtime/lib/controlport/ICE_LICENSE diff --git a/gnuradio-runtime/lib/frontend.ice b/gnuradio-runtime/lib/controlport/frontend.ice index b7474f37bf..b7474f37bf 100644 --- a/gnuradio-runtime/lib/frontend.ice +++ b/gnuradio-runtime/lib/controlport/frontend.ice diff --git a/gnuradio-runtime/lib/gnuradio.ice b/gnuradio-runtime/lib/controlport/gnuradio.ice index 731cbea956..731cbea956 100644 --- a/gnuradio-runtime/lib/gnuradio.ice +++ b/gnuradio-runtime/lib/controlport/gnuradio.ice diff --git a/gnuradio-runtime/lib/ice_application_base.cc b/gnuradio-runtime/lib/controlport/ice_application_base.cc index 88db6056c1..b390c77c84 100644 --- a/gnuradio-runtime/lib/ice_application_base.cc +++ b/gnuradio-runtime/lib/controlport/ice_application_base.cc @@ -20,7 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#include <ice_application_base.h> +#include <gnuradio/ice_application_base.h> int ice_application_common::d_reacquire_attributes(0); bool ice_application_common::d_main_called(false); diff --git a/gnuradio-runtime/lib/rpcmanager.cc b/gnuradio-runtime/lib/controlport/rpcmanager.cc index 4d164b63f3..59ec518960 100644 --- a/gnuradio-runtime/lib/rpcmanager.cc +++ b/gnuradio-runtime/lib/controlport/rpcmanager.cc @@ -20,7 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#include <rpcmanager.h> +#include <gnuradio/rpcmanager.h> #include <iostream> #include <stdexcept> diff --git a/gnuradio-runtime/lib/rpcpmtconverters_ice.cc b/gnuradio-runtime/lib/controlport/rpcpmtconverters_ice.cc index 7c8b6041e9..18b73faeba 100644 --- a/gnuradio-runtime/lib/rpcpmtconverters_ice.cc +++ b/gnuradio-runtime/lib/controlport/rpcpmtconverters_ice.cc @@ -20,7 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#include <rpcpmtconverters_ice.h> +#include <gnuradio/rpcpmtconverters_ice.h> #include <Ice/Ice.h> #include <gnuradio.h> diff --git a/gnuradio-runtime/lib/rpcserver_aggregator.cc b/gnuradio-runtime/lib/controlport/rpcserver_aggregator.cc index d750d64905..3ff553af69 100644 --- a/gnuradio-runtime/lib/rpcserver_aggregator.cc +++ b/gnuradio-runtime/lib/controlport/rpcserver_aggregator.cc @@ -20,8 +20,8 @@ * Boston, MA 02110-1301, USA. */ -#include <rpcserver_aggregator.h> -#include <rpcserver_booter_base.h> +#include <gnuradio/rpcserver_aggregator.h> +#include <gnuradio/rpcserver_booter_base.h> #include <iostream> #include <sstream> #include <stdexcept> diff --git a/gnuradio-runtime/lib/rpcserver_booter_aggregator.cc b/gnuradio-runtime/lib/controlport/rpcserver_booter_aggregator.cc index c4c1b03c15..e86306910d 100644 --- a/gnuradio-runtime/lib/rpcserver_booter_aggregator.cc +++ b/gnuradio-runtime/lib/controlport/rpcserver_booter_aggregator.cc @@ -20,7 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#include <rpcserver_booter_aggregator.h> +#include <gnuradio/rpcserver_booter_aggregator.h> rpcserver_booter_aggregator::rpcserver_booter_aggregator() : d_type(std::string("aggregator")), server(new rpcserver_aggregator()) diff --git a/gnuradio-runtime/lib/rpcserver_booter_ice.cc b/gnuradio-runtime/lib/controlport/rpcserver_booter_ice.cc index 7cc8cc8938..cffa268a6d 100644 --- a/gnuradio-runtime/lib/rpcserver_booter_ice.cc +++ b/gnuradio-runtime/lib/controlport/rpcserver_booter_ice.cc @@ -20,8 +20,8 @@ * Boston, MA 02110-1301, USA. */ -#include <rpcserver_ice.h> -#include <rpcserver_booter_ice.h> +#include <gnuradio/rpcserver_ice.h> +#include <gnuradio/rpcserver_booter_ice.h> namespace { static const char* const CONTROL_PORT_CLASS("ice"); diff --git a/gnuradio-runtime/lib/rpcserver_ice.cc b/gnuradio-runtime/lib/controlport/rpcserver_ice.cc index 2454bf2580..045d7ba4f1 100644 --- a/gnuradio-runtime/lib/rpcserver_ice.cc +++ b/gnuradio-runtime/lib/controlport/rpcserver_ice.cc @@ -20,7 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#include <rpcserver_ice.h> +#include <gnuradio/rpcserver_ice.h> #include <IceUtil/IceUtil.h> #include <Ice/Ice.h> #include <iostream> diff --git a/gnuradio-runtime/lib/rpcserver_selector.cc b/gnuradio-runtime/lib/controlport/rpcserver_selector.cc index 362d5f060a..697ec497b1 100644 --- a/gnuradio-runtime/lib/rpcserver_selector.cc +++ b/gnuradio-runtime/lib/controlport/rpcserver_selector.cc @@ -20,14 +20,14 @@ * Boston, MA 02110-1301, USA. */ -#include <rpcserver_booter_aggregator.h> -#include <rpcmanager.h> -#include <rpcserver_selector.h> +#include <gnuradio/rpcserver_booter_aggregator.h> +#include <gnuradio/rpcmanager.h> +#include <gnuradio/rpcserver_selector.h> bool rpcmanager::make_aggregator(false); #ifdef RPCSERVER_ICE - #include <rpcserver_booter_ice.h> + #include <gnuradio/rpcserver_booter_ice.h> rpcmanager::rpcserver_booter_register_helper<rpcserver_booter_ice> boot_ice; #endif diff --git a/gnuradio-runtime/lib/dispatcher.cc b/gnuradio-runtime/lib/dispatcher.cc new file mode 100644 index 0000000000..7c9e13c5a6 --- /dev/null +++ b/gnuradio-runtime/lib/dispatcher.cc @@ -0,0 +1,195 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/dispatcher.h> +#include <math.h> +#include <errno.h> +#include <stdio.h> + +#ifdef HAVE_SELECT +# ifdef HAVE_SYS_SELECT_H +# include <sys/select.h> +# else +# ifdef HAVE_SYS_TIME_H +# include <sys/time.h> +# endif +# ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +# endif +# ifdef HAVE_UNISTD_H +# include <unistd.h> +# endif +# endif +#endif + +namespace gr { + + static dispatcher_sptr s_singleton; + + dispatcher_sptr + make_dispatcher() + { + return dispatcher_sptr(new dispatcher()); + } + + dispatcher_sptr + dispatcher_singleton() + { + if(s_singleton) + return s_singleton; + + s_singleton = make_dispatcher(); + return s_singleton; + } + +#if !defined(HAVE_SELECT) // Stub it out + + dispatcher::dispatcher() + { + } + + dispatcher::~dispatcher() + { + } + + bool + dispatcher::add_handler(select_handler_sptr handler) + { + return true; + } + + bool + dispatcher::del_handler(select_handler_sptr handler) + { + return true; + } + + bool + dispatcher::del_handler(select_handler *handler) + { + return true; + } + + void + dispatcher::loop(double timeout) + { + } + +#else // defined(HAVE_SELECT) + + dispatcher::dispatcher() + : d_handler(FD_SETSIZE), d_max_index(-1) + { + } + + dispatcher::~dispatcher() + { + } + + bool + dispatcher::add_handler(select_handler_sptr handler) + { + int fd = handler->fd(); + if(fd < 0 || fd >= FD_SETSIZE) + return false; + + d_max_index = std::max(d_max_index, fd); + d_handler[fd] = handler; + return true; + } + + bool + dispatcher::del_handler(select_handler_sptr handler) + { + return del_handler(handler.get()); + } + + bool + dispatcher::del_handler(select_handler *handler) + { + int fd = handler->fd(); + if(fd < 0 || fd >= FD_SETSIZE) + return false; + + d_handler[fd].reset(); + + if(fd == d_max_index) { + int i; + for(i = fd - 1; i >= 0 && !d_handler[i]; i--) + ; + d_max_index = i; + } + return true; + } + + void + dispatcher::loop(double timeout) + { + struct timeval master; + struct timeval tmp; + fd_set rd_set; + fd_set wr_set; + + double secs = floor (timeout); + master.tv_sec = (long) secs; + master.tv_usec = (long) ((timeout - secs) * 1e6); + + while(d_max_index >= 0) { + FD_ZERO(&rd_set); + FD_ZERO(&wr_set); + + for(int i = 0; i <= d_max_index; i++) { + if(d_handler[i] && d_handler[i]->readable()) + FD_SET(i, &rd_set); + if(d_handler[i] && d_handler[i]->writable()) + FD_SET(i, &wr_set); + } + + tmp = master; + int retval = select(d_max_index+1, &rd_set, &wr_set, 0, &tmp); + if(retval == 0) // timed out with nothing ready + continue; + if(retval < 0) { + if(errno == EINTR) + continue; + perror("gr_dispatcher/select"); + return; + } + + for(int i = 0; i <= d_max_index; i++) { + if(FD_ISSET(i, &rd_set)) + if(d_handler[i]) + d_handler[i]->handle_read(); + if(FD_ISSET(i, &wr_set)) + if(d_handler[i]) + d_handler[i]->handle_write(); + } + } + } + +} /* namespace gr */ + +#endif /* HAVE_SELECT */ diff --git a/gnuradio-runtime/lib/error_handler.cc b/gnuradio-runtime/lib/error_handler.cc new file mode 100644 index 0000000000..50db15d049 --- /dev/null +++ b/gnuradio-runtime/lib/error_handler.cc @@ -0,0 +1,249 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ +/* + * This code is based on error.cc from the "Click Modular Router". + * Original copyright follows: + */ +/* + * error.{cc,hh} -- flexible classes for error reporting + * Eddie Kohler + * + * Copyright (c) 1999-2000 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, subject to the conditions + * listed in the Click LICENSE file. These conditions include: you must + * preserve this copyright notice, and you cannot mention the copyright + * holders in advertising related to the Software without their permission. + * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This + * notice is a summary of the Click LICENSE file; the license in that file is + * legally binding. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/error_handler.h> +#include <assert.h> +#include <stdexcept> +#include <unistd.h> + +#ifdef HAVE_IO_H +#include <io.h> +#endif + +namespace gr { + + static error_handler *s_default_handler = 0; + static error_handler *s_silent_handler = 0; + + bool + error_handler::has_default_handler() + { + return s_default_handler != 0; + } + + void + error_handler::set_default_handler(error_handler *errh) + { + s_default_handler = errh; + } + + error_handler * + error_handler::default_handler() + { + assert(s_default_handler != 0); + return s_default_handler; + } + + error_handler * + error_handler::silent_handler() + { + assert(s_silent_handler != 0); + return s_silent_handler; + } + + // ---------------------------------------------------------------- + + error_handler::~error_handler() + { + // nop + } + + void + error_handler::debug(const char *format, ...) + { + va_list val; + va_start(val, format); + verror(ERR_DEBUG, format, val); + va_end(val); + } + + void + error_handler::message(const char *format, ...) + { + va_list val; + va_start(val, format); + verror(ERR_MESSAGE, format, val); + va_end(val); + } + + void + error_handler::warning(const char *format, ...) + { + va_list val; + va_start(val, format); + verror(ERR_WARNING, format, val); + va_end(val); + } + + void + error_handler::error(const char *format, ...) + { + va_list val; + va_start(val, format); + verror(ERR_ERROR, format, val); + va_end(val); + } + + void + error_handler::fatal(const char *format, ...) + { + va_list val; + va_start(val, format); + verror(ERR_FATAL, format, val); + va_end(val); + } + + void + error_handler::verror(seriousness s, const char *format, va_list val) + { + std::string text = make_text(s, format, val); + handle_text(s, text); + count_error(s); + } + + void + error_handler::verror_text(seriousness s, const std::string &text) + { + // text is already made + handle_text(s, text); + count_error(s); + } + + std::string + error_handler::make_text(seriousness s, const char *format, va_list val) + { + char text_buf[4096]; + vsnprintf(text_buf, sizeof(text_buf), format, val); + text_buf[sizeof(text_buf)-1] = 0; + return text_buf; + } + + // ---------------------------------------------------------------- + + void + base_error_handler::count_error(seriousness s) + { + if(s < ERR_WARNING) + /* do nothing */; + else if(s < ERR_ERROR) + d_nwarnings++; + else + d_nerrors++; + } + + // ---------------------------------------------------------------- + + file_error_handler::file_error_handler(FILE *file) + : d_file(file), d_fd(-1) + { + } + + file_error_handler::file_error_handler(int file_descriptor) + { + d_fd = dup(file_descriptor); // so we can fclose it + if(d_fd == -1){ + perror("gr::file_error_handler:dup"); + throw std::invalid_argument("gr::file_error_handler:dup"); + } + d_file = fdopen(d_fd, "w"); + if(d_file == 0){ + perror("gr::file_error_handler:fdopen"); + throw std::invalid_argument("gr::file_error_handler:fdopen"); + } + } + + file_error_handler::~file_error_handler() + { + if(d_fd != -1){ + fclose(d_file); + } + } + + void + file_error_handler::handle_text(seriousness s, const std::string &text) + { + if(text.length() <= 0) + return; + + fwrite(text.data(), 1, text.length(), d_file); + if(text[text.length()-1] != '\n') + fwrite("\n", 1, 1, d_file); + + if(d_fd != -1) + fflush(d_file); // keep synced with any other users of fd + } + + + // ---------------------------------------------------------------- + // static error handlers + // + + class silent_error_handler : public base_error_handler + { + public: + silent_error_handler() {} + void handle_text(seriousness s, const std::string &str); + }; + + void + silent_error_handler::handle_text(seriousness s, const std::string &str) + { + // nop + } + + class force_init + { + public: + force_init() + { + s_default_handler = new file_error_handler(stdout); + s_silent_handler = new silent_error_handler(); + } + }; + + static force_init kludge; + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/feval.cc b/gnuradio-runtime/lib/feval.cc new file mode 100644 index 0000000000..93976c8ac7 --- /dev/null +++ b/gnuradio-runtime/lib/feval.cc @@ -0,0 +1,136 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gnuradio/feval.h> + +namespace gr { + + feval_dd::~feval_dd(){} + + double + feval_dd::eval(double x) + { + return 0; + } + + double + feval_dd::calleval(double x) + { + return eval(x); + } + + // ---------------------------------------------------------------- + + feval_cc::~feval_cc(){} + + gr_complex + feval_cc::eval(gr_complex x) + { + return 0; + } + + gr_complex + feval_cc::calleval(gr_complex x) + { + return eval(x); + } + + // ---------------------------------------------------------------- + + feval_ll::~feval_ll(){} + + long + feval_ll::eval(long x) + { + return 0; + } + + long + feval_ll::calleval(long x) + { + return eval(x); + } + + // ---------------------------------------------------------------- + + feval::~feval(){} + + void + feval::eval(void) + { + // nop + } + + void + feval::calleval(void) + { + eval(); + } + + // ---------------------------------------------------------------- + + feval_p::~feval_p(){} + + void + feval_p::eval(pmt::pmt_t x) + { + // nop + } + + void + feval_p::calleval(pmt::pmt_t x) + { + eval(x); + } + + /* + * Trivial examples showing C++ (transparently) calling Python + */ + double + feval_dd_example(feval_dd *f, double x) + { + return f->calleval(x); + } + + gr_complex + feval_cc_example(feval_cc *f, gr_complex x) + { + return f->calleval(x); + } + + long + feval_ll_example(feval_ll *f, long x) + { + return f->calleval(x); + } + + void + feval_example(feval *f) + { + f->calleval(); + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/flat_flowgraph.cc b/gnuradio-runtime/lib/flat_flowgraph.cc new file mode 100644 index 0000000000..8b188799a5 --- /dev/null +++ b/gnuradio-runtime/lib/flat_flowgraph.cc @@ -0,0 +1,436 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "flat_flowgraph.h" +#include <gnuradio/block_detail.h> +#include <gnuradio/buffer.h> +#include <gnuradio/prefs.h> +#include <volk/volk.h> +#include <iostream> +#include <map> +#include <boost/format.hpp> + +namespace gr { + +#define FLAT_FLOWGRAPH_DEBUG 0 + +// 32Kbyte buffer size between blocks +#define GR_FIXED_BUFFER_SIZE (32*(1L<<10)) + + static const unsigned int s_fixed_buffer_size = GR_FIXED_BUFFER_SIZE; + + flat_flowgraph_sptr + make_flat_flowgraph() + { + return flat_flowgraph_sptr(new flat_flowgraph()); + } + + flat_flowgraph::flat_flowgraph() + { + } + + flat_flowgraph::~flat_flowgraph() + { + } + + void + flat_flowgraph::setup_connections() + { + basic_block_vector_t blocks = calc_used_blocks(); + + // Assign block details to blocks + for(basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) + cast_to_block_sptr(*p)->set_detail(allocate_block_detail(*p)); + + // Connect inputs to outputs for each block + for(basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { + connect_block_inputs(*p); + + block_sptr block = cast_to_block_sptr(*p); + block->set_unaligned(0); + block->set_is_unaligned(false); + } + + // Connect message ports connetions + for(msg_edge_viter_t i = d_msg_edges.begin(); i != d_msg_edges.end(); i++) { + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << boost::format("flat_fg connecting msg primitives: (%s, %s)->(%s, %s)\n") % + i->src().block() % i->src().port() % + i->dst().block() % i->dst().port(); + i->src().block()->message_port_sub(i->src().port(), pmt::cons(i->dst().block()->alias_pmt(), i->dst().port())); + } + } + + block_detail_sptr + flat_flowgraph::allocate_block_detail(basic_block_sptr block) + { + int ninputs = calc_used_ports(block, true).size(); + int noutputs = calc_used_ports(block, false).size(); + block_detail_sptr detail = make_block_detail(ninputs, noutputs); + + block_sptr grblock = cast_to_block_sptr(block); + if(!grblock) + throw std::runtime_error("allocate_block_detail found non-gr::block"); + + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << "Creating block detail for " << block << std::endl; + + for(int i = 0; i < noutputs; i++) { + grblock->expand_minmax_buffer(i); + + buffer_sptr buffer = allocate_buffer(block, i); + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << "Allocated buffer for output " << block << ":" << i << std::endl; + detail->set_output(i, buffer); + + // Update the block's max_output_buffer based on what was actually allocated. + grblock->set_max_output_buffer(i, buffer->bufsize()); + } + + return detail; + } + + buffer_sptr + flat_flowgraph::allocate_buffer(basic_block_sptr block, int port) + { + block_sptr grblock = cast_to_block_sptr(block); + if(!grblock) + throw std::runtime_error("allocate_buffer found non-gr::block"); + int item_size = block->output_signature()->sizeof_stream_item(port); + + // *2 because we're now only filling them 1/2 way in order to + // increase the available parallelism when using the TPB scheduler. + // (We're double buffering, where we used to single buffer) + int nitems = s_fixed_buffer_size * 2 / item_size; + + // Make sure there are at least twice the output_multiple no. of items + if(nitems < 2*grblock->output_multiple()) // Note: this means output_multiple() + nitems = 2*grblock->output_multiple(); // can't be changed by block dynamically + + // If any downstream blocks are decimators and/or have a large output_multiple, + // ensure we have a buffer at least twice their decimation factor*output_multiple + basic_block_vector_t blocks = calc_downstream_blocks(block, port); + + // limit buffer size if indicated + if(grblock->max_output_buffer(port) > 0) { + //std::cout << "constraining output items to " << block->max_output_buffer(port) << "\n"; + nitems = std::min((long)nitems, (long)grblock->max_output_buffer(port)); + nitems -= nitems%grblock->output_multiple(); + if(nitems < 1) + throw std::runtime_error("problems allocating a buffer with the given max output buffer constraint!"); + } + else if(grblock->min_output_buffer(port) > 0) { + nitems = std::max((long)nitems, (long)grblock->min_output_buffer(port)); + nitems -= nitems%grblock->output_multiple(); + if(nitems < 1) + throw std::runtime_error("problems allocating a buffer with the given min output buffer constraint!"); + } + + for(basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { + block_sptr dgrblock = cast_to_block_sptr(*p); + if(!dgrblock) + throw std::runtime_error("allocate_buffer found non-gr::block"); + + double decimation = (1.0/dgrblock->relative_rate()); + int multiple = dgrblock->output_multiple(); + int history = dgrblock->history(); + nitems = std::max(nitems, static_cast<int>(2*(decimation*multiple+history))); + } + + // std::cout << "make_buffer(" << nitems << ", " << item_size << ", " << grblock << "\n"; + return make_buffer(nitems, item_size, grblock); + } + + void + flat_flowgraph::connect_block_inputs(basic_block_sptr block) + { + block_sptr grblock = cast_to_block_sptr(block); + if (!grblock) + throw std::runtime_error("connect_block_inputs found non-gr::block"); + + // Get its detail and edges that feed into it + block_detail_sptr detail = grblock->detail(); + edge_vector_t in_edges = calc_upstream_edges(block); + + // For each edge that feeds into it + for(edge_viter_t e = in_edges.begin(); e != in_edges.end(); e++) { + // Set the buffer reader on the destination port to the output + // buffer on the source port + int dst_port = e->dst().port(); + int src_port = e->src().port(); + basic_block_sptr src_block = e->src().block(); + block_sptr src_grblock = cast_to_block_sptr(src_block); + if(!src_grblock) + throw std::runtime_error("connect_block_inputs found non-gr::block"); + buffer_sptr src_buffer = src_grblock->detail()->output(src_port); + + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << "Setting input " << dst_port << " from edge " << (*e) << std::endl; + + detail->set_input(dst_port, buffer_add_reader(src_buffer, grblock->history()-1, grblock)); + } + } + + void + flat_flowgraph::merge_connections(flat_flowgraph_sptr old_ffg) + { + // Allocate block details if needed. Only new blocks that aren't pruned out + // by flattening will need one; existing blocks still in the new flowgraph will + // already have one. + for(basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { + block_sptr block = cast_to_block_sptr(*p); + + if(!block->detail()) { + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << "merge: allocating new detail for block " << (*p) << std::endl; + block->set_detail(allocate_block_detail(block)); + } + else + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << "merge: reusing original detail for block " << (*p) << std::endl; + } + + // Calculate the old edges that will be going away, and clear the + // buffer readers on the RHS. + for(edge_viter_t old_edge = old_ffg->d_edges.begin(); old_edge != old_ffg->d_edges.end(); old_edge++) { + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << "merge: testing old edge " << (*old_edge) << "..."; + + edge_viter_t new_edge; + for(new_edge = d_edges.begin(); new_edge != d_edges.end(); new_edge++) + if(new_edge->src() == old_edge->src() && + new_edge->dst() == old_edge->dst()) + break; + + if(new_edge == d_edges.end()) { // not found in new edge list + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << "not in new edge list" << std::endl; + // zero the buffer reader on RHS of old edge + block_sptr block(cast_to_block_sptr(old_edge->dst().block())); + int port = old_edge->dst().port(); + block->detail()->set_input(port, buffer_reader_sptr()); + } + else { + if (FLAT_FLOWGRAPH_DEBUG) + std::cout << "found in new edge list" << std::endl; + } + } + + // Now connect inputs to outputs, reusing old buffer readers if they exist + for(basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { + block_sptr block = cast_to_block_sptr(*p); + + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << "merge: merging " << (*p) << "..."; + + if(old_ffg->has_block_p(*p)) { + // Block exists in old flow graph + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << "used in old flow graph" << std::endl; + block_detail_sptr detail = block->detail(); + + // Iterate through the inputs and see what needs to be done + int ninputs = calc_used_ports(block, true).size(); // Might be different now + for(int i = 0; i < ninputs; i++) { + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << "Checking input " << block << ":" << i << "..."; + edge edge = calc_upstream_edge(*p, i); + + // Fish out old buffer reader and see if it matches correct buffer from edge list + block_sptr src_block = cast_to_block_sptr(edge.src().block()); + block_detail_sptr src_detail = src_block->detail(); + buffer_sptr src_buffer = src_detail->output(edge.src().port()); + buffer_reader_sptr old_reader; + if(i < detail->ninputs()) // Don't exceed what the original detail has + old_reader = detail->input(i); + + // If there's a match, use it + if(old_reader && (src_buffer == old_reader->buffer())) { + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << "matched, reusing" << std::endl; + } + else { + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << "needs a new reader" << std::endl; + + // Create new buffer reader and assign + detail->set_input(i, buffer_add_reader(src_buffer, block->history()-1, block)); + } + } + } + else { + // Block is new, it just needs buffer readers at this point + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << "new block" << std::endl; + connect_block_inputs(block); + + // Make sure all buffers are aligned + setup_buffer_alignment(block); + } + + // Now deal with the fact that the block details might have + // changed numbers of inputs and outputs vs. in the old + // flowgraph. + } + } + + void + flat_flowgraph::setup_buffer_alignment(block_sptr block) + { + const int alignment = volk_get_alignment(); + for(int i = 0; i < block->detail()->ninputs(); i++) { + void *r = (void*)block->detail()->input(i)->read_pointer(); + unsigned long int ri = (unsigned long int)r % alignment; + //std::cerr << "reader: " << r << " alignment: " << ri << std::endl; + if(ri != 0) { + size_t itemsize = block->detail()->input(i)->get_sizeof_item(); + block->detail()->input(i)->update_read_pointer(alignment-ri/itemsize); + } + block->set_unaligned(0); + block->set_is_unaligned(false); + } + + for(int i = 0; i < block->detail()->noutputs(); i++) { + void *w = (void*)block->detail()->output(i)->write_pointer(); + unsigned long int wi = (unsigned long int)w % alignment; + //std::cerr << "writer: " << w << " alignment: " << wi << std::endl; + if(wi != 0) { + size_t itemsize = block->detail()->output(i)->get_sizeof_item(); + block->detail()->output(i)->update_write_pointer(alignment-wi/itemsize); + } + block->set_unaligned(0); + block->set_is_unaligned(false); + } + } + + std::string + flat_flowgraph::edge_list() + { + std::stringstream s; + for(edge_viter_t e = d_edges.begin(); e != d_edges.end(); e++) + s << (*e) << std::endl; + return s.str(); + } + + void flat_flowgraph::dump() + { + for(edge_viter_t e = d_edges.begin(); e != d_edges.end(); e++) + std::cout << " edge: " << (*e) << std::endl; + + for(basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { + std::cout << " block: " << (*p) << std::endl; + block_detail_sptr detail = cast_to_block_sptr(*p)->detail(); + std::cout << " detail @" << detail << ":" << std::endl; + + int ni = detail->ninputs(); + int no = detail->noutputs(); + for(int i = 0; i < no; i++) { + buffer_sptr buffer = detail->output(i); + std::cout << " output " << i << ": " << buffer << std::endl; + } + + for(int i = 0; i < ni; i++) { + buffer_reader_sptr reader = detail->input(i); + std::cout << " reader " << i << ": " << reader + << " reading from buffer=" << reader->buffer() << std::endl; + } + } + } + + block_vector_t + flat_flowgraph::make_block_vector(basic_block_vector_t &blocks) + { + block_vector_t result; + for(basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { + result.push_back(cast_to_block_sptr(*p)); + } + + return result; + } + + void + flat_flowgraph::clear_endpoint(const msg_endpoint &e, bool is_src) + { + for(size_t i=0; i<d_msg_edges.size(); i++) { + if(is_src) { + if(d_msg_edges[i].src() == e) { + d_msg_edges.erase(d_msg_edges.begin() + i); + i--; + } + } + else { + if(d_msg_edges[i].dst() == e) { + d_msg_edges.erase(d_msg_edges.begin() + i); + i--; + } + } + } + } + + void + flat_flowgraph::replace_endpoint(const msg_endpoint &e, const msg_endpoint &r, bool is_src) + { + size_t n_replr(0); + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << boost::format("flat_flowgraph::replace_endpoint( %s, %s, %d )\n") % e.block()% r.block()% is_src; + for(size_t i=0; i<d_msg_edges.size(); i++) { + if(is_src) { + if(d_msg_edges[i].src() == e) { + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << boost::format("flat_flowgraph::replace_endpoint() flattening to ( %s, %s )\n") \ + % r.block()% d_msg_edges[i].dst().block(); + d_msg_edges.push_back( msg_edge(r, d_msg_edges[i].dst() ) ); + n_replr++; + } + } + else { + if(d_msg_edges[i].dst() == e) { + if(FLAT_FLOWGRAPH_DEBUG) + std::cout << boost::format("flat_flowgraph::replace_endpoint() flattening to ( %s, %s )\n") \ + % r.block()% d_msg_edges[i].dst().block(); + d_msg_edges.push_back( msg_edge(d_msg_edges[i].src(), r ) ); + n_replr++; + } + } + } + } + + void + flat_flowgraph::enable_pc_rpc() + { +#ifdef GR_PERFORMANCE_COUNTERS + if(prefs::singleton()->get_bool("PerfCounters", "on", false)) { + basic_block_viter_t p; + for(p = d_blocks.begin(); p != d_blocks.end(); p++) { + block_sptr block = cast_to_block_sptr(*p); + if(!block->is_pc_rpc_set()) + block->setup_pc_rpc(); + } + } +#endif /* GR_PERFORMANCE_COUNTERS */ + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/flat_flowgraph.h b/gnuradio-runtime/lib/flat_flowgraph.h new file mode 100644 index 0000000000..fe43969b6f --- /dev/null +++ b/gnuradio-runtime/lib/flat_flowgraph.h @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2007,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_RUNTIME_FLAT_FLOWGRAPH_H +#define INCLUDED_GR_RUNTIME_FLAT_FLOWGRAPH_H + +#include <gnuradio/api.h> +#include <gnuradio/flowgraph.h> +#include <gnuradio/block.h> + +namespace gr { + + // Create a shared pointer to a heap allocated gr::flat_flowgraph + // (types defined in gr_runtime_types.h) + GR_RUNTIME_API flat_flowgraph_sptr make_flat_flowgraph(); + + /*! + *\brief Class specializing gr_flat_flowgraph that has all nodes + * as blocks, with no hierarchy + * \ingroup internal + */ + class GR_RUNTIME_API flat_flowgraph : public flowgraph + { + public: + friend GR_RUNTIME_API flat_flowgraph_sptr make_flat_flowgraph(); + + // Destruct an arbitrary gr::flat_flowgraph + ~flat_flowgraph(); + + // Wire list of gr::block together in new flat_flowgraph + void setup_connections(); + + // Merge applicable connections from existing flat flowgraph + void merge_connections(flat_flowgraph_sptr sfg); + + // Return a string list of edges + std::string edge_list(); + + void dump(); + + /*! + * Make a vector of gr::block from a vector of gr::basic_block + */ + static block_vector_t make_block_vector(basic_block_vector_t &blocks); + + void replace_endpoint(const msg_endpoint &e, const msg_endpoint &r, bool is_src); + void clear_endpoint(const msg_endpoint &e, bool is_src); + + /*! + * Enables export of perf. counters to ControlPort on all blocks in + * the flowgraph. + */ + void enable_pc_rpc(); + + private: + flat_flowgraph(); + + block_detail_sptr allocate_block_detail(basic_block_sptr block); + buffer_sptr allocate_buffer(basic_block_sptr block, int port); + void connect_block_inputs(basic_block_sptr block); + + /* When reusing a flowgraph's blocks, this call makes sure all of + * the buffer's are aligned at the machine's alignment boundary + * and tells the blocks that they are aligned. + * + * Called from both setup_connections and merge_connections for + * start and restarts. + */ + void setup_buffer_alignment(block_sptr block); + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_RUNTIME_FLAT_FLOWGRAPH_H */ diff --git a/gnuradio-runtime/lib/flowgraph.cc b/gnuradio-runtime/lib/flowgraph.cc new file mode 100644 index 0000000000..0b0285088b --- /dev/null +++ b/gnuradio-runtime/lib/flowgraph.cc @@ -0,0 +1,519 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2011,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/flowgraph.h> +#include <stdexcept> +#include <sstream> +#include <iterator> + +namespace gr { + +#define FLOWGRAPH_DEBUG 0 + + edge::~edge() + { + } + + flowgraph_sptr make_flowgraph() + { + return flowgraph_sptr(new flowgraph()); + } + + flowgraph::flowgraph() + { + } + + flowgraph::~flowgraph() + { + } + + template<class T> + static + std::vector<T> + unique_vector(std::vector<T> v) + { + std::vector<T> result; + std::insert_iterator<std::vector<T> > inserter(result, result.begin()); + + sort(v.begin(), v.end()); + unique_copy(v.begin(), v.end(), inserter); + return result; + } + + void + flowgraph::connect(const endpoint &src, const endpoint &dst) + { + check_valid_port(src.block()->output_signature(), src.port()); + check_valid_port(dst.block()->input_signature(), dst.port()); + check_dst_not_used(dst); + check_type_match(src, dst); + + // All ist klar, Herr Kommisar + d_edges.push_back(edge(src,dst)); + } + + void + flowgraph::disconnect(const endpoint &src, const endpoint &dst) + { + for(edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + if(src == p->src() && dst == p->dst()) { + d_edges.erase(p); + return; + } + } + + std::stringstream msg; + msg << "cannot disconnect edge " << edge(src, dst) << ", not found"; + throw std::invalid_argument(msg.str()); + } + + void + flowgraph::validate() + { + d_blocks = calc_used_blocks(); + + for(basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { + std::vector<int> used_ports; + int ninputs, noutputs; + + if(FLOWGRAPH_DEBUG) + std::cout << "Validating block: " << (*p) << std::endl; + + used_ports = calc_used_ports(*p, true); // inputs + ninputs = used_ports.size(); + check_contiguity(*p, used_ports, true); // inputs + + used_ports = calc_used_ports(*p, false); // outputs + noutputs = used_ports.size(); + check_contiguity(*p, used_ports, false); // outputs + + if(!((*p)->check_topology(ninputs, noutputs))) { + std::stringstream msg; + msg << "check topology failed on " << (*p) + << " using ninputs=" << ninputs + << ", noutputs=" << noutputs; + throw std::runtime_error(msg.str()); + } + } + } + + void + flowgraph::clear() + { + // Boost shared pointers will deallocate as needed + d_blocks.clear(); + d_edges.clear(); + } + + void + flowgraph::check_valid_port(gr::io_signature::sptr sig, int port) + { + std::stringstream msg; + + if(port < 0) { + msg << "negative port number " << port << " is invalid"; + throw std::invalid_argument(msg.str()); + } + + int max = sig->max_streams(); + if(max != io_signature::IO_INFINITE && port >= max) { + msg << "port number " << port << " exceeds max of "; + if(max == 0) + msg << "(none)"; + else + msg << max-1; + throw std::invalid_argument(msg.str()); + } + } + + void + flowgraph::check_valid_port(const msg_endpoint &e) + { + if(FLOWGRAPH_DEBUG) + std::cout << "check_valid_port( " << e.block() << ", " << e.port() << ")\n"; + + if(!e.block()->has_msg_port(e.port())) + throw std::invalid_argument("invalid msg port in connect() or disconnect()"); + } + + void + flowgraph::check_dst_not_used(const endpoint &dst) + { + // A destination is in use if it is already on the edge list + for(edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if(p->dst() == dst) { + std::stringstream msg; + msg << "destination already in use by edge " << (*p); + throw std::invalid_argument(msg.str()); + } + } + + void + flowgraph::check_type_match(const endpoint &src, const endpoint &dst) + { + int src_size = src.block()->output_signature()->sizeof_stream_item(src.port()); + int dst_size = dst.block()->input_signature()->sizeof_stream_item(dst.port()); + + if(src_size != dst_size) { + std::stringstream msg; + msg << "itemsize mismatch: " << src << " using " << src_size + << ", " << dst << " using " << dst_size; + throw std::invalid_argument(msg.str()); + } + } + + basic_block_vector_t + flowgraph::calc_used_blocks() + { + basic_block_vector_t tmp; + + // make sure free standing message blocks are included + for(msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) { + //for now only blocks receiving messages get a thread context - uncomment to allow senders to also obtain one + // tmp.push_back(p->src().block()); + tmp.push_back(p->dst().block()); + } + + // Collect all blocks in the edge list + for(edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + tmp.push_back(p->src().block()); + tmp.push_back(p->dst().block()); + } + + return unique_vector<basic_block_sptr>(tmp); + } + + std::vector<int> + flowgraph::calc_used_ports(basic_block_sptr block, bool check_inputs) + { + std::vector<int> tmp; + + // Collect all seen ports + edge_vector_t edges = calc_connections(block, check_inputs); + for(edge_viter_t p = edges.begin(); p != edges.end(); p++) { + if(check_inputs == true) + tmp.push_back(p->dst().port()); + else + tmp.push_back(p->src().port()); + } + + return unique_vector<int>(tmp); + } + + edge_vector_t + flowgraph::calc_connections(basic_block_sptr block, bool check_inputs) + { + edge_vector_t result; + + for(edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + if(check_inputs) { + if(p->dst().block() == block) + result.push_back(*p); + } + else { + if(p->src().block() == block) + result.push_back(*p); + } + } + + return result; // assumes no duplicates + } + + void + flowgraph::check_contiguity(basic_block_sptr block, + const std::vector<int> &used_ports, + bool check_inputs) + { + std::stringstream msg; + + gr::io_signature::sptr sig = + check_inputs ? block->input_signature() : block->output_signature(); + + int nports = used_ports.size(); + int min_ports = sig->min_streams(); + int max_ports = sig->max_streams(); + + if(nports == 0 && min_ports == 0) + return; + + if(nports < min_ports) { + msg << block << ": insufficient connected " + << (check_inputs ? "input ports " : "output ports ") + << "(" << min_ports << " needed, " << nports << " connected)"; + throw std::runtime_error(msg.str()); + } + + if(nports > max_ports && max_ports != io_signature::IO_INFINITE) { + msg << block << ": too many connected " + << (check_inputs ? "input ports " : "output ports ") + << "(" << max_ports << " allowed, " << nports << " connected)"; + throw std::runtime_error(msg.str()); + } + + if(used_ports[nports-1]+1 != nports) { + for(int i = 0; i < nports; i++) { + if(used_ports[i] != i) { + msg << block << ": missing connection " + << (check_inputs ? "to input port " : "from output port ") + << i; + throw std::runtime_error(msg.str()); + } + } + } + } + + basic_block_vector_t + flowgraph::calc_downstream_blocks(basic_block_sptr block, int port) + { + basic_block_vector_t tmp; + + for(edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if(p->src() == endpoint(block, port)) + tmp.push_back(p->dst().block()); + + return unique_vector<basic_block_sptr>(tmp); + } + + basic_block_vector_t + flowgraph::calc_downstream_blocks(basic_block_sptr block) + { + basic_block_vector_t tmp; + + for(edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if(p->src().block() == block) + tmp.push_back(p->dst().block()); + + return unique_vector<basic_block_sptr>(tmp); + } + + edge_vector_t + flowgraph::calc_upstream_edges(basic_block_sptr block) + { + edge_vector_t result; + + for(edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if(p->dst().block() == block) + result.push_back(*p); + + return result; // Assume no duplicates + } + + bool + flowgraph::has_block_p(basic_block_sptr block) + { + basic_block_viter_t result; + result = std::find(d_blocks.begin(), d_blocks.end(), block); + return (result != d_blocks.end()); + } + + edge + flowgraph::calc_upstream_edge(basic_block_sptr block, int port) + { + edge result; + + for(edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + if(p->dst() == endpoint(block, port)) { + result = (*p); + break; + } + } + + return result; + } + + std::vector<basic_block_vector_t> + flowgraph::partition() + { + std::vector<basic_block_vector_t> result; + basic_block_vector_t blocks = calc_used_blocks(); + basic_block_vector_t graph; + + while(blocks.size() > 0) { + graph = calc_reachable_blocks(blocks[0], blocks); + assert(graph.size()); + result.push_back(topological_sort(graph)); + + for(basic_block_viter_t p = graph.begin(); p != graph.end(); p++) + blocks.erase(find(blocks.begin(), blocks.end(), *p)); + } + + return result; + } + + basic_block_vector_t + flowgraph::calc_reachable_blocks(basic_block_sptr block, basic_block_vector_t &blocks) + { + basic_block_vector_t result; + + // Mark all blocks as unvisited + for(basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) + (*p)->set_color(basic_block::WHITE); + + // Recursively mark all reachable blocks + reachable_dfs_visit(block, blocks); + + // Collect all the blocks that have been visited + for(basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) + if((*p)->color() == basic_block::BLACK) + result.push_back(*p); + + return result; + } + + // Recursively mark all reachable blocks from given block and block list + void + flowgraph::reachable_dfs_visit(basic_block_sptr block, basic_block_vector_t &blocks) + { + // Mark the current one as visited + block->set_color(basic_block::BLACK); + + // Recurse into adjacent vertices + basic_block_vector_t adjacent = calc_adjacent_blocks(block, blocks); + + for(basic_block_viter_t p = adjacent.begin(); p != adjacent.end(); p++) + if((*p)->color() == basic_block::WHITE) + reachable_dfs_visit(*p, blocks); + } + + // Return a list of block adjacent to a given block along any edge + basic_block_vector_t + flowgraph::calc_adjacent_blocks(basic_block_sptr block, basic_block_vector_t &blocks) + { + basic_block_vector_t tmp; + + // Find any blocks that are inputs or outputs + for(edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + if(p->src().block() == block) + tmp.push_back(p->dst().block()); + if(p->dst().block() == block) + tmp.push_back(p->src().block()); + } + + return unique_vector<basic_block_sptr>(tmp); + } + + basic_block_vector_t + flowgraph::topological_sort(basic_block_vector_t &blocks) + { + basic_block_vector_t tmp; + basic_block_vector_t result; + tmp = sort_sources_first(blocks); + + // Start 'em all white + for(basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++) + (*p)->set_color(basic_block::WHITE); + + for(basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++) { + if((*p)->color() == basic_block::WHITE) + topological_dfs_visit(*p, result); + } + + reverse(result.begin(), result.end()); + return result; + } + + basic_block_vector_t + flowgraph::sort_sources_first(basic_block_vector_t &blocks) + { + basic_block_vector_t sources, nonsources, result; + + for(basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { + if(source_p(*p)) + sources.push_back(*p); + else + nonsources.push_back(*p); + } + + for(basic_block_viter_t p = sources.begin(); p != sources.end(); p++) + result.push_back(*p); + + for(basic_block_viter_t p = nonsources.begin(); p != nonsources.end(); p++) + result.push_back(*p); + + return result; + } + + bool + flowgraph::source_p(basic_block_sptr block) + { + return (calc_upstream_edges(block).size() == 0); + } + + void + flowgraph::topological_dfs_visit(basic_block_sptr block, basic_block_vector_t &output) + { + block->set_color(basic_block::GREY); + basic_block_vector_t blocks(calc_downstream_blocks(block)); + + for(basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { + switch((*p)->color()) { + case basic_block::WHITE: + topological_dfs_visit(*p, output); + break; + + case basic_block::GREY: + throw std::runtime_error("flow graph has loops!"); + + case basic_block::BLACK: + continue; + + default: + throw std::runtime_error("invalid color on block!"); + } + } + + block->set_color(basic_block::BLACK); + output.push_back(block); + } + + void + flowgraph::connect(const msg_endpoint &src, const msg_endpoint &dst) + { + check_valid_port(src); + check_valid_port(dst); + for(msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) { + if(p->src() == src && p->dst() == dst){ + throw std::runtime_error("connect called on already connected edge!"); + } + } + d_msg_edges.push_back(msg_edge(src,dst)); + } + + void + flowgraph::disconnect(const msg_endpoint &src, const msg_endpoint &dst) + { + check_valid_port(src); + check_valid_port(dst); + for(msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) { + if(p->src() == src && p->dst() == dst){ + d_msg_edges.erase(p); + return; + } + } + throw std::runtime_error("disconnect called on non-connected edge!"); + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/gr_basic_block.cc b/gnuradio-runtime/lib/gr_basic_block.cc deleted file mode 100644 index 83f6c07c87..0000000000 --- a/gnuradio-runtime/lib/gr_basic_block.cc +++ /dev/null @@ -1,226 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2012 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_basic_block.h> -#include <gr_block_registry.h> -#include <stdexcept> -#include <sstream> -#include <iostream> - -static long s_next_id = 0; -static long s_ncurrently_allocated = 0; - -long -gr_basic_block_ncurrently_allocated() -{ - return s_ncurrently_allocated; -} - -gr_basic_block::gr_basic_block(const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature) - : d_name(name), - d_input_signature(input_signature), - d_output_signature(output_signature), - d_unique_id(s_next_id++), - d_symbolic_id(global_block_registry.block_register(this)), - d_symbol_name(global_block_registry.register_symbolic_name(this)), - d_color(WHITE), - d_rpc_set(false), - message_subscribers(pmt::make_dict()) -{ - s_ncurrently_allocated++; -} - -gr_basic_block::~gr_basic_block() -{ - s_ncurrently_allocated--; - global_block_registry.block_unregister(this); -} - -gr_basic_block_sptr -gr_basic_block::to_basic_block() -{ - return shared_from_this(); -} - -void -gr_basic_block::set_block_alias(std::string name) -{ - global_block_registry.register_symbolic_name(this, name); -} - -// ** Message passing interface ** - -// - register a new input message port -void -gr_basic_block::message_port_register_in(pmt::pmt_t port_id) -{ - if(!pmt::is_symbol(port_id)) { - throw std::runtime_error("message_port_register_in: bad port id"); - } - msg_queue[port_id] = msg_queue_t(); - msg_queue_ready[port_id] = boost::shared_ptr<boost::condition_variable>(new boost::condition_variable()); -} - -pmt::pmt_t -gr_basic_block::message_ports_in() -{ - pmt::pmt_t port_names = pmt::make_vector(msg_queue.size(), pmt::PMT_NIL); - msg_queue_map_itr itr = msg_queue.begin(); - for(size_t i = 0; i < msg_queue.size(); i++) { - pmt::vector_set(port_names, i, (*itr).first); - itr++; - } - return port_names; -} - -// - register a new output message port -void -gr_basic_block::message_port_register_out(pmt::pmt_t port_id) -{ - if(!pmt::is_symbol(port_id)) { - throw std::runtime_error("message_port_register_out: bad port id"); - } - if(pmt::dict_has_key(message_subscribers, port_id)) { - throw std::runtime_error("message_port_register_out: port already in use"); - } - message_subscribers = pmt::dict_add(message_subscribers, port_id, pmt::PMT_NIL); -} - -pmt::pmt_t -gr_basic_block::message_ports_out() -{ - size_t len = pmt::length(message_subscribers); - pmt::pmt_t port_names = pmt::make_vector(len, pmt::PMT_NIL); - pmt::pmt_t keys = pmt::dict_keys(message_subscribers); - for(size_t i = 0; i < len; i++) { - pmt::vector_set(port_names, i, pmt::nth(i, keys)); - } - return port_names; -} - -// - publish a message on a message port -void gr_basic_block::message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg) -{ - if(!pmt::dict_has_key(message_subscribers, port_id)) { - throw std::runtime_error("port does not exist"); - } - - pmt::pmt_t currlist = pmt::dict_ref(message_subscribers, port_id, pmt::PMT_NIL); - // iterate through subscribers on port - while(pmt::is_pair(currlist)) { - pmt::pmt_t target = pmt::car(currlist); - - pmt::pmt_t block = pmt::car(target); - pmt::pmt_t port = pmt::cdr(target); - - currlist = pmt::cdr(currlist); - gr_basic_block_sptr blk = global_block_registry.block_lookup(block); - //blk->post(msg); - blk->post(port, msg); - } -} - -// - subscribe to a message port -void -gr_basic_block::message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target){ - if(!pmt::dict_has_key(message_subscribers, port_id)){ - std::stringstream ss; - ss << "Port does not exist: \"" << pmt::write_string(port_id) << "\" on block: " << pmt::write_string(target) << std::endl; - throw std::runtime_error(ss.str()); - } - pmt::pmt_t currlist = pmt::dict_ref(message_subscribers,port_id,pmt::PMT_NIL); - - // ignore re-adds of the same target - if(!pmt::list_has(currlist, target)) - message_subscribers = pmt::dict_add(message_subscribers,port_id,pmt::list_add(currlist,target)); -} - -void -gr_basic_block::message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target){ - if(!pmt::dict_has_key(message_subscribers, port_id)){ - std::stringstream ss; - ss << "Port does not exist: \"" << pmt::write_string(port_id) << "\" on block: " << pmt::write_string(target) << std::endl; - throw std::runtime_error(ss.str()); - } - - // ignore unsubs of unknown targets - pmt::pmt_t currlist = pmt::dict_ref(message_subscribers,port_id,pmt::PMT_NIL); - message_subscribers = pmt::dict_add(message_subscribers,port_id,pmt::list_rm(currlist,target)); -} - -void -gr_basic_block::_post(pmt::pmt_t which_port, pmt::pmt_t msg) -{ - insert_tail(which_port, msg); -} - -void -gr_basic_block::insert_tail(pmt::pmt_t which_port, pmt::pmt_t msg) -{ - gr::thread::scoped_lock guard(mutex); - - if( (msg_queue.find(which_port) == msg_queue.end()) || (msg_queue_ready.find(which_port) == msg_queue_ready.end())){ - std::cout << "target port = " << pmt::symbol_to_string(which_port) << std::endl; - throw std::runtime_error("attempted to insert_tail on invalid queue!"); - } - - msg_queue[which_port].push_back(msg); - msg_queue_ready[which_port]->notify_one(); - - // wake up thread if BLKD_IN or BLKD_OUT - global_block_registry.notify_blk(alias()); -} - -pmt::pmt_t -gr_basic_block::delete_head_nowait(pmt::pmt_t which_port) -{ - gr::thread::scoped_lock guard(mutex); - - if (empty_p(which_port)){ - return pmt::pmt_t(); - } - - pmt::pmt_t m(msg_queue[which_port].front()); - msg_queue[which_port].pop_front(); - - return m; -} - -pmt::pmt_t -gr_basic_block::delete_head_blocking(pmt::pmt_t which_port) -{ - gr::thread::scoped_lock guard(mutex); - - while (empty_p(which_port)){ - msg_queue_ready[which_port]->wait(guard); - } - - pmt::pmt_t m(msg_queue[which_port].front()); - msg_queue[which_port].pop_front(); - return m; -} diff --git a/gnuradio-runtime/lib/gr_block.cc b/gnuradio-runtime/lib/gr_block.cc deleted file mode 100644 index 2830a999ea..0000000000 --- a/gnuradio-runtime/lib/gr_block.cc +++ /dev/null @@ -1,687 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2009,2010,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_block.h> -#include <gr_block_detail.h> -#include <stdexcept> -#include <iostream> -#include <gr_block_registry.h> -#include <gr_prefs.h> - -gr_block::gr_block (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature) - : gr_basic_block(name, input_signature, output_signature), - d_output_multiple (1), - d_output_multiple_set(false), - d_unaligned(0), - d_is_unaligned(false), - d_relative_rate (1.0), - d_history(1), - d_fixed_rate(false), - d_max_noutput_items_set(false), - d_max_noutput_items(0), - d_min_noutput_items(0), - d_tag_propagation_policy(TPP_ALL_TO_ALL), - d_pc_rpc_set(false), - d_max_output_buffer(std::max(output_signature->max_streams(),1), -1), - d_min_output_buffer(std::max(output_signature->max_streams(),1), -1) -{ - global_block_registry.register_primitive(alias(), this); - -#ifdef ENABLE_GR_LOG -#ifdef HAVE_LOG4CPP - gr_prefs *p = gr_prefs::singleton(); - std::string config_file = p->get_string("LOG", "log_config", ""); - std::string log_level = p->get_string("LOG", "log_level", "off"); - std::string log_file = p->get_string("LOG", "log_file", ""); - std::string debug_level = p->get_string("LOG", "debug_level", "off"); - std::string debug_file = p->get_string("LOG", "debug_file", ""); - - GR_CONFIG_LOGGER(config_file); - - GR_LOG_GETLOGGER(LOG, "gr_log." + alias()); - GR_LOG_SET_LEVEL(LOG, log_level); - if(log_file.size() > 0) { - if(log_file == "stdout") { - GR_LOG_ADD_CONSOLE_APPENDER(LOG, "cout","gr::log :%p: %c{1} - %m%n"); - } - else if(log_file == "stderr") { - GR_LOG_ADD_CONSOLE_APPENDER(LOG, "cerr","gr::log :%p: %c{1} - %m%n"); - } - else { - GR_LOG_ADD_FILE_APPENDER(LOG, log_file , true,"%r :%p: %c{1} - %m%n"); - } - } - d_logger = LOG; - - GR_LOG_GETLOGGER(DLOG, "gr_log_debug." + alias()); - GR_LOG_SET_LEVEL(DLOG, debug_level); - if(debug_file.size() > 0) { - if(debug_file == "stdout") { - GR_LOG_ADD_CONSOLE_APPENDER(DLOG, "cout","gr::debug :%p: %c{1} - %m%n"); - } - else if(debug_file == "stderr") { - GR_LOG_ADD_CONSOLE_APPENDER(DLOG, "cerr", "gr::debug :%p: %c{1} - %m%n"); - } - else { - GR_LOG_ADD_FILE_APPENDER(DLOG, debug_file, true, "%r :%p: %c{1} - %m%n"); - } - } - d_debug_logger = DLOG; -#endif /* HAVE_LOG4CPP */ -#else /* ENABLE_GR_LOG */ - d_logger = NULL; - d_debug_logger = NULL; -#endif /* ENABLE_GR_LOG */ -} - -gr_block::~gr_block () -{ - global_block_registry.unregister_primitive(alias()); -} - -// stub implementation: 1:1 - -void -gr_block::forecast (int noutput_items, gr_vector_int &ninput_items_required) -{ - unsigned ninputs = ninput_items_required.size (); - for (unsigned i = 0; i < ninputs; i++) - ninput_items_required[i] = noutput_items + history() - 1; -} - -// default implementation - -bool -gr_block::start() -{ - return true; -} - -bool -gr_block::stop() -{ - return true; -} - -void -gr_block::set_output_multiple (int multiple) -{ - if (multiple < 1) - throw std::invalid_argument ("gr_block::set_output_multiple"); - - d_output_multiple_set = true; - d_output_multiple = multiple; -} - -void -gr_block::set_alignment (int multiple) -{ - if (multiple < 1) - throw std::invalid_argument ("gr_block::set_alignment_multiple"); - - d_output_multiple = multiple; -} - -void -gr_block::set_unaligned (int na) -{ - // unaligned value must be less than 0 and it doesn't make sense - // that it's larger than the alignment value. - if ((na < 0) || (na > d_output_multiple)) - throw std::invalid_argument ("gr_block::set_unaligned"); - - d_unaligned = na; -} - -void -gr_block::set_is_unaligned (bool u) -{ - d_is_unaligned = u; -} - -void -gr_block::set_relative_rate (double relative_rate) -{ - if (relative_rate < 0.0) - throw std::invalid_argument ("gr_block::set_relative_rate"); - - d_relative_rate = relative_rate; -} - - -void -gr_block::consume (int which_input, int how_many_items) -{ - d_detail->consume (which_input, how_many_items); -} - -void -gr_block::consume_each (int how_many_items) -{ - d_detail->consume_each (how_many_items); -} - -void -gr_block::produce (int which_output, int how_many_items) -{ - d_detail->produce (which_output, how_many_items); -} - -int -gr_block::fixed_rate_ninput_to_noutput(int ninput) -{ - throw std::runtime_error("Unimplemented"); -} - -int -gr_block::fixed_rate_noutput_to_ninput(int noutput) -{ - throw std::runtime_error("Unimplemented"); -} - -uint64_t -gr_block::nitems_read(unsigned int which_input) -{ - if(d_detail) { - return d_detail->nitems_read(which_input); - } - else { - //throw std::runtime_error("No block_detail associated with block yet"); - return 0; - } -} - -uint64_t -gr_block::nitems_written(unsigned int which_output) -{ - if(d_detail) { - return d_detail->nitems_written(which_output); - } - else { - //throw std::runtime_error("No block_detail associated with block yet"); - return 0; - } -} - -void -gr_block::add_item_tag(unsigned int which_output, - const gr_tag_t &tag) -{ - d_detail->add_item_tag(which_output, tag); -} - -void -gr_block::remove_item_tag(unsigned int which_input, - const gr_tag_t &tag) -{ - d_detail->remove_item_tag(which_input, tag); -} - -void -gr_block::get_tags_in_range(std::vector<gr_tag_t> &v, - unsigned int which_output, - uint64_t start, uint64_t end) -{ - d_detail->get_tags_in_range(v, which_output, start, end); -} - -void -gr_block::get_tags_in_range(std::vector<gr_tag_t> &v, - unsigned int which_output, - uint64_t start, uint64_t end, - const pmt::pmt_t &key) -{ - d_detail->get_tags_in_range(v, which_output, start, end, key); -} - -gr_block::tag_propagation_policy_t -gr_block::tag_propagation_policy() -{ - return d_tag_propagation_policy; -} - -void -gr_block::set_tag_propagation_policy(tag_propagation_policy_t p) -{ - d_tag_propagation_policy = p; -} - - -int -gr_block::max_noutput_items() -{ - return d_max_noutput_items; -} - -void -gr_block::set_max_noutput_items(int m) -{ - if(m <= 0) - throw std::runtime_error("gr_block::set_max_noutput_items: value for max_noutput_items must be greater than 0.\n"); - - d_max_noutput_items = m; - d_max_noutput_items_set = true; -} - -void -gr_block::unset_max_noutput_items() -{ - d_max_noutput_items_set = false; -} - -bool -gr_block::is_set_max_noutput_items() -{ - return d_max_noutput_items_set; -} - -void -gr_block::set_processor_affinity(const std::vector<int> &mask) -{ - d_affinity = mask; - if(d_detail) { - d_detail->set_processor_affinity(d_affinity); - } -} - -void -gr_block::unset_processor_affinity() -{ - d_affinity.clear(); - if(d_detail) { - d_detail->unset_processor_affinity(); - } -} - -float -gr_block::pc_noutput_items() -{ - if(d_detail) { - return d_detail->pc_noutput_items(); - } - else { - return 0; - } -} - -float -gr_block::pc_noutput_items_avg() -{ - if(d_detail) { - return d_detail->pc_noutput_items_avg(); - } - else { - return 0; - } -} - -float -gr_block::pc_noutput_items_var() -{ - if(d_detail) { - return d_detail->pc_noutput_items_var(); - } - else { - return 0; - } -} - -float -gr_block::pc_nproduced() -{ - if(d_detail) { - return d_detail->pc_nproduced(); - } - else { - return 0; - } -} - -float -gr_block::pc_nproduced_avg() -{ - if(d_detail) { - return d_detail->pc_nproduced_avg(); - } - else { - return 0; - } -} - -float -gr_block::pc_nproduced_var() -{ - if(d_detail) { - return d_detail->pc_nproduced_var(); - } - else { - return 0; - } -} - -float -gr_block::pc_input_buffers_full(int which) -{ - if(d_detail) { - return d_detail->pc_input_buffers_full(static_cast<size_t>(which)); - } - else { - return 0; - } -} - -float -gr_block::pc_input_buffers_full_avg(int which) -{ - if(d_detail) { - return d_detail->pc_input_buffers_full_avg(static_cast<size_t>(which)); - } - else { - return 0; - } -} - -float -gr_block::pc_input_buffers_full_var(int which) -{ - if(d_detail) { - return d_detail->pc_input_buffers_full_var(static_cast<size_t>(which)); - } - else { - return 0; - } -} - -std::vector<float> -gr_block::pc_input_buffers_full() -{ - if(d_detail) { - return d_detail->pc_input_buffers_full(); - } - else { - return std::vector<float>(1,0); - } -} - -std::vector<float> -gr_block::pc_input_buffers_full_avg() -{ - if(d_detail) { - return d_detail->pc_input_buffers_full_avg(); - } - else { - return std::vector<float>(1,0); - } -} - -std::vector<float> -gr_block::pc_input_buffers_full_var() -{ - if(d_detail) { - return d_detail->pc_input_buffers_full_var(); - } - else { - return std::vector<float>(1,0); - } -} - -float -gr_block::pc_output_buffers_full(int which) -{ - if(d_detail) { - return d_detail->pc_output_buffers_full(static_cast<size_t>(which)); - } - else { - return 0; - } -} - -float -gr_block::pc_output_buffers_full_avg(int which) -{ - if(d_detail) { - return d_detail->pc_output_buffers_full_avg(static_cast<size_t>(which)); - } - else { - return 0; - } -} - -float -gr_block::pc_output_buffers_full_var(int which) -{ - if(d_detail) { - return d_detail->pc_output_buffers_full_var(static_cast<size_t>(which)); - } - else { - return 0; - } -} - -std::vector<float> -gr_block::pc_output_buffers_full() -{ - if(d_detail) { - return d_detail->pc_output_buffers_full(); - } - else { - return std::vector<float>(1,0); - } -} - -std::vector<float> -gr_block::pc_output_buffers_full_avg() -{ - if(d_detail) { - return d_detail->pc_output_buffers_full_avg(); - } - else { - return std::vector<float>(1,0); - } -} - -std::vector<float> -gr_block::pc_output_buffers_full_var() -{ - if(d_detail) { - return d_detail->pc_output_buffers_full_var(); - } - else { - return std::vector<float>(1,0); - } -} - -float -gr_block::pc_work_time() -{ - if(d_detail) { - return d_detail->pc_work_time(); - } - else { - return 0; - } -} - -float -gr_block::pc_work_time_avg() -{ - if(d_detail) { - return d_detail->pc_work_time_avg(); - } - else { - return 0; - } -} - -float -gr_block::pc_work_time_var() -{ - if(d_detail) { - return d_detail->pc_work_time_var(); - } - else { - return 0; - } -} - -void -gr_block::reset_perf_counters() -{ - if(d_detail) { - d_detail->reset_perf_counters(); - } -} - -void -gr_block::setup_pc_rpc() -{ - d_pc_rpc_set = true; -#ifdef GR_CTRLPORT - d_rpc_vars.push_back( - rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>( - alias(), "noutput_items", &gr_block::pc_noutput_items, - pmt::mp(0), pmt::mp(32768), pmt::mp(0), - "", "noutput items", RPC_PRIVLVL_MIN, - DISPTIME | DISPOPTSTRIP))); - - d_rpc_vars.push_back( - rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>( - alias(), "avg noutput_items", &gr_block::pc_noutput_items_avg, - pmt::mp(0), pmt::mp(32768), pmt::mp(0), - "", "Average noutput items", RPC_PRIVLVL_MIN, - DISPTIME | DISPOPTSTRIP))); - - d_rpc_vars.push_back( - rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>( - alias(), "var noutput_items", &gr_block::pc_noutput_items_var, - pmt::mp(0), pmt::mp(32768), pmt::mp(0), - "", "Var. noutput items", RPC_PRIVLVL_MIN, - DISPTIME | DISPOPTSTRIP))); - - d_rpc_vars.push_back( - rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>( - alias(), "nproduced", &gr_block::pc_nproduced, - pmt::mp(0), pmt::mp(32768), pmt::mp(0), - "", "items produced", RPC_PRIVLVL_MIN, - DISPTIME | DISPOPTSTRIP))); - - d_rpc_vars.push_back( - rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>( - alias(), "avg nproduced", &gr_block::pc_nproduced_avg, - pmt::mp(0), pmt::mp(32768), pmt::mp(0), - "", "Average items produced", RPC_PRIVLVL_MIN, - DISPTIME | DISPOPTSTRIP))); - - d_rpc_vars.push_back( - rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>( - alias(), "var nproduced", &gr_block::pc_nproduced_var, - pmt::mp(0), pmt::mp(32768), pmt::mp(0), - "", "Var. items produced", RPC_PRIVLVL_MIN, - DISPTIME | DISPOPTSTRIP))); - - d_rpc_vars.push_back( - rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>( - alias(), "work time", &gr_block::pc_work_time, - pmt::mp(0), pmt::mp(1e9), pmt::mp(0), - "", "clock cycles in call to work", RPC_PRIVLVL_MIN, - DISPTIME | DISPOPTSTRIP))); - - d_rpc_vars.push_back( - rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>( - alias(), "avg work time", &gr_block::pc_work_time_avg, - pmt::mp(0), pmt::mp(1e9), pmt::mp(0), - "", "Average clock cycles in call to work", RPC_PRIVLVL_MIN, - DISPTIME | DISPOPTSTRIP))); - - d_rpc_vars.push_back( - rpcbasic_sptr(new rpcbasic_register_get<gr_block, float>( - alias(), "var work time", &gr_block::pc_work_time_var, - pmt::mp(0), pmt::mp(1e9), pmt::mp(0), - "", "Var. clock cycles in call to work", RPC_PRIVLVL_MIN, - DISPTIME | DISPOPTSTRIP))); - - d_rpc_vars.push_back( - rpcbasic_sptr(new rpcbasic_register_get<gr_block, std::vector<float> >( - alias(), "input \% full", &gr_block::pc_input_buffers_full, - pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0), - "", "how full input buffers are", RPC_PRIVLVL_MIN, - DISPTIME | DISPOPTSTRIP))); - - d_rpc_vars.push_back( - rpcbasic_sptr(new rpcbasic_register_get<gr_block, std::vector<float> >( - alias(), "avg input \% full", &gr_block::pc_input_buffers_full_avg, - pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0), - "", "Average of how full input buffers are", RPC_PRIVLVL_MIN, - DISPTIME | DISPOPTSTRIP))); - - d_rpc_vars.push_back( - rpcbasic_sptr(new rpcbasic_register_get<gr_block, std::vector<float> >( - alias(), "var input \% full", &gr_block::pc_input_buffers_full_var, - pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0), - "", "Var. of how full input buffers are", RPC_PRIVLVL_MIN, - DISPTIME | DISPOPTSTRIP))); - - d_rpc_vars.push_back( - rpcbasic_sptr(new rpcbasic_register_get<gr_block, std::vector<float> >( - alias(), "output \% full", &gr_block::pc_output_buffers_full, - pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0), - "", "how full output buffers are", RPC_PRIVLVL_MIN, - DISPTIME | DISPOPTSTRIP))); - - d_rpc_vars.push_back( - rpcbasic_sptr(new rpcbasic_register_get<gr_block, std::vector<float> >( - alias(), "avg output \% full", &gr_block::pc_output_buffers_full_avg, - pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0), - "", "Average of how full output buffers are", RPC_PRIVLVL_MIN, - DISPTIME | DISPOPTSTRIP))); - - d_rpc_vars.push_back( - rpcbasic_sptr(new rpcbasic_register_get<gr_block, std::vector<float> >( - alias(), "var output \% full", &gr_block::pc_output_buffers_full_var, - pmt::make_c32vector(0,0), pmt::make_c32vector(0,1), pmt::make_c32vector(0,0), - "", "Var. of how full output buffers are", RPC_PRIVLVL_MIN, - DISPTIME | DISPOPTSTRIP))); -#endif /* GR_CTRLPORT */ -} - -std::ostream& -operator << (std::ostream& os, const gr_block *m) -{ - os << "<gr_block " << m->name() << " (" << m->unique_id() << ")>"; - return os; -} - -int -gr_block::general_work(int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - throw std::runtime_error("gr_block::general_work() not implemented"); - return 0; -} diff --git a/gnuradio-runtime/lib/gr_block_detail.cc b/gnuradio-runtime/lib/gr_block_detail.cc deleted file mode 100644 index 7098113301..0000000000 --- a/gnuradio-runtime/lib/gr_block_detail.cc +++ /dev/null @@ -1,473 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2009,2010,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_block_detail.h> -#include <gr_buffer.h> -#include <iostream> - -static long s_ncurrently_allocated = 0; - -long -gr_block_detail_ncurrently_allocated () -{ - return s_ncurrently_allocated; -} - -gr_block_detail::gr_block_detail (unsigned int ninputs, unsigned int noutputs) - : d_produce_or(0), - d_ninputs (ninputs), d_noutputs (noutputs), - d_input (ninputs), d_output (noutputs), - d_done (false), - d_ins_noutput_items(0), - d_avg_noutput_items(0), - d_var_noutput_items(0), - d_ins_nproduced(0), - d_avg_nproduced(0), - d_var_nproduced(0), - d_ins_input_buffers_full(ninputs, 0), - d_avg_input_buffers_full(ninputs, 0), - d_var_input_buffers_full(ninputs, 0), - d_ins_output_buffers_full(noutputs, 0), - d_avg_output_buffers_full(noutputs, 0), - d_var_output_buffers_full(noutputs, 0), - d_ins_work_time(0), - d_avg_work_time(0), - d_var_work_time(0), - d_pc_counter(0) -{ - s_ncurrently_allocated++; -} - -gr_block_detail::~gr_block_detail () -{ - // should take care of itself - s_ncurrently_allocated--; -} - -void -gr_block_detail::set_input (unsigned int which, gr_buffer_reader_sptr reader) -{ - if (which >= d_ninputs) - throw std::invalid_argument ("gr_block_detail::set_input"); - - d_input[which] = reader; -} - -void -gr_block_detail::set_output (unsigned int which, gr_buffer_sptr buffer) -{ - if (which >= d_noutputs) - throw std::invalid_argument ("gr_block_detail::set_output"); - - d_output[which] = buffer; -} - -gr_block_detail_sptr -gr_make_block_detail (unsigned int ninputs, unsigned int noutputs) -{ - return gr_block_detail_sptr (new gr_block_detail (ninputs, noutputs)); -} - -void -gr_block_detail::set_done (bool done) -{ - d_done = done; - for (unsigned int i = 0; i < d_noutputs; i++) - d_output[i]->set_done (done); - - for (unsigned int i = 0; i < d_ninputs; i++) - d_input[i]->set_done (done); -} - -void -gr_block_detail::consume (int which_input, int how_many_items) -{ - if (how_many_items > 0) { - input (which_input)->update_read_pointer (how_many_items); - } -} - - -void -gr_block_detail::consume_each (int how_many_items) -{ - if (how_many_items > 0) { - for (int i = 0; i < ninputs (); i++) { - d_input[i]->update_read_pointer (how_many_items); - } - } -} - -void -gr_block_detail::produce (int which_output, int how_many_items) -{ - if (how_many_items > 0){ - d_output[which_output]->update_write_pointer (how_many_items); - d_produce_or |= how_many_items; - } -} - -void -gr_block_detail::produce_each (int how_many_items) -{ - if (how_many_items > 0) { - for (int i = 0; i < noutputs (); i++) { - d_output[i]->update_write_pointer (how_many_items); - } - d_produce_or |= how_many_items; - } -} - - -uint64_t -gr_block_detail::nitems_read(unsigned int which_input) -{ - if(which_input >= d_ninputs) - throw std::invalid_argument ("gr_block_detail::n_input_items"); - return d_input[which_input]->nitems_read(); -} - -uint64_t -gr_block_detail::nitems_written(unsigned int which_output) -{ - if(which_output >= d_noutputs) - throw std::invalid_argument ("gr_block_detail::n_output_items"); - return d_output[which_output]->nitems_written(); -} - -void -gr_block_detail::add_item_tag(unsigned int which_output, const gr_tag_t &tag) -{ - if(!pmt::is_symbol(tag.key)) { - throw pmt::wrong_type("gr_block_detail::add_item_tag key", tag.key); - } - else { - // Add tag to gr_buffer's deque tags - d_output[which_output]->add_item_tag(tag); - } -} - -void -gr_block_detail::remove_item_tag(unsigned int which_input, const gr_tag_t &tag) -{ - if(!pmt::is_symbol(tag.key)) { - throw pmt::wrong_type("gr_block_detail::add_item_tag key", tag.key); - } - else { - // Add tag to gr_buffer's deque tags - d_input[which_input]->buffer()->remove_item_tag(tag); - } -} - -void -gr_block_detail::get_tags_in_range(std::vector<gr_tag_t> &v, - unsigned int which_input, - uint64_t abs_start, - uint64_t abs_end) -{ - // get from gr_buffer_reader's deque of tags - d_input[which_input]->get_tags_in_range(v, abs_start, abs_end); -} - -void -gr_block_detail::get_tags_in_range(std::vector<gr_tag_t> &v, - unsigned int which_input, - uint64_t abs_start, - uint64_t abs_end, - const pmt::pmt_t &key) -{ - std::vector<gr_tag_t> found_items; - - v.resize(0); - - // get from gr_buffer_reader's deque of tags - d_input[which_input]->get_tags_in_range(found_items, abs_start, abs_end); - - // Filter further by key name - pmt::pmt_t itemkey; - std::vector<gr_tag_t>::iterator itr; - for(itr = found_items.begin(); itr != found_items.end(); itr++) { - itemkey = (*itr).key; - if(pmt::eqv(key, itemkey)) { - v.push_back(*itr); - } - } -} - -void -gr_block_detail::set_processor_affinity(const std::vector<int> &mask) -{ - if(threaded) { - try { - gr::thread::thread_bind_to_processor(thread, mask); - } - catch (std::runtime_error e) { - std::cerr << "set_processor_affinity: invalid mask." << std::endl;; - } - } -} - -void -gr_block_detail::unset_processor_affinity() -{ - if(threaded) { - gr::thread::thread_unbind(thread); - } -} - -void -gr_block_detail::start_perf_counters() -{ - d_start_of_work = gr::high_res_timer_now(); -} - -void -gr_block_detail::stop_perf_counters(int noutput_items, int nproduced) -{ - d_end_of_work = gr::high_res_timer_now(); - gr::high_res_timer_type diff = d_end_of_work - d_start_of_work; - - if(d_pc_counter == 0) { - d_ins_work_time = diff; - d_avg_work_time = diff; - d_var_work_time = 0; - d_ins_nproduced = nproduced; - d_avg_nproduced = nproduced; - d_var_nproduced = 0; - d_ins_noutput_items = noutput_items; - d_avg_noutput_items = noutput_items; - d_var_noutput_items = 0; - for(size_t i=0; i < d_input.size(); i++) { - float pfull = static_cast<float>(d_input[i]->items_available()) / - static_cast<float>(d_input[i]->max_possible_items_available()); - d_ins_input_buffers_full[i] = pfull; - d_avg_input_buffers_full[i] = pfull; - d_var_input_buffers_full[i] = 0; - } - for(size_t i=0; i < d_output.size(); i++) { - float pfull = 1.0f - static_cast<float>(d_output[i]->space_available()) / - static_cast<float>(d_output[i]->bufsize()); - d_ins_output_buffers_full[i] = pfull; - d_avg_output_buffers_full[i] = pfull; - d_var_output_buffers_full[i] = 0; - } - } - else { - float d = diff - d_avg_work_time; - d_ins_work_time = diff; - d_avg_work_time = d_avg_work_time + d/d_pc_counter; - d_var_work_time = d_var_work_time + d*d; - - d = nproduced - d_avg_nproduced; - d_ins_nproduced = nproduced; - d_avg_nproduced = d_avg_nproduced + d/d_pc_counter; - d_var_nproduced = d_var_nproduced + d*d; - - d = noutput_items - d_avg_noutput_items; - d_ins_noutput_items = noutput_items; - d_avg_noutput_items = d_avg_noutput_items + d/d_pc_counter; - d_var_noutput_items = d_var_noutput_items + d*d; - - for(size_t i=0; i < d_input.size(); i++) { - float pfull = static_cast<float>(d_input[i]->items_available()) / - static_cast<float>(d_input[i]->max_possible_items_available()); - - d = pfull - d_avg_input_buffers_full[i]; - d_ins_input_buffers_full[i] = pfull; - d_avg_input_buffers_full[i] = d_avg_input_buffers_full[i] + d/d_pc_counter; - d_var_input_buffers_full[i] = d_var_input_buffers_full[i] + d*d; - } - - for(size_t i=0; i < d_output.size(); i++) { - float pfull = 1.0f - static_cast<float>(d_output[i]->space_available()) / - static_cast<float>(d_output[i]->bufsize()); - - d = pfull - d_avg_output_buffers_full[i]; - d_ins_output_buffers_full[i] = pfull; - d_avg_output_buffers_full[i] = d_avg_output_buffers_full[i] + d/d_pc_counter; - d_var_output_buffers_full[i] = d_var_output_buffers_full[i] + d*d; - } - } - - d_pc_counter++; -} - -void -gr_block_detail::reset_perf_counters() -{ - d_pc_counter = 0; -} - -float -gr_block_detail::pc_noutput_items() -{ - return d_ins_noutput_items; -} - -float -gr_block_detail::pc_nproduced() -{ - return d_ins_nproduced; -} - -float -gr_block_detail::pc_input_buffers_full(size_t which) -{ - if(which < d_ins_input_buffers_full.size()) - return d_ins_input_buffers_full[which]; - else - return 0; -} - -std::vector<float> -gr_block_detail::pc_input_buffers_full() -{ - return d_ins_input_buffers_full; -} - -float -gr_block_detail::pc_output_buffers_full(size_t which) -{ - if(which < d_ins_output_buffers_full.size()) - return d_ins_output_buffers_full[which]; - else - return 0; -} - -std::vector<float> -gr_block_detail::pc_output_buffers_full() -{ - return d_ins_output_buffers_full; -} - -float -gr_block_detail::pc_work_time() -{ - return d_ins_work_time; -} - -float -gr_block_detail::pc_noutput_items_avg() -{ - return d_avg_noutput_items; -} - -float -gr_block_detail::pc_nproduced_avg() -{ - return d_avg_nproduced; -} - -float -gr_block_detail::pc_input_buffers_full_avg(size_t which) -{ - if(which < d_avg_input_buffers_full.size()) - return d_avg_input_buffers_full[which]; - else - return 0; -} - -std::vector<float> -gr_block_detail::pc_input_buffers_full_avg() -{ - return d_avg_input_buffers_full; -} - -float -gr_block_detail::pc_output_buffers_full_avg(size_t which) -{ - if(which < d_avg_output_buffers_full.size()) - return d_avg_output_buffers_full[which]; - else - return 0; -} - -std::vector<float> -gr_block_detail::pc_output_buffers_full_avg() -{ - return d_avg_output_buffers_full; -} - -float -gr_block_detail::pc_work_time_avg() -{ - return d_avg_work_time; -} - - -float -gr_block_detail::pc_noutput_items_var() -{ - return d_var_noutput_items/(d_pc_counter-1); -} - -float -gr_block_detail::pc_nproduced_var() -{ - return d_var_nproduced/(d_pc_counter-1); -} - -float -gr_block_detail::pc_input_buffers_full_var(size_t which) -{ - if(which < d_avg_input_buffers_full.size()) - return d_var_input_buffers_full[which]/(d_pc_counter-1); - else - return 0; -} - -std::vector<float> -gr_block_detail::pc_input_buffers_full_var() -{ - std::vector<float> var(d_avg_input_buffers_full.size(), 0); - for(size_t i = 0; i < d_avg_input_buffers_full.size(); i++) - var[i] = d_avg_input_buffers_full[i]/(d_pc_counter-1); - return var; -} - -float -gr_block_detail::pc_output_buffers_full_var(size_t which) -{ - if(which < d_avg_output_buffers_full.size()) - return d_var_output_buffers_full[which]/(d_pc_counter-1); - else - return 0; -} - -std::vector<float> -gr_block_detail::pc_output_buffers_full_var() -{ - std::vector<float> var(d_avg_output_buffers_full.size(), 0); - for(size_t i = 0; i < d_avg_output_buffers_full.size(); i++) - var[i] = d_avg_output_buffers_full[i]/(d_pc_counter-1); - return var; -} - -float -gr_block_detail::pc_work_time_var() -{ - return d_var_work_time/(d_pc_counter-1); -} diff --git a/gnuradio-runtime/lib/gr_block_executor.cc b/gnuradio-runtime/lib/gr_block_executor.cc deleted file mode 100644 index cfef406412..0000000000 --- a/gnuradio-runtime/lib/gr_block_executor.cc +++ /dev/null @@ -1,487 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2008,2009,2010 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_block_executor.h> -#include <gr_block.h> -#include <gr_block_detail.h> -#include <gr_buffer.h> -#include <gr_prefs.h> -#include <boost/thread.hpp> -#include <boost/format.hpp> -#include <iostream> -#include <limits> -#include <assert.h> -#include <stdio.h> - -// must be defined to either 0 or 1 -#define ENABLE_LOGGING 0 - -#if (ENABLE_LOGGING) -#define LOG(x) do { x; } while(0) -#else -#define LOG(x) do {;} while(0) -#endif - -static int which_scheduler = 0; - -inline static unsigned int -round_up (unsigned int n, unsigned int multiple) -{ - return ((n + multiple - 1) / multiple) * multiple; -} - -inline static unsigned int -round_down (unsigned int n, unsigned int multiple) -{ - return (n / multiple) * multiple; -} - -// -// Return minimum available write space in all our downstream buffers -// or -1 if we're output blocked and the output we're blocked -// on is done. -// -static int -min_available_space (gr_block_detail *d, int output_multiple, int min_noutput_items) -{ - int min_space = std::numeric_limits<int>::max(); - if (min_noutput_items == 0) - min_noutput_items = 1; - for (int i = 0; i < d->noutputs (); i++){ - gr::thread::scoped_lock guard(*d->output(i)->mutex()); - int avail_n = round_down(d->output(i)->space_available(), output_multiple); - int best_n = round_down(d->output(i)->bufsize()/2, output_multiple); - if (best_n < min_noutput_items) - throw std::runtime_error("Buffer too small for min_noutput_items"); - int n = std::min(avail_n, best_n); - if (n < min_noutput_items){ // We're blocked on output. - if (d->output(i)->done()){ // Downstream is done, therefore we're done. - return -1; - } - return 0; - } - min_space = std::min (min_space, n); - } - return min_space; -} - -static bool -propagate_tags(gr_block::tag_propagation_policy_t policy, gr_block_detail *d, - const std::vector<uint64_t> &start_nitems_read, double rrate, - std::vector<gr_tag_t> &rtags) -{ - // Move tags downstream - // if a sink, we don't need to move downstream - if(d->sink_p()) { - return true; - } - - switch(policy) { - case gr_block::TPP_DONT: - return true; - break; - case gr_block::TPP_ALL_TO_ALL: - // every tag on every input propogates to everyone downstream - for(int i = 0; i < d->ninputs(); i++) { - d->get_tags_in_range(rtags, i, start_nitems_read[i], - d->nitems_read(i)); - - std::vector<gr_tag_t>::iterator t; - if(rrate == 1.0) { - for(t = rtags.begin(); t != rtags.end(); t++) { - for(int o = 0; o < d->noutputs(); o++) - d->output(o)->add_item_tag(*t); - } - } - else { - for(t = rtags.begin(); t != rtags.end(); t++) { - gr_tag_t new_tag = *t; - new_tag.offset *= rrate; - for(int o = 0; o < d->noutputs(); o++) - d->output(o)->add_item_tag(new_tag); - } - } - } - break; - case gr_block::TPP_ONE_TO_ONE: - // tags from input i only go to output i - // this requires d->ninputs() == d->noutputs; this is checked when this - // type of tag-propagation system is selected in gr_block_detail - if(d->ninputs() == d->noutputs()) { - for(int i = 0; i < d->ninputs(); i++) { - d->get_tags_in_range(rtags, i, start_nitems_read[i], - d->nitems_read(i)); - - std::vector<gr_tag_t>::iterator t; - for(t = rtags.begin(); t != rtags.end(); t++) { - gr_tag_t new_tag = *t; - new_tag.offset *= rrate; - d->output(i)->add_item_tag(new_tag); - } - } - } - else { - std::cerr << "Error: gr_block_executor: propagation_policy 'ONE-TO-ONE' requires ninputs == noutputs" << std::endl; - return false; - } - - break; - default: - return true; - } - return true; -} - -gr_block_executor::gr_block_executor (gr_block_sptr block, int max_noutput_items) - : d_block(block), d_log(0), d_max_noutput_items(max_noutput_items) -{ - if (ENABLE_LOGGING){ - std::string name = str(boost::format("sst-%03d.log") % which_scheduler++); - d_log = new std::ofstream(name.c_str()); - std::unitbuf(*d_log); // make it unbuffered... - *d_log << "gr_block_executor: " - << d_block << std::endl; - } - -#ifdef GR_PERFORMANCE_COUNTERS - gr_prefs *prefs = gr_prefs::singleton(); - d_use_pc = prefs->get_bool("PerfCounters", "on", false); -#endif /* GR_PERFORMANCE_COUNTERS */ - - d_block->start(); // enable any drivers, etc. -} - -gr_block_executor::~gr_block_executor () -{ - if (ENABLE_LOGGING) - delete d_log; - - d_block->stop(); // stop any drivers, etc. -} - -gr_block_executor::state -gr_block_executor::run_one_iteration() -{ - int noutput_items; - int max_items_avail; - int max_noutput_items = d_max_noutput_items; - int new_alignment=0; - int alignment_state=-1; - - gr_block *m = d_block.get(); - gr_block_detail *d = m->detail().get(); - - LOG(*d_log << std::endl << m); - - if (d->done()){ - assert(0); - return DONE; - } - - if (d->source_p ()){ - d_ninput_items_required.resize (0); - d_ninput_items.resize (0); - d_input_items.resize (0); - d_input_done.resize(0); - d_output_items.resize (d->noutputs ()); - d_start_nitems_read.resize(0); - - // determine the minimum available output space - noutput_items = min_available_space (d, m->output_multiple (), m->min_noutput_items ()); - noutput_items = std::min(noutput_items, max_noutput_items); - LOG(*d_log << " source\n noutput_items = " << noutput_items << std::endl); - if (noutput_items == -1) // we're done - goto were_done; - - if (noutput_items == 0){ // we're output blocked - LOG(*d_log << " BLKD_OUT\n"); - return BLKD_OUT; - } - - goto setup_call_to_work; // jump to common code - } - - else if (d->sink_p ()){ - d_ninput_items_required.resize (d->ninputs ()); - d_ninput_items.resize (d->ninputs ()); - d_input_items.resize (d->ninputs ()); - d_input_done.resize(d->ninputs()); - d_output_items.resize (0); - d_start_nitems_read.resize(d->ninputs()); - LOG(*d_log << " sink\n"); - - max_items_avail = 0; - for (int i = 0; i < d->ninputs (); i++){ - { - /* - * Acquire the mutex and grab local copies of items_available and done. - */ - gr::thread::scoped_lock guard(*d->input(i)->mutex()); - d_ninput_items[i] = d->input(i)->items_available(); - d_input_done[i] = d->input(i)->done(); - } - - LOG(*d_log << " d_ninput_items[" << i << "] = " << d_ninput_items[i] << std::endl); - LOG(*d_log << " d_input_done[" << i << "] = " << d_input_done[i] << std::endl); - - if (d_ninput_items[i] < m->output_multiple() && d_input_done[i]) - goto were_done; - - max_items_avail = std::max (max_items_avail, d_ninput_items[i]); - } - - // take a swag at how much output we can sink - noutput_items = (int) (max_items_avail * m->relative_rate ()); - noutput_items = round_down (noutput_items, m->output_multiple ()); - noutput_items = std::min(noutput_items, max_noutput_items); - LOG(*d_log << " max_items_avail = " << max_items_avail << std::endl); - LOG(*d_log << " noutput_items = " << noutput_items << std::endl); - - if (noutput_items == 0){ // we're blocked on input - LOG(*d_log << " BLKD_IN\n"); - return BLKD_IN; - } - - goto try_again; // Jump to code shared with regular case. - } - - else { - // do the regular thing - d_ninput_items_required.resize (d->ninputs ()); - d_ninput_items.resize (d->ninputs ()); - d_input_items.resize (d->ninputs ()); - d_input_done.resize(d->ninputs()); - d_output_items.resize (d->noutputs ()); - d_start_nitems_read.resize(d->ninputs()); - - max_items_avail = 0; - for (int i = 0; i < d->ninputs (); i++){ - { - /* - * Acquire the mutex and grab local copies of items_available and done. - */ - gr::thread::scoped_lock guard(*d->input(i)->mutex()); - d_ninput_items[i] = d->input(i)->items_available (); - d_input_done[i] = d->input(i)->done(); - } - max_items_avail = std::max (max_items_avail, d_ninput_items[i]); - } - - // determine the minimum available output space - noutput_items = min_available_space (d, m->output_multiple (), m->min_noutput_items ()); - if (ENABLE_LOGGING){ - *d_log << " regular "; - if (m->relative_rate() >= 1.0) - *d_log << "1:" << m->relative_rate() << std::endl; - else - *d_log << 1.0/m->relative_rate() << ":1\n"; - *d_log << " max_items_avail = " << max_items_avail << std::endl; - *d_log << " noutput_items = " << noutput_items << std::endl; - } - if (noutput_items == -1) // we're done - goto were_done; - - if (noutput_items == 0){ // we're output blocked - LOG(*d_log << " BLKD_OUT\n"); - return BLKD_OUT; - } - - try_again: - if (m->fixed_rate()){ - // try to work it forward starting with max_items_avail. - // We want to try to consume all the input we've got. - int reqd_noutput_items = m->fixed_rate_ninput_to_noutput(max_items_avail); - - // only test this if we specifically set the output_multiple - if(m->output_multiple_set()) - reqd_noutput_items = round_down(reqd_noutput_items, m->output_multiple()); - - if (reqd_noutput_items > 0 && reqd_noutput_items <= noutput_items) - noutput_items = reqd_noutput_items; - - // if we need this many outputs, overrule the max_noutput_items setting - max_noutput_items = std::max(m->output_multiple(), max_noutput_items); - } - noutput_items = std::min(noutput_items, max_noutput_items); - - // Check if we're still unaligned; use up items until we're - // aligned again. Otherwise, make sure we set the alignment - // requirement. - if(!m->output_multiple_set()) { - if(m->is_unaligned()) { - // When unaligned, don't just set noutput_items to the remaining - // samples to meet alignment; this causes too much overhead in - // requiring a premature call back here. Set the maximum amount - // of samples to handle unalignment and get us back aligned. - if(noutput_items >= m->unaligned()) { - noutput_items = round_up(noutput_items, m->alignment()) \ - - (m->alignment() - m->unaligned()); - new_alignment = 0; - } - else { - new_alignment = m->unaligned() - noutput_items; - } - alignment_state = 0; - } - else if(noutput_items < m->alignment()) { - // if we don't have enough for an aligned call, keep track of - // misalignment, set unaligned flag, and proceed. - new_alignment = m->alignment() - noutput_items; - m->set_unaligned(new_alignment); - m->set_is_unaligned(true); - alignment_state = 1; - } - else { - // enough to round down to the nearest alignment and process. - noutput_items = round_down(noutput_items, m->alignment()); - m->set_is_unaligned(false); - alignment_state = 2; - } - } - - // ask the block how much input they need to produce noutput_items - m->forecast (noutput_items, d_ninput_items_required); - - // See if we've got sufficient input available - - int i; - for (i = 0; i < d->ninputs (); i++) - if (d_ninput_items_required[i] > d_ninput_items[i]) // not enough - break; - - if (i < d->ninputs ()){ // not enough input on input[i] - // if we can, try reducing the size of our output request - if (noutput_items > m->output_multiple ()){ - noutput_items /= 2; - noutput_items = round_up (noutput_items, m->output_multiple ()); - goto try_again; - } - - // We're blocked on input - LOG(*d_log << " BLKD_IN\n"); - if (d_input_done[i]) // If the upstream block is done, we're done - goto were_done; - - // Is it possible to ever fulfill this request? - if (d_ninput_items_required[i] > d->input(i)->max_possible_items_available ()){ - // Nope, never going to happen... - std::cerr << "\nsched: <gr_block " << m->name() - << " (" << m->unique_id() << ")>" - << " is requesting more input data\n" - << " than we can provide.\n" - << " ninput_items_required = " - << d_ninput_items_required[i] << "\n" - << " max_possible_items_available = " - << d->input(i)->max_possible_items_available() << "\n" - << " If this is a filter, consider reducing the number of taps.\n"; - goto were_done; - } - - // If we were made unaligned in this round but return here without - // processing; reset the unalignment claim before next entry. - if(alignment_state == 1) { - m->set_unaligned(0); - m->set_is_unaligned(false); - } - return BLKD_IN; - } - - // We've got enough data on each input to produce noutput_items. - // Finish setting up the call to work. - - for (int i = 0; i < d->ninputs (); i++) - d_input_items[i] = d->input(i)->read_pointer(); - - setup_call_to_work: - - d->d_produce_or = 0; - for (int i = 0; i < d->noutputs (); i++) - d_output_items[i] = d->output(i)->write_pointer(); - - // determine where to start looking for new tags - for (int i = 0; i < d->ninputs(); i++) - d_start_nitems_read[i] = d->nitems_read(i); - -#ifdef GR_PERFORMANCE_COUNTERS - if(d_use_pc) - d->start_perf_counters(); -#endif /* GR_PERFORMANCE_COUNTERS */ - - // Do the actual work of the block - int n = m->general_work (noutput_items, d_ninput_items, - d_input_items, d_output_items); - -#ifdef GR_PERFORMANCE_COUNTERS - if(d_use_pc) - d->stop_perf_counters(noutput_items, n); -#endif /* GR_PERFORMANCE_COUNTERS */ - - LOG(*d_log << " general_work: noutput_items = " << noutput_items - << " result = " << n << std::endl); - - // Adjust number of unaligned items left to process - if(m->is_unaligned()) { - m->set_unaligned(new_alignment); - m->set_is_unaligned(m->unaligned() != 0); - } - - if(!propagate_tags(m->tag_propagation_policy(), d, - d_start_nitems_read, m->relative_rate(), - d_returned_tags)) - goto were_done; - - if (n == gr_block::WORK_DONE) - goto were_done; - - if (n != gr_block::WORK_CALLED_PRODUCE) - d->produce_each (n); // advance write pointers - - if (d->d_produce_or > 0) // block produced something - return READY; - - // We didn't produce any output even though we called general_work. - // We have (most likely) consumed some input. - - /* - // If this is a source, it's broken. - if (d->source_p()){ - std::cerr << "gr_block_executor: source " << m - << " produced no output. We're marking it DONE.\n"; - // FIXME maybe we ought to raise an exception... - goto were_done; - } - */ - - // Have the caller try again... - return READY_NO_OUTPUT; - } - assert (0); - - were_done: - LOG(*d_log << " were_done\n"); - d->set_done (true); - return DONE; -} diff --git a/gnuradio-runtime/lib/gr_block_executor.h b/gnuradio-runtime/lib/gr_block_executor.h deleted file mode 100644 index 7d5c4949a3..0000000000 --- a/gnuradio-runtime/lib/gr_block_executor.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2008 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_BLOCK_EXECUTOR_H -#define INCLUDED_GR_BLOCK_EXECUTOR_H - -#include <gr_runtime_api.h> -#include <gr_runtime_types.h> -#include <fstream> -#include <gr_tags.h> - -//class gr_block_executor; -//typedef boost::shared_ptr<gr_block_executor> gr_block_executor_sptr; - - -/*! - * \brief Manage the execution of a single block. - * \ingroup internal - */ - -class GR_RUNTIME_API gr_block_executor { -protected: - gr_block_sptr d_block; // The block we're trying to run - std::ofstream *d_log; - - // These are allocated here so we don't have to on each iteration - - gr_vector_int d_ninput_items_required; - gr_vector_int d_ninput_items; - gr_vector_const_void_star d_input_items; - std::vector<bool> d_input_done; - gr_vector_void_star d_output_items; - std::vector<uint64_t> d_start_nitems_read; //stores where tag counts are before work - std::vector<gr_tag_t> d_returned_tags; - int d_max_noutput_items; - -#ifdef GR_PERFORMANCE_COUNTERS - bool d_use_pc; -#endif /* GR_PERFORMANCE_COUNTERS */ - - public: - gr_block_executor(gr_block_sptr block, int max_noutput_items=100000); - ~gr_block_executor (); - - enum state { - READY, // We made progress; everything's cool. - READY_NO_OUTPUT, // We consumed some input, but produced no output. - BLKD_IN, // no progress; we're blocked waiting for input data. - BLKD_OUT, // no progress; we're blocked waiting for output buffer space. - DONE, // we're done; don't call me again. - }; - - /* - * \brief Run one iteration. - */ - state run_one_iteration(); -}; - -#endif /* INCLUDED_GR_BLOCK_EXECUTOR_H */ diff --git a/gnuradio-runtime/lib/gr_block_registry.cc b/gnuradio-runtime/lib/gr_block_registry.cc deleted file mode 100644 index a80673691a..0000000000 --- a/gnuradio-runtime/lib/gr_block_registry.cc +++ /dev/null @@ -1,98 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2012-2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include <gr_basic_block.h> -#include <gr_block_registry.h> -#include <gr_tpb_detail.h> -#include <gr_block_detail.h> -#include <gr_block.h> -#include <stdio.h> - -gr_block_registry global_block_registry; - -gr_block_registry::gr_block_registry(){ - d_ref_map = pmt::make_dict(); -} - -long gr_block_registry::block_register(gr_basic_block* block){ - if(d_map.find(block->name()) == d_map.end()){ - d_map[block->name()] = blocksubmap_t(); - d_map[block->name()][0] = block; - return 0; - } else { - for(size_t i=0; i<=d_map[block->name()].size(); i++){ - if(d_map[block->name()].find(i) == d_map[block->name()].end()){ - d_map[block->name()][i] = block; - return i; - } - } - } - throw std::runtime_error("should not reach this"); -} - -void gr_block_registry::block_unregister(gr_basic_block* block){ - d_map[block->name()].erase( d_map[block->name()].find(block->symbolic_id())); - d_ref_map = pmt::dict_delete(d_ref_map, pmt::intern(block->symbol_name())); - if(block->alias_set()){ - d_ref_map = pmt::dict_delete(d_ref_map, pmt::intern(block->alias())); - } -} - -std::string gr_block_registry::register_symbolic_name(gr_basic_block* block){ - std::stringstream ss; - ss << block->name() << block->symbolic_id(); - //std::cout << "register_symbolic_name: " << ss.str() << std::endl; - register_symbolic_name(block, ss.str()); - return ss.str(); -} - -void gr_block_registry::register_symbolic_name(gr_basic_block* block, std::string name){ - if(pmt::dict_has_key(d_ref_map, pmt::intern(name))){ - throw std::runtime_error("symbol already exists, can not re-use!"); - } - d_ref_map = pmt::dict_add(d_ref_map, pmt::intern(name), pmt::make_any(block)); -} - -gr_basic_block_sptr gr_block_registry::block_lookup(pmt::pmt_t symbol){ - pmt::pmt_t ref = pmt::dict_ref(d_ref_map, symbol, pmt::PMT_NIL); - if(pmt::eq(ref, pmt::PMT_NIL)){ - throw std::runtime_error("block lookup failed! block not found!"); - } - gr_basic_block* blk = boost::any_cast<gr_basic_block*>( pmt::any_ref(ref) ); - return blk->shared_from_this(); -} - - -void gr_block_registry::register_primitive(std::string blk, gr_block* ref){ - primitive_map[blk] = ref; -} - -void gr_block_registry::unregister_primitive(std::string blk){ - primitive_map.erase(primitive_map.find(blk)); -} - -void gr_block_registry::notify_blk(std::string blk){ - if(primitive_map.find(blk) == primitive_map.end()){ return; } - if(primitive_map[blk]->detail().get()) - primitive_map[blk]->detail()->d_tpb.notify_msg(); -} - diff --git a/gnuradio-runtime/lib/gr_buffer.cc b/gnuradio-runtime/lib/gr_buffer.cc deleted file mode 100644 index bdce5b4036..0000000000 --- a/gnuradio-runtime/lib/gr_buffer.cc +++ /dev/null @@ -1,347 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2009,2010 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_buffer.h> -#include <gr_vmcircbuf.h> -#include <gr_math.h> -#include <stdexcept> -#include <iostream> -#include <assert.h> -#include <algorithm> -#include <boost/math/common_factor_rt.hpp> - -static long s_buffer_count = 0; // counts for debugging storage mgmt -static long s_buffer_reader_count = 0; - -// ---------------------------------------------------------------------------- -// Notes on storage management -// -// Pretty much all the fundamental classes are now using the -// shared_ptr stuff for automatic reference counting. To ensure that -// no mistakes are made, we make the constructors for classes private, -// and then provide a free factory function that returns a smart -// pointer to the desired class. -// -// gr_buffer and gr_buffer_reader are no exceptions. However, they -// both want pointers to each other, and unless we do something, we'll -// never delete any of them because of the circular structure. -// They'll always have a reference count of at least one. We could -// use boost::weak_ptr's from gr_buffer to gr_buffer_reader but that -// introduces it's own problems. (gr_buffer_reader's destructor needs -// to call gr_buffer::drop_reader, but has no easy way to get a -// shared_ptr to itself.) -// -// Instead, we solve this problem by having gr_buffer hold a raw -// pointer to gr_buffer_reader in its d_reader vector. -// gr_buffer_reader's destructor calls gr_buffer::drop_reader, so -// we're never left with an dangling pointer. gr_buffer_reader still -// has a shared_ptr to the buffer ensuring that the buffer doesn't go -// away under it. However, when the reference count of a -// gr_buffer_reader goes to zero, we can successfully reclaim it. -// ---------------------------------------------------------------------------- - - -/* - * Compute the minimum number of buffer items that work (i.e., - * address space wrap-around works). To work is to satisfy this - * contraint for integer buffer_size and k: - * - * type_size * nitems == k * page_size - */ -static long -minimum_buffer_items (long type_size, long page_size) -{ - return page_size / boost::math::gcd (type_size, page_size); -} - - -gr_buffer::gr_buffer (int nitems, size_t sizeof_item, gr_block_sptr link) - : d_base (0), d_bufsize (0), d_vmcircbuf (0), - d_sizeof_item (sizeof_item), d_link(link), - d_write_index (0), d_abs_write_offset(0), d_done (false), - d_last_min_items_read(0) -{ - if (!allocate_buffer (nitems, sizeof_item)) - throw std::bad_alloc (); - - s_buffer_count++; -} - -gr_buffer_sptr -gr_make_buffer (int nitems, size_t sizeof_item, gr_block_sptr link) -{ - return gr_buffer_sptr (new gr_buffer (nitems, sizeof_item, link)); -} - -gr_buffer::~gr_buffer () -{ - delete d_vmcircbuf; - assert (d_readers.size() == 0); - s_buffer_count--; -} - -/*! - * sets d_vmcircbuf, d_base, d_bufsize. - * returns true iff successful. - */ -bool -gr_buffer::allocate_buffer (int nitems, size_t sizeof_item) -{ - int orig_nitems = nitems; - - // Any buffersize we come up with must be a multiple of min_nitems. - - int granularity = gr_vmcircbuf_sysconfig::granularity (); - int min_nitems = minimum_buffer_items (sizeof_item, granularity); - - // Round-up nitems to a multiple of min_nitems. - - if (nitems % min_nitems != 0) - nitems = ((nitems / min_nitems) + 1) * min_nitems; - - // If we rounded-up a whole bunch, give the user a heads up. - // This only happens if sizeof_item is not a power of two. - - if (nitems > 2 * orig_nitems && nitems * (int) sizeof_item > granularity){ - std::cerr << "gr_buffer::allocate_buffer: warning: tried to allocate\n" - << " " << orig_nitems << " items of size " - << sizeof_item << ". Due to alignment requirements\n" - << " " << nitems << " were allocated. If this isn't OK, consider padding\n" - << " your structure to a power-of-two bytes.\n" - << " On this platform, our allocation granularity is " << granularity << " bytes.\n"; - } - - d_bufsize = nitems; - d_vmcircbuf = gr_vmcircbuf_sysconfig::make (d_bufsize * d_sizeof_item); - if (d_vmcircbuf == 0){ - std::cerr << "gr_buffer::allocate_buffer: failed to allocate buffer of size " - << d_bufsize * d_sizeof_item / 1024 << " KB\n"; - return false; - } - - d_base = (char *) d_vmcircbuf->pointer_to_first_copy (); - return true; -} - - -int -gr_buffer::space_available () -{ - if (d_readers.empty ()) - return d_bufsize - 1; // See comment below - - else { - - // Find out the maximum amount of data available to our readers - - int most_data = d_readers[0]->items_available (); - uint64_t min_items_read = d_readers[0]->nitems_read(); - for (size_t i = 1; i < d_readers.size (); i++) { - most_data = std::max (most_data, d_readers[i]->items_available ()); - min_items_read = std::min(min_items_read, d_readers[i]->nitems_read()); - } - - if(min_items_read != d_last_min_items_read) { - prune_tags(d_last_min_items_read); - d_last_min_items_read = min_items_read; - } - - // The -1 ensures that the case d_write_index == d_read_index is - // unambiguous. It indicates that there is no data for the reader - - return d_bufsize - most_data - 1; - } -} - -void * -gr_buffer::write_pointer () -{ - return &d_base[d_write_index * d_sizeof_item]; -} - -void -gr_buffer::update_write_pointer (int nitems) -{ - gr::thread::scoped_lock guard(*mutex()); - d_write_index = index_add (d_write_index, nitems); - d_abs_write_offset += nitems; -} - -void -gr_buffer::set_done (bool done) -{ - gr::thread::scoped_lock guard(*mutex()); - d_done = done; -} - -gr_buffer_reader_sptr -gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link) -{ - if (nzero_preload < 0) - throw std::invalid_argument("gr_buffer_add_reader: nzero_preload must be >= 0"); - - gr_buffer_reader_sptr r (new gr_buffer_reader (buf, - buf->index_sub(buf->d_write_index, - nzero_preload), - link)); - buf->d_readers.push_back (r.get ()); - - return r; -} - -void -gr_buffer::drop_reader (gr_buffer_reader *reader) -{ - // isn't C++ beautiful... GAG! - - std::vector<gr_buffer_reader *>::iterator result = - std::find (d_readers.begin (), d_readers.end (), reader); - - if (result == d_readers.end ()) - throw std::invalid_argument ("gr_buffer::drop_reader"); // we didn't find it... - - d_readers.erase (result); -} - -void -gr_buffer::add_item_tag(const gr_tag_t &tag) -{ - gr::thread::scoped_lock guard(*mutex()); - d_item_tags.push_back(tag); -} - -void -gr_buffer::remove_item_tag(const gr_tag_t &tag) -{ - gr::thread::scoped_lock guard(*mutex()); - for (std::deque<gr_tag_t>::iterator it = d_item_tags.begin(); it != d_item_tags.end(); ++it) { - if (*it == tag) { - d_item_tags.erase(it); - break; - } - } -} - -void -gr_buffer::prune_tags(uint64_t max_time) -{ - /* NOTE: this function _should_ lock the mutex before editing - d_item_tags. In practice, this function is only called at - runtime by min_available_space in gr_block_executor.cc, - which locks the mutex itself. - - If this function is used elsewhere, remember to lock the - buffer's mutex al la the scoped_lock line below. - */ - //gr::thread::scoped_lock guard(*mutex()); - std::deque<gr_tag_t>::iterator itr = d_item_tags.begin(); - - uint64_t item_time; - - // Since tags are not guarenteed to be in any particular order, - // we need to erase here instead of pop_front. An erase in the - // middle invalidates all iterators; so this resets the iterator - // to find more. Mostly, we wil be erasing from the front and - // therefore lose little time this way. - while(itr != d_item_tags.end()) { - item_time = (*itr).offset; - if(item_time < max_time) { - d_item_tags.erase(itr); - itr = d_item_tags.begin(); - } - else - itr++; - } -} - -long -gr_buffer_ncurrently_allocated () -{ - return s_buffer_count; -} - -// ---------------------------------------------------------------------------- - -gr_buffer_reader::gr_buffer_reader(gr_buffer_sptr buffer, unsigned int read_index, - gr_block_sptr link) - : d_buffer(buffer), d_read_index(read_index), d_abs_read_offset(0), d_link(link) -{ - s_buffer_reader_count++; -} - -gr_buffer_reader::~gr_buffer_reader () -{ - d_buffer->drop_reader(this); - s_buffer_reader_count--; -} - -int -gr_buffer_reader::items_available () const -{ - return d_buffer->index_sub (d_buffer->d_write_index, d_read_index); -} - -const void * -gr_buffer_reader::read_pointer () -{ - return &d_buffer->d_base[d_read_index * d_buffer->d_sizeof_item]; -} - -void -gr_buffer_reader::update_read_pointer (int nitems) -{ - gr::thread::scoped_lock guard(*mutex()); - d_read_index = d_buffer->index_add (d_read_index, nitems); - d_abs_read_offset += nitems; -} - -void -gr_buffer_reader::get_tags_in_range(std::vector<gr_tag_t> &v, - uint64_t abs_start, - uint64_t abs_end) -{ - gr::thread::scoped_lock guard(*mutex()); - - v.resize(0); - std::deque<gr_tag_t>::iterator itr = d_buffer->get_tags_begin(); - - uint64_t item_time; - while(itr != d_buffer->get_tags_end()) { - item_time = (*itr).offset; - - if((item_time >= abs_start) && (item_time < abs_end)) { - v.push_back(*itr); - } - - itr++; - } -} - -long -gr_buffer_reader_ncurrently_allocated () -{ - return s_buffer_reader_count; -} diff --git a/gnuradio-runtime/lib/gr_circular_file.cc b/gnuradio-runtime/lib/gr_circular_file.cc deleted file mode 100644 index 6f710c49b1..0000000000 --- a/gnuradio-runtime/lib/gr_circular_file.cc +++ /dev/null @@ -1,203 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2002,2010 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gr_circular_file.h> - -#include <unistd.h> -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <fcntl.h> -#include <stdio.h> -#include <assert.h> -#include <stdlib.h> - -#include <algorithm> -#include <stdio.h> -#include <string.h> - -#ifdef HAVE_IO_H -#include <io.h> -#endif - -static const int HEADER_SIZE = 4096; -static const int HEADER_MAGIC = 0xEB021026; - -static const int HD_MAGIC = 0; -static const int HD_HEADER_SIZE = 1; // integer offsets into header -static const int HD_BUFFER_SIZE = 2; -static const int HD_BUFFER_BASE = 3; -static const int HD_BUFFER_CURRENT = 4; - -gr_circular_file::gr_circular_file (const char *filename, - bool writable, int size) - : d_fd (-1), d_header (0), d_buffer (0), d_mapped_size (0), d_bytes_read (0) -{ - int mm_prot; - if (writable){ -#ifdef HAVE_MMAP - mm_prot = PROT_READ | PROT_WRITE; -#endif - d_fd = open (filename, O_CREAT | O_RDWR | O_TRUNC, 0664); - if (d_fd < 0){ - perror (filename); - exit (1); - } -#ifdef HAVE_MMAP /* FIXME */ - if(ftruncate (d_fd, size + HEADER_SIZE) != 0) { - perror (filename); - exit (1); - } -#endif - } - else { -#ifdef HAVE_MMAP - mm_prot = PROT_READ; -#endif - d_fd = open (filename, O_RDONLY); - if (d_fd < 0){ - perror (filename); - exit (1); - } - } - - struct stat statbuf; - if (fstat (d_fd, &statbuf) < 0){ - perror (filename); - exit (1); - } - - if (statbuf.st_size < HEADER_SIZE){ - fprintf (stderr, "%s: file too small to be circular buffer\n", filename); - exit (1); - } - - d_mapped_size = statbuf.st_size; -#ifdef HAVE_MMAP - void *p = mmap (0, d_mapped_size, mm_prot, MAP_SHARED, d_fd, 0); - if (p == MAP_FAILED){ - perror ("gr_circular_file: mmap failed"); - exit (1); - } - - d_header = (int *) p; -#else - perror ("gr_circular_file: mmap unsupported by this system"); - exit (1); -#endif - - if (writable){ // init header - - if (size < 0){ - fprintf (stderr, "gr_circular_buffer: size must be > 0 when writable\n"); - exit (1); - } - - d_header[HD_MAGIC] = HEADER_MAGIC; - d_header[HD_HEADER_SIZE] = HEADER_SIZE; - d_header[HD_BUFFER_SIZE] = size; - d_header[HD_BUFFER_BASE] = HEADER_SIZE; // right after header - d_header[HD_BUFFER_CURRENT] = 0; - } - - // sanity check (the asserts are a bit unforgiving...) - - assert (d_header[HD_MAGIC] == HEADER_MAGIC); - assert (d_header[HD_HEADER_SIZE] == HEADER_SIZE); - assert (d_header[HD_BUFFER_SIZE] > 0); - assert (d_header[HD_BUFFER_BASE] >= d_header[HD_HEADER_SIZE]); - assert (d_header[HD_BUFFER_BASE] + d_header[HD_BUFFER_SIZE] <= d_mapped_size); - assert (d_header[HD_BUFFER_CURRENT] >= 0 && - d_header[HD_BUFFER_CURRENT] < d_header[HD_BUFFER_SIZE]); - - d_bytes_read = 0; - d_buffer = (unsigned char *) d_header + d_header[HD_BUFFER_BASE]; -} - -gr_circular_file::~gr_circular_file () -{ -#ifdef HAVE_MMAP - if (munmap ((char *) d_header, d_mapped_size) < 0){ - perror ("gr_circular_file: munmap"); - exit (1); - } -#endif - close (d_fd); -} - -bool -gr_circular_file::write (void *vdata, int nbytes) -{ - unsigned char *data = (unsigned char *) vdata; - int buffer_size = d_header[HD_BUFFER_SIZE]; - int buffer_current = d_header[HD_BUFFER_CURRENT]; - - while (nbytes > 0){ - int n = std::min (nbytes, buffer_size - buffer_current); - memcpy (d_buffer + buffer_current, data, n); - - buffer_current += n; - if (buffer_current >= buffer_size) - buffer_current = 0; - - data += n; - nbytes -= n; - } - - d_header[HD_BUFFER_CURRENT] = buffer_current; - return true; -} - -int -gr_circular_file::read (void *vdata, int nbytes) -{ - unsigned char *data = (unsigned char *) vdata; - int buffer_current = d_header[HD_BUFFER_CURRENT]; - int buffer_size = d_header[HD_BUFFER_SIZE]; - int total = 0; - - nbytes = std::min (nbytes, buffer_size - d_bytes_read); - - while (nbytes > 0){ - int offset = (buffer_current + d_bytes_read) % buffer_size; - int n = std::min (nbytes, buffer_size - offset); - memcpy (data, d_buffer + offset, n); - data += n; - d_bytes_read += n; - total += n; - nbytes -= n; - } - return total; -} - -void -gr_circular_file::reset_read_pointer () -{ - d_bytes_read = 0; -} diff --git a/gnuradio-runtime/lib/gr_circular_file.h b/gnuradio-runtime/lib/gr_circular_file.h deleted file mode 100644 index 2b61bf2711..0000000000 --- a/gnuradio-runtime/lib/gr_circular_file.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2002 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef _GR_CIRCULAR_FILE_H_ -#define _GR_CIRCULAR_FILE_H_ - -#include <gr_runtime_api.h> - -/* - * writes input data into a circular buffer on disk. - * - * the file contains a fixed header: - * 0x0000: int32 magic (0xEB021026) - * 0x0004: int32 size in bytes of header (constant 4096) - * 0x0008: int32 size in bytes of circular buffer (not including header) - * 0x000C: int32 file offset to beginning of circular buffer - * 0x0010: int32 byte offset from beginning of circular buffer to - * current start of data - * - */ -class GR_RUNTIME_API gr_circular_file { - int d_fd; - int *d_header; - unsigned char *d_buffer; - int d_mapped_size; - int d_bytes_read; - -public: - gr_circular_file (const char *filename, bool writable = false, int size = 0); - ~gr_circular_file (); - - bool write (void *data, int nbytes); - - // returns # of bytes actually read or 0 if end of buffer, or -1 on error. - int read (void *data, int nbytes); - - // reset read pointer to beginning of buffer. - void reset_read_pointer (); -}; - -#endif /* _GR_CIRCULAR_FILE_H_ */
\ No newline at end of file diff --git a/gnuradio-runtime/lib/gr_dispatcher.cc b/gnuradio-runtime/lib/gr_dispatcher.cc deleted file mode 100644 index 96ebe9ad8b..0000000000 --- a/gnuradio-runtime/lib/gr_dispatcher.cc +++ /dev/null @@ -1,193 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_dispatcher.h> -#include <math.h> -#include <errno.h> -#include <stdio.h> - -#ifdef HAVE_SELECT -# ifdef HAVE_SYS_SELECT_H -# include <sys/select.h> -# else -# ifdef HAVE_SYS_TIME_H -# include <sys/time.h> -# endif -# ifdef HAVE_SYS_TYPES_H -# include <sys/types.h> -# endif -# ifdef HAVE_UNISTD_H -# include <unistd.h> -# endif -# endif -#endif - - -static gr_dispatcher_sptr s_singleton; - -gr_dispatcher_sptr -gr_make_dispatcher() -{ - return gr_dispatcher_sptr(new gr_dispatcher()); -} - -gr_dispatcher_sptr -gr_dispatcher_singleton() -{ - if (s_singleton) - return s_singleton; - - s_singleton = gr_make_dispatcher(); - return s_singleton; -} - -#if !defined(HAVE_SELECT) // Stub it out - -gr_dispatcher::gr_dispatcher() -{ -} - -gr_dispatcher::~gr_dispatcher() -{ -} - -bool -gr_dispatcher::add_handler(gr_select_handler_sptr handler) -{ - return true; -} - -bool -gr_dispatcher::del_handler(gr_select_handler_sptr handler) -{ - return true; -} - -bool -gr_dispatcher::del_handler(gr_select_handler *handler) -{ - return true; -} - -void -gr_dispatcher::loop(double timeout) -{ -} - -#else // defined(HAVE_SELECT) - -gr_dispatcher::gr_dispatcher() - : d_handler(FD_SETSIZE), d_max_index(-1) -{ -} - -gr_dispatcher::~gr_dispatcher() -{ -} - -bool -gr_dispatcher::add_handler(gr_select_handler_sptr handler) -{ - int fd = handler->fd(); - if (fd < 0 || fd >= FD_SETSIZE) - return false; - - d_max_index = std::max(d_max_index, fd); - d_handler[fd] = handler; - return true; -} - -bool -gr_dispatcher::del_handler(gr_select_handler_sptr handler) -{ - return del_handler(handler.get()); -} - -bool -gr_dispatcher::del_handler(gr_select_handler *handler) -{ - int fd = handler->fd(); - if (fd < 0 || fd >= FD_SETSIZE) - return false; - - d_handler[fd].reset(); - - if (fd == d_max_index){ - int i; - for (i = fd - 1; i >= 0 && !d_handler[i]; i--) - ; - d_max_index = i; - } - return true; -} - - -void -gr_dispatcher::loop(double timeout) -{ - struct timeval master; - struct timeval tmp; - fd_set rd_set; - fd_set wr_set; - - double secs = floor (timeout); - master.tv_sec = (long) secs; - master.tv_usec = (long) ((timeout - secs) * 1e6); - - while (d_max_index >= 0){ - FD_ZERO(&rd_set); - FD_ZERO(&wr_set); - - for (int i = 0; i <= d_max_index; i++){ - if (d_handler[i] && d_handler[i]->readable()) - FD_SET(i, &rd_set); - if (d_handler[i] && d_handler[i]->writable()) - FD_SET(i, &wr_set); - } - - tmp = master; - int retval = select(d_max_index+1, &rd_set, &wr_set, 0, &tmp); - if (retval == 0) // timed out with nothing ready - continue; - if (retval < 0){ - if (errno == EINTR) - continue; - perror ("gr_dispatcher/select"); - return; - } - - for (int i = 0; i <= d_max_index; i++){ - if (FD_ISSET(i, &rd_set)) - if (d_handler[i]) - d_handler[i]->handle_read(); - if (FD_ISSET(i, &wr_set)) - if (d_handler[i]) - d_handler[i]->handle_write(); - } - } -} - -#endif diff --git a/gnuradio-runtime/lib/gr_error_handler.cc b/gnuradio-runtime/lib/gr_error_handler.cc deleted file mode 100644 index 448682966e..0000000000 --- a/gnuradio-runtime/lib/gr_error_handler.cc +++ /dev/null @@ -1,244 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -/* - * This code is based on error.cc from the "Click Modular Router". - * Original copyright follows: - */ -/* - * error.{cc,hh} -- flexible classes for error reporting - * Eddie Kohler - * - * Copyright (c) 1999-2000 Massachusetts Institute of Technology - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, subject to the conditions - * listed in the Click LICENSE file. These conditions include: you must - * preserve this copyright notice, and you cannot mention the copyright - * holders in advertising related to the Software without their permission. - * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This - * notice is a summary of the Click LICENSE file; the license in that file is - * legally binding. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_error_handler.h> -#include <assert.h> -#include <stdexcept> -#include <unistd.h> - -#ifdef HAVE_IO_H -#include <io.h> -#endif - -static gr_error_handler *s_default_handler = 0; -static gr_error_handler *s_silent_handler = 0; - -bool -gr_error_handler::has_default_handler() -{ - return s_default_handler != 0; -} - -void -gr_error_handler::set_default_handler(gr_error_handler *errh) -{ - s_default_handler = errh; -} - -gr_error_handler * -gr_error_handler::default_handler() -{ - assert (s_default_handler != 0); - return s_default_handler; -} - -gr_error_handler * -gr_error_handler::silent_handler() -{ - assert (s_silent_handler != 0); - return s_silent_handler; -} - -// ---------------------------------------------------------------- - -gr_error_handler::~gr_error_handler() -{ - // nop -} - -void -gr_error_handler::debug(const char *format, ...) -{ - va_list val; - va_start(val, format); - verror(ERR_DEBUG, format, val); - va_end(val); -} - -void -gr_error_handler::message(const char *format, ...) -{ - va_list val; - va_start(val, format); - verror(ERR_MESSAGE, format, val); - va_end(val); -} - -void -gr_error_handler::warning(const char *format, ...) -{ - va_list val; - va_start(val, format); - verror(ERR_WARNING, format, val); - va_end(val); -} - -void -gr_error_handler::error(const char *format, ...) -{ - va_list val; - va_start(val, format); - verror(ERR_ERROR, format, val); - va_end(val); -} - -void -gr_error_handler::fatal(const char *format, ...) -{ - va_list val; - va_start(val, format); - verror(ERR_FATAL, format, val); - va_end(val); -} - -void -gr_error_handler::verror(seriousness s, const char *format, va_list val) -{ - std::string text = make_text(s, format, val); - handle_text(s, text); - count_error(s); -} - -void -gr_error_handler::verror_text(seriousness s, const std::string &text) -{ - // text is already made - handle_text(s, text); - count_error(s); -} - -std::string -gr_error_handler::make_text(seriousness s, const char *format, va_list val) -{ - char text_buf[4096]; - vsnprintf(text_buf, sizeof(text_buf), format, val); - text_buf[sizeof(text_buf)-1] = 0; - return text_buf; -} - -// ---------------------------------------------------------------- - -void -gr_base_error_handler::count_error(seriousness s) -{ - if (s < ERR_WARNING) - /* do nothing */; - else if (s < ERR_ERROR) - d_nwarnings++; - else - d_nerrors++; -} - -// ---------------------------------------------------------------- - -gr_file_error_handler::gr_file_error_handler(FILE *file) - : d_file(file), d_fd(-1) -{ -} - -gr_file_error_handler::gr_file_error_handler(int file_descriptor) -{ - d_fd = dup(file_descriptor); // so we can fclose it - if (d_fd == -1){ - perror("gr_file_error_handler:dup"); - throw std::invalid_argument("gr_file_error_handler:dup"); - } - d_file = fdopen(d_fd, "w"); - if (d_file == 0){ - perror("gr_file_error_handler:fdopen"); - throw std::invalid_argument("gr_file_error_handler:fdopen"); - } -} - -gr_file_error_handler::~gr_file_error_handler() -{ - if (d_fd != -1){ - fclose(d_file); - } -} - -void -gr_file_error_handler::handle_text(seriousness s, const std::string &text) -{ - if (text.length() <= 0) - return; - - fwrite(text.data(), 1, text.length(), d_file); - if (text[text.length()-1] != '\n') - fwrite("\n", 1, 1, d_file); - - if (d_fd != -1) - fflush(d_file); // keep synced with any other users of fd -} - - -// ---------------------------------------------------------------- -// static error handlers -// - -class gr_silent_error_handler : public gr_base_error_handler -{ -public: - gr_silent_error_handler() {} - void handle_text(seriousness s, const std::string &str); -}; - -void -gr_silent_error_handler::handle_text(seriousness s, const std::string &str) -{ - // nop -} - -class force_init { -public: - force_init() - { - s_default_handler = new gr_file_error_handler(stdout); - s_silent_handler = new gr_silent_error_handler(); - } -}; - -static force_init kludge; diff --git a/gnuradio-runtime/lib/gr_fast_atan2f.cc b/gnuradio-runtime/lib/gr_fast_atan2f.cc deleted file mode 100644 index 8b7bfea12e..0000000000 --- a/gnuradio-runtime/lib/gr_fast_atan2f.cc +++ /dev/null @@ -1,199 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include <gr_math.h> // declaration is in here -#include <cmath> - -#define REAL float - -/***************************************************************************/ -/* Constant definitions */ -/***************************************************************************/ - -#define TAN_MAP_RES 0.003921569 /* (smallest non-zero value in table) */ -#define RAD_PER_DEG 0.017453293 -#define TAN_MAP_SIZE 256 - -/* arctangents from 0 to pi/4 radians */ -static REAL -fast_atan_table[257] = { - 0.000000e+00, 3.921549e-03, 7.842976e-03, 1.176416e-02, - 1.568499e-02, 1.960533e-02, 2.352507e-02, 2.744409e-02, - 3.136226e-02, 3.527947e-02, 3.919560e-02, 4.311053e-02, - 4.702413e-02, 5.093629e-02, 5.484690e-02, 5.875582e-02, - 6.266295e-02, 6.656816e-02, 7.047134e-02, 7.437238e-02, - 7.827114e-02, 8.216752e-02, 8.606141e-02, 8.995267e-02, - 9.384121e-02, 9.772691e-02, 1.016096e-01, 1.054893e-01, - 1.093658e-01, 1.132390e-01, 1.171087e-01, 1.209750e-01, - 1.248376e-01, 1.286965e-01, 1.325515e-01, 1.364026e-01, - 1.402496e-01, 1.440924e-01, 1.479310e-01, 1.517652e-01, - 1.555948e-01, 1.594199e-01, 1.632403e-01, 1.670559e-01, - 1.708665e-01, 1.746722e-01, 1.784728e-01, 1.822681e-01, - 1.860582e-01, 1.898428e-01, 1.936220e-01, 1.973956e-01, - 2.011634e-01, 2.049255e-01, 2.086818e-01, 2.124320e-01, - 2.161762e-01, 2.199143e-01, 2.236461e-01, 2.273716e-01, - 2.310907e-01, 2.348033e-01, 2.385093e-01, 2.422086e-01, - 2.459012e-01, 2.495869e-01, 2.532658e-01, 2.569376e-01, - 2.606024e-01, 2.642600e-01, 2.679104e-01, 2.715535e-01, - 2.751892e-01, 2.788175e-01, 2.824383e-01, 2.860514e-01, - 2.896569e-01, 2.932547e-01, 2.968447e-01, 3.004268e-01, - 3.040009e-01, 3.075671e-01, 3.111252e-01, 3.146752e-01, - 3.182170e-01, 3.217506e-01, 3.252758e-01, 3.287927e-01, - 3.323012e-01, 3.358012e-01, 3.392926e-01, 3.427755e-01, - 3.462497e-01, 3.497153e-01, 3.531721e-01, 3.566201e-01, - 3.600593e-01, 3.634896e-01, 3.669110e-01, 3.703234e-01, - 3.737268e-01, 3.771211e-01, 3.805064e-01, 3.838825e-01, - 3.872494e-01, 3.906070e-01, 3.939555e-01, 3.972946e-01, - 4.006244e-01, 4.039448e-01, 4.072558e-01, 4.105574e-01, - 4.138496e-01, 4.171322e-01, 4.204054e-01, 4.236689e-01, - 4.269229e-01, 4.301673e-01, 4.334021e-01, 4.366272e-01, - 4.398426e-01, 4.430483e-01, 4.462443e-01, 4.494306e-01, - 4.526070e-01, 4.557738e-01, 4.589307e-01, 4.620778e-01, - 4.652150e-01, 4.683424e-01, 4.714600e-01, 4.745676e-01, - 4.776654e-01, 4.807532e-01, 4.838312e-01, 4.868992e-01, - 4.899573e-01, 4.930055e-01, 4.960437e-01, 4.990719e-01, - 5.020902e-01, 5.050985e-01, 5.080968e-01, 5.110852e-01, - 5.140636e-01, 5.170320e-01, 5.199904e-01, 5.229388e-01, - 5.258772e-01, 5.288056e-01, 5.317241e-01, 5.346325e-01, - 5.375310e-01, 5.404195e-01, 5.432980e-01, 5.461666e-01, - 5.490251e-01, 5.518738e-01, 5.547124e-01, 5.575411e-01, - 5.603599e-01, 5.631687e-01, 5.659676e-01, 5.687566e-01, - 5.715357e-01, 5.743048e-01, 5.770641e-01, 5.798135e-01, - 5.825531e-01, 5.852828e-01, 5.880026e-01, 5.907126e-01, - 5.934128e-01, 5.961032e-01, 5.987839e-01, 6.014547e-01, - 6.041158e-01, 6.067672e-01, 6.094088e-01, 6.120407e-01, - 6.146630e-01, 6.172755e-01, 6.198784e-01, 6.224717e-01, - 6.250554e-01, 6.276294e-01, 6.301939e-01, 6.327488e-01, - 6.352942e-01, 6.378301e-01, 6.403565e-01, 6.428734e-01, - 6.453808e-01, 6.478788e-01, 6.503674e-01, 6.528466e-01, - 6.553165e-01, 6.577770e-01, 6.602282e-01, 6.626701e-01, - 6.651027e-01, 6.675261e-01, 6.699402e-01, 6.723452e-01, - 6.747409e-01, 6.771276e-01, 6.795051e-01, 6.818735e-01, - 6.842328e-01, 6.865831e-01, 6.889244e-01, 6.912567e-01, - 6.935800e-01, 6.958943e-01, 6.981998e-01, 7.004964e-01, - 7.027841e-01, 7.050630e-01, 7.073330e-01, 7.095943e-01, - 7.118469e-01, 7.140907e-01, 7.163258e-01, 7.185523e-01, - 7.207701e-01, 7.229794e-01, 7.251800e-01, 7.273721e-01, - 7.295557e-01, 7.317307e-01, 7.338974e-01, 7.360555e-01, - 7.382053e-01, 7.403467e-01, 7.424797e-01, 7.446045e-01, - 7.467209e-01, 7.488291e-01, 7.509291e-01, 7.530208e-01, - 7.551044e-01, 7.571798e-01, 7.592472e-01, 7.613064e-01, - 7.633576e-01, 7.654008e-01, 7.674360e-01, 7.694633e-01, - 7.714826e-01, 7.734940e-01, 7.754975e-01, 7.774932e-01, - 7.794811e-01, 7.814612e-01, 7.834335e-01, 7.853983e-01, - 7.853983e-01 - }; - - -/***************************************************************************** -Function: Arc tangent - -Syntax: angle = fast_atan2(y, x); -REAL y y component of input vector -REAL x x component of input vector -REAL angle angle of vector (x, y) in radians - -Description: This function calculates the angle of the vector (x,y) based -on a table lookup and linear interpolation. The table uses -a 256 point table covering -45 to +45 degrees and uses -symetry to determine the final angle value in the range of --180 to 180 degrees. Note that this function uses the small -angle approximation for values close to zero. This routine -calculates the arc tangent with an average error of -+/- 0.045 degrees. -*****************************************************************************/ - -REAL -gr_fast_atan2f(REAL y, REAL x) -{ - REAL x_abs, y_abs, z; - REAL alpha, angle, base_angle; - int index; - - /* don't divide by zero! */ // FIXME could get hosed with -0.0 - if ((y == 0.0) && (x == 0.0)) - return 0.0; - - /* normalize to +/- 45 degree range */ - y_abs = fabs(y); - x_abs = fabs(x); - //z = (y_abs < x_abs ? y_abs / x_abs : x_abs / y_abs); - if (y_abs < x_abs) - z = y_abs / x_abs; - else - z = x_abs / y_abs; - - /* when ratio approaches the table resolution, the angle is */ - /* best approximated with the argument itself... */ - if (z < TAN_MAP_RES) - base_angle = z; - else { - /* find index and interpolation value */ - alpha = z * (REAL) TAN_MAP_SIZE - .5; - index = (int) alpha; - alpha -= (REAL) index; - /* determine base angle based on quadrant and */ - /* add or subtract table value from base angle based on quadrant */ - base_angle = fast_atan_table[index]; - base_angle += - (fast_atan_table[index + 1] - fast_atan_table[index]) * alpha; - } - - if (x_abs > y_abs) { /* -45 -> 45 or 135 -> 225 */ - if (x >= 0.0) { /* -45 -> 45 */ - if (y >= 0.0) - angle = base_angle; /* 0 -> 45, angle OK */ - else - angle = -base_angle; /* -45 -> 0, angle = -angle */ - } else { /* 135 -> 180 or 180 -> -135 */ - angle = 3.14159265358979323846; - if (y >= 0.0) - angle -= base_angle; /* 135 -> 180, angle = 180 - angle */ - else - angle = base_angle - angle; /* 180 -> -135, angle = angle - 180 */ - } - } else { /* 45 -> 135 or -135 -> -45 */ - if (y >= 0.0) { /* 45 -> 135 */ - angle = 1.57079632679489661923; - if (x >= 0.0) - angle -= base_angle; /* 45 -> 90, angle = 90 - angle */ - else - angle += base_angle; /* 90 -> 135, angle = 90 + angle */ - } else { /* -135 -> -45 */ - angle = -1.57079632679489661923; - if (x >= 0.0) - angle += base_angle; /* -90 -> -45, angle = -90 + angle */ - else - angle -= base_angle; /* -135 -> -90, angle = -90 - angle */ - } - } - -#ifdef ZERO_TO_TWOPI - if (angle < 0) - return (angle + TWOPI); - else - return (angle); -#else - return (angle); -#endif -} - diff --git a/gnuradio-runtime/lib/gr_feval.cc b/gnuradio-runtime/lib/gr_feval.cc deleted file mode 100644 index 89f09984cf..0000000000 --- a/gnuradio-runtime/lib/gr_feval.cc +++ /dev/null @@ -1,132 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gr_feval.h> - -gr_feval_dd::~gr_feval_dd(){} - -double -gr_feval_dd::eval(double x) -{ - return 0; -} - -double -gr_feval_dd::calleval(double x) -{ - return eval(x); -} - -// ---------------------------------------------------------------- - -gr_feval_cc::~gr_feval_cc(){} - -gr_complex -gr_feval_cc::eval(gr_complex x) -{ - return 0; -} - -gr_complex -gr_feval_cc::calleval(gr_complex x) -{ - return eval(x); -} - -// ---------------------------------------------------------------- - -gr_feval_ll::~gr_feval_ll(){} - -long -gr_feval_ll::eval(long x) -{ - return 0; -} - -long -gr_feval_ll::calleval(long x) -{ - return eval(x); -} - -// ---------------------------------------------------------------- - -gr_feval::~gr_feval(){} - -void -gr_feval::eval(void) -{ - // nop -} - -void -gr_feval::calleval(void) -{ - eval(); -} - -// ---------------------------------------------------------------- - -gr_feval_p::~gr_feval_p(){} - -void -gr_feval_p::eval(pmt::pmt_t x) -{ - // nop -} - -void -gr_feval_p::calleval(pmt::pmt_t x) -{ - eval(x); -} - -/* - * Trivial examples showing C++ (transparently) calling Python - */ -double -gr_feval_dd_example(gr_feval_dd *f, double x) -{ - return f->calleval(x); -} - -gr_complex -gr_feval_cc_example(gr_feval_cc *f, gr_complex x) -{ - return f->calleval(x); -} - -long -gr_feval_ll_example(gr_feval_ll *f, long x) -{ - return f->calleval(x); -} - -void -gr_feval_example(gr_feval *f) -{ - f->calleval(); -} diff --git a/gnuradio-runtime/lib/gr_flat_flowgraph.cc b/gnuradio-runtime/lib/gr_flat_flowgraph.cc deleted file mode 100644 index de1e227ef0..0000000000 --- a/gnuradio-runtime/lib/gr_flat_flowgraph.cc +++ /dev/null @@ -1,427 +0,0 @@ -/* -*- 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_flat_flowgraph.h> -#include <gr_block_detail.h> -#include <gr_io_signature.h> -#include <gr_buffer.h> -#include <gr_prefs.h> -#include <volk/volk.h> -#include <iostream> -#include <map> -#include <boost/format.hpp> - -#define GR_FLAT_FLOWGRAPH_DEBUG 0 - -// 32Kbyte buffer size between blocks -#define GR_FIXED_BUFFER_SIZE (32*(1L<<10)) - -static const unsigned int s_fixed_buffer_size = GR_FIXED_BUFFER_SIZE; - -gr_flat_flowgraph_sptr -gr_make_flat_flowgraph() -{ - return gr_flat_flowgraph_sptr(new gr_flat_flowgraph()); -} - -gr_flat_flowgraph::gr_flat_flowgraph() -{ -} - -gr_flat_flowgraph::~gr_flat_flowgraph() -{ -} - -void -gr_flat_flowgraph::setup_connections() -{ - gr_basic_block_vector_t blocks = calc_used_blocks(); - - // Assign block details to blocks - for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) - cast_to_block_sptr(*p)->set_detail(allocate_block_detail(*p)); - - // Connect inputs to outputs for each block - for(gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { - connect_block_inputs(*p); - - gr_block_sptr block = cast_to_block_sptr(*p); - block->set_unaligned(0); - block->set_is_unaligned(false); - } - - // Connect message ports connetions - for(gr_msg_edge_viter_t i = d_msg_edges.begin(); i != d_msg_edges.end(); i++){ - if(GR_FLAT_FLOWGRAPH_DEBUG) - std::cout << boost::format("flat_fg connecting msg primitives: (%s, %s)->(%s, %s)\n") % - i->src().block() % i->src().port() % - i->dst().block() % i->dst().port(); - i->src().block()->message_port_sub( i->src().port(), pmt::cons(i->dst().block()->alias_pmt(), i->dst().port()) ); - } - -} - -gr_block_detail_sptr -gr_flat_flowgraph::allocate_block_detail(gr_basic_block_sptr block) -{ - int ninputs = calc_used_ports(block, true).size(); - int noutputs = calc_used_ports(block, false).size(); - gr_block_detail_sptr detail = gr_make_block_detail(ninputs, noutputs); - - gr_block_sptr grblock = cast_to_block_sptr(block); - if(!grblock) - throw std::runtime_error("allocate_block_detail found non-gr_block"); - - if (GR_FLAT_FLOWGRAPH_DEBUG) - std::cout << "Creating block detail for " << block << std::endl; - - for (int i = 0; i < noutputs; i++) { - grblock->expand_minmax_buffer(i); - - gr_buffer_sptr buffer = allocate_buffer(block, i); - if (GR_FLAT_FLOWGRAPH_DEBUG) - std::cout << "Allocated buffer for output " << block << ":" << i << std::endl; - detail->set_output(i, buffer); - - // Update the block's max_output_buffer based on what was actually allocated. - grblock->set_max_output_buffer(i, buffer->bufsize()); - } - - return detail; -} - -gr_buffer_sptr -gr_flat_flowgraph::allocate_buffer(gr_basic_block_sptr block, int port) -{ - gr_block_sptr grblock = cast_to_block_sptr(block); - if (!grblock) - throw std::runtime_error("allocate_buffer found non-gr_block"); - int item_size = block->output_signature()->sizeof_stream_item(port); - - // *2 because we're now only filling them 1/2 way in order to - // increase the available parallelism when using the TPB scheduler. - // (We're double buffering, where we used to single buffer) - int nitems = s_fixed_buffer_size * 2 / item_size; - - // Make sure there are at least twice the output_multiple no. of items - if (nitems < 2*grblock->output_multiple()) // Note: this means output_multiple() - nitems = 2*grblock->output_multiple(); // can't be changed by block dynamically - - // If any downstream blocks are decimators and/or have a large output_multiple, - // ensure we have a buffer at least twice their decimation factor*output_multiple - gr_basic_block_vector_t blocks = calc_downstream_blocks(block, port); - - // limit buffer size if indicated - if(grblock->max_output_buffer(port) > 0) { -// std::cout << "constraining output items to " << block->max_output_buffer(port) << "\n"; - nitems = std::min((long)nitems, (long)grblock->max_output_buffer(port)); - nitems -= nitems%grblock->output_multiple(); - if( nitems < 1 ) - throw std::runtime_error("problems allocating a buffer with the given max output buffer constraint!"); - } - else if(grblock->min_output_buffer(port) > 0) { - nitems = std::max((long)nitems, (long)grblock->min_output_buffer(port)); - nitems -= nitems%grblock->output_multiple(); - if( nitems < 1 ) - throw std::runtime_error("problems allocating a buffer with the given min output buffer constraint!"); - } - - for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { - gr_block_sptr dgrblock = cast_to_block_sptr(*p); - if (!dgrblock) - throw std::runtime_error("allocate_buffer found non-gr_block"); - - double decimation = (1.0/dgrblock->relative_rate()); - int multiple = dgrblock->output_multiple(); - int history = dgrblock->history(); - nitems = std::max(nitems, static_cast<int>(2*(decimation*multiple+history))); - } - -// std::cout << "gr_make_buffer(" << nitems << ", " << item_size << ", " << grblock << "\n"; - return gr_make_buffer(nitems, item_size, grblock); -} - -void -gr_flat_flowgraph::connect_block_inputs(gr_basic_block_sptr block) -{ - gr_block_sptr grblock = cast_to_block_sptr(block); - if (!grblock) - throw std::runtime_error("connect_block_inputs found non-gr_block"); - - // Get its detail and edges that feed into it - gr_block_detail_sptr detail = grblock->detail(); - gr_edge_vector_t in_edges = calc_upstream_edges(block); - - // For each edge that feeds into it - for (gr_edge_viter_t e = in_edges.begin(); e != in_edges.end(); e++) { - // Set the buffer reader on the destination port to the output - // buffer on the source port - int dst_port = e->dst().port(); - int src_port = e->src().port(); - gr_basic_block_sptr src_block = e->src().block(); - gr_block_sptr src_grblock = cast_to_block_sptr(src_block); - if (!src_grblock) - throw std::runtime_error("connect_block_inputs found non-gr_block"); - gr_buffer_sptr src_buffer = src_grblock->detail()->output(src_port); - - if (GR_FLAT_FLOWGRAPH_DEBUG) - std::cout << "Setting input " << dst_port << " from edge " << (*e) << std::endl; - - detail->set_input(dst_port, gr_buffer_add_reader(src_buffer, grblock->history()-1, grblock)); - } -} - -void -gr_flat_flowgraph::merge_connections(gr_flat_flowgraph_sptr old_ffg) -{ - // Allocate block details if needed. Only new blocks that aren't pruned out - // by flattening will need one; existing blocks still in the new flowgraph will - // already have one. - for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { - gr_block_sptr block = cast_to_block_sptr(*p); - - if (!block->detail()) { - if (GR_FLAT_FLOWGRAPH_DEBUG) - std::cout << "merge: allocating new detail for block " << (*p) << std::endl; - block->set_detail(allocate_block_detail(block)); - } - else - if (GR_FLAT_FLOWGRAPH_DEBUG) - std::cout << "merge: reusing original detail for block " << (*p) << std::endl; - } - - // Calculate the old edges that will be going away, and clear the buffer readers - // on the RHS. - for (gr_edge_viter_t old_edge = old_ffg->d_edges.begin(); old_edge != old_ffg->d_edges.end(); old_edge++) { - if (GR_FLAT_FLOWGRAPH_DEBUG) - std::cout << "merge: testing old edge " << (*old_edge) << "..."; - - gr_edge_viter_t new_edge; - for (new_edge = d_edges.begin(); new_edge != d_edges.end(); new_edge++) - if (new_edge->src() == old_edge->src() && - new_edge->dst() == old_edge->dst()) - break; - - if (new_edge == d_edges.end()) { // not found in new edge list - if (GR_FLAT_FLOWGRAPH_DEBUG) - std::cout << "not in new edge list" << std::endl; - // zero the buffer reader on RHS of old edge - gr_block_sptr block(cast_to_block_sptr(old_edge->dst().block())); - int port = old_edge->dst().port(); - block->detail()->set_input(port, gr_buffer_reader_sptr()); - } - else { - if (GR_FLAT_FLOWGRAPH_DEBUG) - std::cout << "found in new edge list" << std::endl; - } - } - - // Now connect inputs to outputs, reusing old buffer readers if they exist - for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { - gr_block_sptr block = cast_to_block_sptr(*p); - - if (GR_FLAT_FLOWGRAPH_DEBUG) - std::cout << "merge: merging " << (*p) << "..."; - - if (old_ffg->has_block_p(*p)) { - // Block exists in old flow graph - if (GR_FLAT_FLOWGRAPH_DEBUG) - std::cout << "used in old flow graph" << std::endl; - gr_block_detail_sptr detail = block->detail(); - - // Iterate through the inputs and see what needs to be done - int ninputs = calc_used_ports(block, true).size(); // Might be different now - for (int i = 0; i < ninputs; i++) { - if (GR_FLAT_FLOWGRAPH_DEBUG) - std::cout << "Checking input " << block << ":" << i << "..."; - gr_edge edge = calc_upstream_edge(*p, i); - - // Fish out old buffer reader and see if it matches correct buffer from edge list - gr_block_sptr src_block = cast_to_block_sptr(edge.src().block()); - gr_block_detail_sptr src_detail = src_block->detail(); - gr_buffer_sptr src_buffer = src_detail->output(edge.src().port()); - gr_buffer_reader_sptr old_reader; - if (i < detail->ninputs()) // Don't exceed what the original detail has - old_reader = detail->input(i); - - // If there's a match, use it - if (old_reader && (src_buffer == old_reader->buffer())) { - if (GR_FLAT_FLOWGRAPH_DEBUG) - std::cout << "matched, reusing" << std::endl; - } - else { - if (GR_FLAT_FLOWGRAPH_DEBUG) - std::cout << "needs a new reader" << std::endl; - - // Create new buffer reader and assign - detail->set_input(i, gr_buffer_add_reader(src_buffer, block->history()-1, block)); - } - } - } - else { - // Block is new, it just needs buffer readers at this point - if (GR_FLAT_FLOWGRAPH_DEBUG) - std::cout << "new block" << std::endl; - connect_block_inputs(block); - - // Make sure all buffers are aligned - setup_buffer_alignment(block); - } - - // Now deal with the fact that the block details might have changed numbers of - // inputs and outputs vs. in the old flowgraph. - } -} - -void -gr_flat_flowgraph::setup_buffer_alignment(gr_block_sptr block) -{ - const int alignment = volk_get_alignment(); - for(int i = 0; i < block->detail()->ninputs(); i++) { - void *r = (void*)block->detail()->input(i)->read_pointer(); - unsigned long int ri = (unsigned long int)r % alignment; - //std::cerr << "reader: " << r << " alignment: " << ri << std::endl; - if(ri != 0) { - size_t itemsize = block->detail()->input(i)->get_sizeof_item(); - block->detail()->input(i)->update_read_pointer(alignment-ri/itemsize); - } - block->set_unaligned(0); - block->set_is_unaligned(false); - } - - for(int i = 0; i < block->detail()->noutputs(); i++) { - void *w = (void*)block->detail()->output(i)->write_pointer(); - unsigned long int wi = (unsigned long int)w % alignment; - //std::cerr << "writer: " << w << " alignment: " << wi << std::endl; - if(wi != 0) { - size_t itemsize = block->detail()->output(i)->get_sizeof_item(); - block->detail()->output(i)->update_write_pointer(alignment-wi/itemsize); - } - block->set_unaligned(0); - block->set_is_unaligned(false); - } -} - -std::string -gr_flat_flowgraph::edge_list() -{ - std::stringstream s; - for(gr_edge_viter_t e = d_edges.begin(); e != d_edges.end(); e++) - s << (*e) << std::endl; - return s.str(); -} - -void gr_flat_flowgraph::dump() -{ - for (gr_edge_viter_t e = d_edges.begin(); e != d_edges.end(); e++) - std::cout << " edge: " << (*e) << std::endl; - - for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { - std::cout << " block: " << (*p) << std::endl; - gr_block_detail_sptr detail = cast_to_block_sptr(*p)->detail(); - std::cout << " detail @" << detail << ":" << std::endl; - - int ni = detail->ninputs(); - int no = detail->noutputs(); - for (int i = 0; i < no; i++) { - gr_buffer_sptr buffer = detail->output(i); - std::cout << " output " << i << ": " << buffer << std::endl; - } - - for (int i = 0; i < ni; i++) { - gr_buffer_reader_sptr reader = detail->input(i); - std::cout << " reader " << i << ": " << reader - << " reading from buffer=" << reader->buffer() << std::endl; - } - } - -} - -gr_block_vector_t -gr_flat_flowgraph::make_block_vector(gr_basic_block_vector_t &blocks) -{ - gr_block_vector_t result; - for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { - result.push_back(cast_to_block_sptr(*p)); - } - - return result; -} - - -void gr_flat_flowgraph::clear_endpoint(const gr_msg_endpoint &e, bool is_src){ - for(size_t i=0; i<d_msg_edges.size(); i++){ - if(is_src){ - if(d_msg_edges[i].src() == e){ - d_msg_edges.erase(d_msg_edges.begin() + i); - i--; - } - } else { - if(d_msg_edges[i].dst() == e){ - d_msg_edges.erase(d_msg_edges.begin() + i); - i--; - } - } - } -} - -void gr_flat_flowgraph::replace_endpoint(const gr_msg_endpoint &e, const gr_msg_endpoint &r, bool is_src){ - size_t n_replr(0); - if(GR_FLAT_FLOWGRAPH_DEBUG) - std::cout << boost::format("gr_flat_flowgraph::replace_endpoint( %s, %s, %d )\n") % e.block()% r.block()% is_src; - for(size_t i=0; i<d_msg_edges.size(); i++){ - if(is_src){ - if(d_msg_edges[i].src() == e){ - if(GR_FLAT_FLOWGRAPH_DEBUG) - std::cout << boost::format("gr_flat_flowgraph::replace_endpoint() flattening to ( %s, %s )\n") % r.block()% d_msg_edges[i].dst().block(); - d_msg_edges.push_back( gr_msg_edge(r, d_msg_edges[i].dst() ) ); - n_replr++; - } - } else { - if(d_msg_edges[i].dst() == e){ - if(GR_FLAT_FLOWGRAPH_DEBUG) - std::cout << boost::format("gr_flat_flowgraph::replace_endpoint() flattening to ( %s, %s )\n") % r.block()% d_msg_edges[i].dst().block(); - d_msg_edges.push_back( gr_msg_edge(d_msg_edges[i].src(), r ) ); - n_replr++; - } - } - } -} - -void -gr_flat_flowgraph::enable_pc_rpc() -{ -#ifdef GR_PERFORMANCE_COUNTERS - if(gr_prefs::singleton()->get_bool("PerfCounters", "on", false)) { - gr_basic_block_viter_t p; - for(p = d_blocks.begin(); p != d_blocks.end(); p++) { - gr_block_sptr block = cast_to_block_sptr(*p); - if(!block->is_pc_rpc_set()) - block->setup_pc_rpc(); - } - } -#endif /* GR_PERFORMANCE_COUNTERS */ -} diff --git a/gnuradio-runtime/lib/gr_flat_flowgraph.h b/gnuradio-runtime/lib/gr_flat_flowgraph.h deleted file mode 100644 index 9c47a77e23..0000000000 --- a/gnuradio-runtime/lib/gr_flat_flowgraph.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_FLAT_FLOWGRAPH_H -#define INCLUDED_GR_FLAT_FLOWGRAPH_H - -#include <gr_runtime_api.h> -#include <gr_flowgraph.h> -#include <gr_block.h> - -// Create a shared pointer to a heap allocated gr_flat_flowgraph -// (types defined in gr_runtime_types.h) -GR_RUNTIME_API gr_flat_flowgraph_sptr gr_make_flat_flowgraph(); - -/*! - *\brief Class specializing gr_flat_flowgraph that has all nodes - * as gr_blocks, with no hierarchy - * \ingroup internal - */ -class GR_RUNTIME_API gr_flat_flowgraph : public gr_flowgraph -{ -public: - friend GR_RUNTIME_API gr_flat_flowgraph_sptr gr_make_flat_flowgraph(); - - // Destruct an arbitrary gr_flat_flowgraph - ~gr_flat_flowgraph(); - - // Wire gr_blocks together in new flat_flowgraph - void setup_connections(); - - // Merge applicable connections from existing flat flowgraph - void merge_connections(gr_flat_flowgraph_sptr sfg); - - // Return a string list of edges - std::string edge_list(); - - void dump(); - - /*! - * Make a vector of gr_block from a vector of gr_basic_block - */ - static gr_block_vector_t make_block_vector(gr_basic_block_vector_t &blocks); - - void replace_endpoint(const gr_msg_endpoint &e, const gr_msg_endpoint &r, bool is_src); - void clear_endpoint(const gr_msg_endpoint &e, bool is_src); - - /*! - * Enables export of perf. counters to ControlPort on all blocks in - * the flowgraph. - */ - void enable_pc_rpc(); - -private: - gr_flat_flowgraph(); - - gr_block_detail_sptr allocate_block_detail(gr_basic_block_sptr block); - gr_buffer_sptr allocate_buffer(gr_basic_block_sptr block, int port); - void connect_block_inputs(gr_basic_block_sptr block); - - /* When reusing a flowgraph's blocks, this call makes sure all of the - * buffer's are aligned at the machine's alignment boundary and tells - * the blocks that they are aligned. - * - * Called from both setup_connections and merge_connections for - * start and restarts. - */ - void setup_buffer_alignment(gr_block_sptr block); -}; - -#endif /* INCLUDED_GR_FLAT_FLOWGRAPH_H */ diff --git a/gnuradio-runtime/lib/gr_flowgraph.cc b/gnuradio-runtime/lib/gr_flowgraph.cc deleted file mode 100644 index 28cd693171..0000000000 --- a/gnuradio-runtime/lib/gr_flowgraph.cc +++ /dev/null @@ -1,514 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007,2011 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_flowgraph.h> -#include <gr_io_signature.h> -#include <stdexcept> -#include <sstream> -#include <iterator> - -#define GR_FLOWGRAPH_DEBUG 0 - -gr_edge::~gr_edge() -{ -} - -gr_flowgraph_sptr gr_make_flowgraph() -{ - return gr_flowgraph_sptr(new gr_flowgraph()); -} - -gr_flowgraph::gr_flowgraph() -{ -} - -gr_flowgraph::~gr_flowgraph() -{ -} - -template<class T> -static -std::vector<T> -unique_vector(std::vector<T> v) -{ - std::vector<T> result; - std::insert_iterator<std::vector<T> > inserter(result, result.begin()); - - sort(v.begin(), v.end()); - unique_copy(v.begin(), v.end(), inserter); - return result; -} - -void -gr_flowgraph::connect(const gr_endpoint &src, const gr_endpoint &dst) -{ - check_valid_port(src.block()->output_signature(), src.port()); - check_valid_port(dst.block()->input_signature(), dst.port()); - check_dst_not_used(dst); - check_type_match(src, dst); - - // All ist klar, Herr Kommisar - d_edges.push_back(gr_edge(src,dst)); -} - -void -gr_flowgraph::disconnect(const gr_endpoint &src, const gr_endpoint &dst) -{ - for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { - if (src == p->src() && dst == p->dst()) { - d_edges.erase(p); - return; - } - } - - std::stringstream msg; - msg << "cannot disconnect edge " << gr_edge(src, dst) << ", not found"; - throw std::invalid_argument(msg.str()); -} - -void -gr_flowgraph::validate() -{ - d_blocks = calc_used_blocks(); - - for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { - std::vector<int> used_ports; - int ninputs, noutputs; - - if (GR_FLOWGRAPH_DEBUG) - std::cout << "Validating block: " << (*p) << std::endl; - - used_ports = calc_used_ports(*p, true); // inputs - ninputs = used_ports.size(); - check_contiguity(*p, used_ports, true); // inputs - - used_ports = calc_used_ports(*p, false); // outputs - noutputs = used_ports.size(); - check_contiguity(*p, used_ports, false); // outputs - - if (!((*p)->check_topology(ninputs, noutputs))) { - std::stringstream msg; - msg << "check topology failed on " << (*p) - << " using ninputs=" << ninputs - << ", noutputs=" << noutputs; - throw std::runtime_error(msg.str()); - } - } -} - -void -gr_flowgraph::clear() -{ - // Boost shared pointers will deallocate as needed - d_blocks.clear(); - d_edges.clear(); -} - -void -gr_flowgraph::check_valid_port(gr_io_signature_sptr sig, int port) -{ - std::stringstream msg; - - if (port < 0) { - msg << "negative port number " << port << " is invalid"; - throw std::invalid_argument(msg.str()); - } - - int max = sig->max_streams(); - if (max != gr_io_signature::IO_INFINITE && port >= max) { - msg << "port number " << port << " exceeds max of "; - if (max == 0) - msg << "(none)"; - else - msg << max-1; - throw std::invalid_argument(msg.str()); - } -} - -void -gr_flowgraph::check_valid_port(const gr_msg_endpoint &e) -{ - if (GR_FLOWGRAPH_DEBUG) - std::cout << "check_valid_port( " << e.block() << ", " << e.port() << ")\n"; - - if(!e.block()->has_msg_port(e.port())) - throw std::invalid_argument("invalid msg port in connect() or disconnect()"); -} - -void -gr_flowgraph::check_dst_not_used(const gr_endpoint &dst) -{ - // A destination is in use if it is already on the edge list - for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) - if (p->dst() == dst) { - std::stringstream msg; - msg << "destination already in use by edge " << (*p); - throw std::invalid_argument(msg.str()); - } -} - -void -gr_flowgraph::check_type_match(const gr_endpoint &src, const gr_endpoint &dst) -{ - int src_size = src.block()->output_signature()->sizeof_stream_item(src.port()); - int dst_size = dst.block()->input_signature()->sizeof_stream_item(dst.port()); - - if (src_size != dst_size) { - std::stringstream msg; - msg << "itemsize mismatch: " << src << " using " << src_size - << ", " << dst << " using " << dst_size; - throw std::invalid_argument(msg.str()); - } -} - -gr_basic_block_vector_t -gr_flowgraph::calc_used_blocks() -{ - gr_basic_block_vector_t tmp; - - // make sure free standing message blocks are included - for (gr_msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) { -// for now only blocks receiving messages get a thread context - uncomment to allow senders to also obtain one -// tmp.push_back(p->src().block()); - tmp.push_back(p->dst().block()); - } - - // Collect all blocks in the edge list - for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { - tmp.push_back(p->src().block()); - tmp.push_back(p->dst().block()); - } - - return unique_vector<gr_basic_block_sptr>(tmp); -} - -std::vector<int> -gr_flowgraph::calc_used_ports(gr_basic_block_sptr block, bool check_inputs) -{ - std::vector<int> tmp; - - // Collect all seen ports - gr_edge_vector_t edges = calc_connections(block, check_inputs); - for (gr_edge_viter_t p = edges.begin(); p != edges.end(); p++) { - if (check_inputs == true) - tmp.push_back(p->dst().port()); - else - tmp.push_back(p->src().port()); - } - - return unique_vector<int>(tmp); -} - -gr_edge_vector_t -gr_flowgraph::calc_connections(gr_basic_block_sptr block, bool check_inputs) -{ - gr_edge_vector_t result; - - for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { - if (check_inputs) { - if (p->dst().block() == block) - result.push_back(*p); - } - else { - if (p->src().block() == block) - result.push_back(*p); - } - } - - return result; // assumes no duplicates -} - -void -gr_flowgraph::check_contiguity(gr_basic_block_sptr block, - const std::vector<int> &used_ports, - bool check_inputs) -{ - std::stringstream msg; - - gr_io_signature_sptr sig = - check_inputs ? block->input_signature() : block->output_signature(); - - int nports = used_ports.size(); - int min_ports = sig->min_streams(); - int max_ports = sig->max_streams(); - - if (nports == 0 && min_ports == 0) - return; - - if (nports < min_ports) { - msg << block << ": insufficient connected " - << (check_inputs ? "input ports " : "output ports ") - << "(" << min_ports << " needed, " << nports << " connected)"; - throw std::runtime_error(msg.str()); - } - - if (nports > max_ports && max_ports != gr_io_signature::IO_INFINITE) { - msg << block << ": too many connected " - << (check_inputs ? "input ports " : "output ports ") - << "(" << max_ports << " allowed, " << nports << " connected)"; - throw std::runtime_error(msg.str()); - } - - if (used_ports[nports-1]+1 != nports) { - for (int i = 0; i < nports; i++) { - if (used_ports[i] != i) { - msg << block << ": missing connection " - << (check_inputs ? "to input port " : "from output port ") - << i; - throw std::runtime_error(msg.str()); - } - } - } -} - -gr_basic_block_vector_t -gr_flowgraph::calc_downstream_blocks(gr_basic_block_sptr block, int port) -{ - gr_basic_block_vector_t tmp; - - for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) - if (p->src() == gr_endpoint(block, port)) - tmp.push_back(p->dst().block()); - - return unique_vector<gr_basic_block_sptr>(tmp); -} - -gr_basic_block_vector_t -gr_flowgraph::calc_downstream_blocks(gr_basic_block_sptr block) -{ - gr_basic_block_vector_t tmp; - - for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) - if (p->src().block() == block) - tmp.push_back(p->dst().block()); - - return unique_vector<gr_basic_block_sptr>(tmp); -} - -gr_edge_vector_t -gr_flowgraph::calc_upstream_edges(gr_basic_block_sptr block) -{ - gr_edge_vector_t result; - - for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) - if (p->dst().block() == block) - result.push_back(*p); - - return result; // Assume no duplicates -} - -bool -gr_flowgraph::has_block_p(gr_basic_block_sptr block) -{ - gr_basic_block_viter_t result; - result = std::find(d_blocks.begin(), d_blocks.end(), block); - return (result != d_blocks.end()); -} - -gr_edge -gr_flowgraph::calc_upstream_edge(gr_basic_block_sptr block, int port) -{ - gr_edge result; - - for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { - if (p->dst() == gr_endpoint(block, port)) { - result = (*p); - break; - } - } - - return result; -} - -std::vector<gr_basic_block_vector_t> -gr_flowgraph::partition() -{ - std::vector<gr_basic_block_vector_t> result; - gr_basic_block_vector_t blocks = calc_used_blocks(); - gr_basic_block_vector_t graph; - - while (blocks.size() > 0) { - graph = calc_reachable_blocks(blocks[0], blocks); - assert(graph.size()); - result.push_back(topological_sort(graph)); - - for (gr_basic_block_viter_t p = graph.begin(); p != graph.end(); p++) - blocks.erase(find(blocks.begin(), blocks.end(), *p)); - } - - return result; -} - -gr_basic_block_vector_t -gr_flowgraph::calc_reachable_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks) -{ - gr_basic_block_vector_t result; - - // Mark all blocks as unvisited - for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) - (*p)->set_color(gr_basic_block::WHITE); - - // Recursively mark all reachable blocks - reachable_dfs_visit(block, blocks); - - // Collect all the blocks that have been visited - for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) - if ((*p)->color() == gr_basic_block::BLACK) - result.push_back(*p); - - return result; -} - -// Recursively mark all reachable blocks from given block and block list -void -gr_flowgraph::reachable_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks) -{ - // Mark the current one as visited - block->set_color(gr_basic_block::BLACK); - - // Recurse into adjacent vertices - gr_basic_block_vector_t adjacent = calc_adjacent_blocks(block, blocks); - - for (gr_basic_block_viter_t p = adjacent.begin(); p != adjacent.end(); p++) - if ((*p)->color() == gr_basic_block::WHITE) - reachable_dfs_visit(*p, blocks); -} - -// Return a list of block adjacent to a given block along any edge -gr_basic_block_vector_t -gr_flowgraph::calc_adjacent_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks) -{ - gr_basic_block_vector_t tmp; - - // Find any blocks that are inputs or outputs - for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { - if (p->src().block() == block) - tmp.push_back(p->dst().block()); - if (p->dst().block() == block) - tmp.push_back(p->src().block()); - } - - return unique_vector<gr_basic_block_sptr>(tmp); -} - -gr_basic_block_vector_t -gr_flowgraph::topological_sort(gr_basic_block_vector_t &blocks) -{ - gr_basic_block_vector_t tmp; - gr_basic_block_vector_t result; - tmp = sort_sources_first(blocks); - - // Start 'em all white - for (gr_basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++) - (*p)->set_color(gr_basic_block::WHITE); - - for (gr_basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++) { - if ((*p)->color() == gr_basic_block::WHITE) - topological_dfs_visit(*p, result); - } - - reverse(result.begin(), result.end()); - return result; -} - -gr_basic_block_vector_t -gr_flowgraph::sort_sources_first(gr_basic_block_vector_t &blocks) -{ - gr_basic_block_vector_t sources, nonsources, result; - - for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { - if (source_p(*p)) - sources.push_back(*p); - else - nonsources.push_back(*p); - } - - for (gr_basic_block_viter_t p = sources.begin(); p != sources.end(); p++) - result.push_back(*p); - - for (gr_basic_block_viter_t p = nonsources.begin(); p != nonsources.end(); p++) - result.push_back(*p); - - return result; -} - -bool -gr_flowgraph::source_p(gr_basic_block_sptr block) -{ - return (calc_upstream_edges(block).size() == 0); -} - -void -gr_flowgraph::topological_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &output) -{ - block->set_color(gr_basic_block::GREY); - gr_basic_block_vector_t blocks(calc_downstream_blocks(block)); - - for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { - switch ((*p)->color()) { - case gr_basic_block::WHITE: - topological_dfs_visit(*p, output); - break; - - case gr_basic_block::GREY: - throw std::runtime_error("flow graph has loops!"); - - case gr_basic_block::BLACK: - continue; - - default: - throw std::runtime_error("invalid color on block!"); - } - } - - block->set_color(gr_basic_block::BLACK); - output.push_back(block); -} - -void gr_flowgraph::connect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst){ - check_valid_port(src); - check_valid_port(dst); - for (gr_msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) { - if(p->src() == src && p->dst() == dst){ - throw std::runtime_error("connect called on already connected edge!"); - } - } - d_msg_edges.push_back(gr_msg_edge(src,dst)); -} - -void gr_flowgraph::disconnect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst){ - check_valid_port(src); - check_valid_port(dst); - for (gr_msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) { - if(p->src() == src && p->dst() == dst){ - d_msg_edges.erase(p); - return; - } - } - throw std::runtime_error("disconnect called on non-connected edge!"); -} - - diff --git a/gnuradio-runtime/lib/gr_hier_block2.cc b/gnuradio-runtime/lib/gr_hier_block2.cc deleted file mode 100644 index 9e924fdaf5..0000000000 --- a/gnuradio-runtime/lib/gr_hier_block2.cc +++ /dev/null @@ -1,153 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2007,2008 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_hier_block2.h> -#include <gr_io_signature.h> -#include <gr_hier_block2_detail.h> -#include <iostream> - -#define GR_HIER_BLOCK2_DEBUG 0 - - -gr_hier_block2_sptr -gr_make_hier_block2(const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature) -{ - return gnuradio::get_initial_sptr(new gr_hier_block2(name, input_signature, output_signature)); -} - -gr_hier_block2::gr_hier_block2(const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature) - : gr_basic_block(name, input_signature, output_signature), - d_detail(new gr_hier_block2_detail(this)), - hier_message_ports_in(pmt::PMT_NIL), - hier_message_ports_out(pmt::PMT_NIL) -{ - // This bit of magic ensures that self() works in the constructors of derived classes. - gnuradio::detail::sptr_magic::create_and_stash_initial_sptr(this); -} - -gr_hier_block2::~gr_hier_block2() -{ - delete d_detail; -} - -gr_hier_block2::opaque_self -gr_hier_block2::self() -{ - return shared_from_this(); -} - -gr_hier_block2_sptr -gr_hier_block2::to_hier_block2() -{ - return cast_to_hier_block2_sptr(shared_from_this()); -} - -void -gr_hier_block2::connect(gr_basic_block_sptr block) -{ - d_detail->connect(block); -} - -void -gr_hier_block2::connect(gr_basic_block_sptr src, int src_port, - gr_basic_block_sptr dst, int dst_port) -{ - d_detail->connect(src, src_port, dst, dst_port); -} - -void -gr_hier_block2::msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, - gr_basic_block_sptr dst, pmt::pmt_t dstport) -{ - if(!pmt::is_symbol(srcport)){throw std::runtime_error("bad port id"); } - d_detail->msg_connect(src, srcport, dst, dstport); -} - -void -gr_hier_block2::msg_connect(gr_basic_block_sptr src, std::string srcport, - gr_basic_block_sptr dst, std::string dstport) -{ - d_detail->msg_connect(src, pmt::mp(srcport), dst, pmt::mp(dstport)); -} - -void -gr_hier_block2::msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport, - gr_basic_block_sptr dst, pmt::pmt_t dstport) -{ - if(!pmt::is_symbol(srcport)){throw std::runtime_error("bad port id"); } - d_detail->msg_disconnect(src, srcport, dst, dstport); -} - -void -gr_hier_block2::msg_disconnect(gr_basic_block_sptr src, std::string srcport, - gr_basic_block_sptr dst, std::string dstport) -{ - d_detail->msg_disconnect(src, pmt::mp(srcport), dst, pmt::mp(dstport)); -} - -void -gr_hier_block2::disconnect(gr_basic_block_sptr block) -{ - d_detail->disconnect(block); -} - -void -gr_hier_block2::disconnect(gr_basic_block_sptr src, int src_port, - gr_basic_block_sptr dst, int dst_port) -{ - d_detail->disconnect(src, src_port, dst, dst_port); -} - -void -gr_hier_block2::disconnect_all() -{ - d_detail->disconnect_all(); -} - -void -gr_hier_block2::lock() -{ - d_detail->lock(); -} - -void -gr_hier_block2::unlock() -{ - d_detail->unlock(); -} - - -gr_flat_flowgraph_sptr -gr_hier_block2::flatten() const -{ - gr_flat_flowgraph_sptr new_ffg = gr_make_flat_flowgraph(); - d_detail->flatten_aux(new_ffg); - return new_ffg; -} diff --git a/gnuradio-runtime/lib/gr_hier_block2_detail.cc b/gnuradio-runtime/lib/gr_hier_block2_detail.cc deleted file mode 100644 index c8564f6698..0000000000 --- a/gnuradio-runtime/lib/gr_hier_block2_detail.cc +++ /dev/null @@ -1,641 +0,0 @@ -/* - * Copyright 2006,2007,2009 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_hier_block2_detail.h> -#include <gr_io_signature.h> -#include <gr_prefs.h> -#include <stdexcept> -#include <sstream> -#include <boost/format.hpp> - -#define GR_HIER_BLOCK2_DETAIL_DEBUG 0 - -gr_hier_block2_detail::gr_hier_block2_detail(gr_hier_block2 *owner) : - d_owner(owner), - d_parent_detail(0), - d_fg(gr_make_flowgraph()) -{ - int min_inputs = owner->input_signature()->min_streams(); - int max_inputs = owner->input_signature()->max_streams(); - int min_outputs = owner->output_signature()->min_streams(); - int max_outputs = owner->output_signature()->max_streams(); - - if (max_inputs == gr_io_signature::IO_INFINITE || - max_outputs == gr_io_signature::IO_INFINITE || - (min_inputs != max_inputs) ||(min_outputs != max_outputs) ) { - std::stringstream msg; - msg << "Hierarchical blocks do not yet support arbitrary or" - << " variable numbers of inputs or outputs (" << d_owner->name() << ")"; - throw std::runtime_error(msg.str()); - } - - d_inputs = std::vector<gr_endpoint_vector_t>(max_inputs); - d_outputs = gr_endpoint_vector_t(max_outputs); -} - - -gr_hier_block2_detail::~gr_hier_block2_detail() -{ - d_owner = 0; // Don't use delete, we didn't allocate -} - -void -gr_hier_block2_detail::connect(gr_basic_block_sptr block) -{ - std::stringstream msg; - - // Check if duplicate - if (std::find(d_blocks.begin(), d_blocks.end(), block) != d_blocks.end()) { - msg << "Block " << block << " already connected."; - throw std::invalid_argument(msg.str()); - } - - // Check if has inputs or outputs - if (block->input_signature()->max_streams() != 0 || - block->output_signature()->max_streams() != 0) { - msg << "Block " << block << " must not have any input or output ports"; - throw std::invalid_argument(msg.str()); - } - - gr_hier_block2_sptr hblock(cast_to_hier_block2_sptr(block)); - - if (hblock && hblock.get() != d_owner) { - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "connect: block is hierarchical, setting parent to " << this << std::endl; - hblock->d_detail->d_parent_detail = this; - } - - d_blocks.push_back(block); -} - -void -gr_hier_block2_detail::connect(gr_basic_block_sptr src, int src_port, - gr_basic_block_sptr dst, int dst_port) -{ - std::stringstream msg; - - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "connecting: " << gr_endpoint(src, src_port) - << " -> " << gr_endpoint(dst, dst_port) << std::endl; - - if (src.get() == dst.get()) - throw std::invalid_argument("connect: src and destination blocks cannot be the same"); - - gr_hier_block2_sptr src_block(cast_to_hier_block2_sptr(src)); - gr_hier_block2_sptr dst_block(cast_to_hier_block2_sptr(dst)); - - if (src_block && src.get() != d_owner) { - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "connect: src is hierarchical, setting parent to " << this << std::endl; - src_block->d_detail->d_parent_detail = this; - } - - if (dst_block && dst.get() != d_owner) { - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "connect: dst is hierarchical, setting parent to " << this << std::endl; - dst_block->d_detail->d_parent_detail = this; - } - - // Connections to block inputs or outputs - int max_port; - if (src.get() == d_owner) { - max_port = src->input_signature()->max_streams(); - if ((max_port != -1 && (src_port >= max_port)) || src_port < 0) { - msg << "source port " << src_port << " out of range for " << src; - throw std::invalid_argument(msg.str()); - } - - return connect_input(src_port, dst_port, dst); - } - - if (dst.get() == d_owner) { - max_port = dst->output_signature()->max_streams(); - if ((max_port != -1 && (dst_port >= max_port)) || dst_port < 0) { - msg << "destination port " << dst_port << " out of range for " << dst; - throw std::invalid_argument(msg.str()); - } - - return connect_output(dst_port, src_port, src); - } - - // Internal connections - d_fg->connect(src, src_port, dst, dst_port); - - // TODO: connects to NC -} - -void -gr_hier_block2_detail::msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, - gr_basic_block_sptr dst, pmt::pmt_t dstport) -{ - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "connecting message port..." << std::endl; - - // register the subscription -// this is done later... -// src->message_port_sub(srcport, pmt::cons(dst->alias_pmt(), dstport)); - - // add block uniquely to list to internal blocks - if (std::find(d_blocks.begin(), d_blocks.end(), dst) == d_blocks.end()){ - d_blocks.push_back(src); - d_blocks.push_back(dst); - } - - bool hier_out = (d_owner == src.get()) && src->message_port_is_hier_out(srcport);; - bool hier_in = (d_owner == dst.get()) && dst->message_port_is_hier_in(dstport); - - gr_hier_block2_sptr src_block(cast_to_hier_block2_sptr(src)); - gr_hier_block2_sptr dst_block(cast_to_hier_block2_sptr(dst)); - - if (src_block && src.get() != d_owner) { - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "connect: src is hierarchical, setting parent to " << this << std::endl; - src_block->d_detail->d_parent_detail = this; - } - - if (dst_block && dst.get() != d_owner) { - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "connect: dst is hierarchical, setting parent to " << this << std::endl; - dst_block->d_detail->d_parent_detail = this; - } - - // add edge for this message connection - if(GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << boost::format("connect( (%s, %s, %d), (%s, %s, %d) )\n") % - src % srcport % hier_out % - dst % dstport % hier_in; - d_fg->connect( gr_msg_endpoint(src, srcport, hier_out), gr_msg_endpoint(dst, dstport, hier_in)); -} - -void -gr_hier_block2_detail::msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport, - gr_basic_block_sptr dst, pmt::pmt_t dstport) -{ - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "disconnecting message port..." << std::endl; - - // unregister the subscription - if already subscribed - src->message_port_unsub(srcport, pmt::cons(dst->alias_pmt(), dstport)); - - // remove edge for this message connection - bool hier_out = (d_owner == src.get()) && src->message_port_is_hier_out(srcport);; - bool hier_in = (d_owner == dst.get()) && dst->message_port_is_hier_in(dstport); - d_fg->disconnect( gr_msg_endpoint(src, srcport, hier_out), gr_msg_endpoint(dst, dstport, hier_in)); -} - -void -gr_hier_block2_detail::disconnect(gr_basic_block_sptr block) -{ - // Check on singleton list - for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { - if (*p == block) { - d_blocks.erase(p); - - gr_hier_block2_sptr hblock(cast_to_hier_block2_sptr(block)); - if (block && block.get() != d_owner) { - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "disconnect: block is hierarchical, clearing parent" << std::endl; - hblock->d_detail->d_parent_detail = 0; - } - - return; - } - } - - // Otherwise find all edges containing block - gr_edge_vector_t edges, tmp = d_fg->edges(); - gr_edge_vector_t::iterator p; - for (p = tmp.begin(); p != tmp.end(); p++) { - if ((*p).src().block() == block || (*p).dst().block() == block) { - edges.push_back(*p); - - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "disconnect: block found in edge " << (*p) << std::endl; - } - } - - if (edges.size() == 0) { - std::stringstream msg; - msg << "cannot disconnect block " << block << ", not found"; - throw std::invalid_argument(msg.str()); - } - - for (p = edges.begin(); p != edges.end(); p++) { - disconnect((*p).src().block(), (*p).src().port(), - (*p).dst().block(), (*p).dst().port()); - } -} - -void -gr_hier_block2_detail::disconnect(gr_basic_block_sptr src, int src_port, - gr_basic_block_sptr dst, int dst_port) -{ - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "disconnecting: " << gr_endpoint(src, src_port) - << " -> " << gr_endpoint(dst, dst_port) << std::endl; - - if (src.get() == dst.get()) - throw std::invalid_argument("disconnect: source and destination blocks cannot be the same"); - - gr_hier_block2_sptr src_block(cast_to_hier_block2_sptr(src)); - gr_hier_block2_sptr dst_block(cast_to_hier_block2_sptr(dst)); - - if (src_block && src.get() != d_owner) { - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "disconnect: src is hierarchical, clearing parent" << std::endl; - src_block->d_detail->d_parent_detail = 0; - } - - if (dst_block && dst.get() != d_owner) { - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "disconnect: dst is hierarchical, clearing parent" << std::endl; - dst_block->d_detail->d_parent_detail = 0; - } - - if (src.get() == d_owner) - return disconnect_input(src_port, dst_port, dst); - - if (dst.get() == d_owner) - return disconnect_output(dst_port, src_port, src); - - // Internal connections - d_fg->disconnect(src, src_port, dst, dst_port); -} - -void -gr_hier_block2_detail::connect_input(int my_port, int port, gr_basic_block_sptr block) -{ - std::stringstream msg; - - if (my_port < 0 || my_port >= (signed)d_inputs.size()) { - msg << "input port " << my_port << " out of range for " << block; - throw std::invalid_argument(msg.str()); - } - - gr_endpoint_vector_t &endps = d_inputs[my_port]; - gr_endpoint endp(block, port); - - gr_endpoint_viter_t p = std::find(endps.begin(), endps.end(), endp); - if (p != endps.end()) { - msg << "external input port " << my_port << " already wired to " << endp; - throw std::invalid_argument(msg.str()); - } - - endps.push_back(endp); -} - -void -gr_hier_block2_detail::connect_output(int my_port, int port, gr_basic_block_sptr block) -{ - std::stringstream msg; - - if (my_port < 0 || my_port >= (signed)d_outputs.size()) { - msg << "output port " << my_port << " out of range for " << block; - throw std::invalid_argument(msg.str()); - } - - if (d_outputs[my_port].block()) { - msg << "external output port " << my_port << " already connected from " - << d_outputs[my_port]; - throw std::invalid_argument(msg.str()); - } - - d_outputs[my_port] = gr_endpoint(block, port); -} - -void -gr_hier_block2_detail::disconnect_input(int my_port, int port, gr_basic_block_sptr block) -{ - std::stringstream msg; - - if (my_port < 0 || my_port >= (signed)d_inputs.size()) { - msg << "input port number " << my_port << " out of range for " << block; - throw std::invalid_argument(msg.str()); - } - - gr_endpoint_vector_t &endps = d_inputs[my_port]; - gr_endpoint endp(block, port); - - gr_endpoint_viter_t p = std::find(endps.begin(), endps.end(), endp); - if (p == endps.end()) { - msg << "external input port " << my_port << " not connected to " << endp; - throw std::invalid_argument(msg.str()); - } - - endps.erase(p); -} - -void -gr_hier_block2_detail::disconnect_output(int my_port, int port, gr_basic_block_sptr block) -{ - std::stringstream msg; - - if (my_port < 0 || my_port >= (signed)d_outputs.size()) { - msg << "output port number " << my_port << " out of range for " << block; - throw std::invalid_argument(msg.str()); - } - - if (d_outputs[my_port].block() != block) { - msg << "block " << block << " not assigned to output " - << my_port << ", can't disconnect"; - throw std::invalid_argument(msg.str()); - } - - d_outputs[my_port] = gr_endpoint(); -} - -gr_endpoint_vector_t -gr_hier_block2_detail::resolve_port(int port, bool is_input) -{ - std::stringstream msg; - - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "Resolving port " << port << " as an " - << (is_input ? "input" : "output") - << " of " << d_owner->name() << std::endl; - - gr_endpoint_vector_t result; - - if (is_input) { - if (port < 0 || port >= (signed)d_inputs.size()) { - msg << "resolve_port: hierarchical block '" << d_owner->name() - << "': input " << port << " is out of range"; - throw std::runtime_error(msg.str()); - } - - if (d_inputs[port].empty()) { - msg << "resolve_port: hierarchical block '" << d_owner->name() - << "': input " << port << " is not connected internally"; - throw std::runtime_error(msg.str()); - } - - gr_endpoint_vector_t &endps = d_inputs[port]; - gr_endpoint_viter_t p; - for (p = endps.begin(); p != endps.end(); p++) { - gr_endpoint_vector_t tmp = resolve_endpoint(*p, true); - std::copy(tmp.begin(), tmp.end(), back_inserter(result)); - } - } - else { - if (port < 0 || port >= (signed)d_outputs.size()) { - msg << "resolve_port: hierarchical block '" << d_owner->name() - << "': output " << port << " is out of range"; - throw std::runtime_error(msg.str()); - } - - if (d_outputs[port] == gr_endpoint()) { - msg << "resolve_port: hierarchical block '" << d_owner->name() - << "': output " << port << " is not connected internally"; - throw std::runtime_error(msg.str()); - } - - result = resolve_endpoint(d_outputs[port], false); - } - - if (result.empty()) { - msg << "resolve_port: hierarchical block '" << d_owner->name() - << "': unable to resolve " - << (is_input ? "input port " : "output port ") - << port; - throw std::runtime_error(msg.str()); - } - - return result; -} - -void -gr_hier_block2_detail::disconnect_all() -{ - d_fg->clear(); - d_blocks.clear(); - d_inputs.clear(); - d_outputs.clear(); -} - -gr_endpoint_vector_t -gr_hier_block2_detail::resolve_endpoint(const gr_endpoint &endp, bool is_input) const -{ - std::stringstream msg; - gr_endpoint_vector_t result; - - // Check if endpoint is a leaf node - if (cast_to_block_sptr(endp.block())) { - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "Block " << endp.block() << " is a leaf node, returning." << std::endl; - result.push_back(endp); - return result; - } - - // Check if endpoint is a hierarchical block - gr_hier_block2_sptr hier_block2(cast_to_hier_block2_sptr(endp.block())); - if (hier_block2) { - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "Resolving endpoint " << endp << " as an " - << (is_input ? "input" : "output") - << ", recursing" << std::endl; - return hier_block2->d_detail->resolve_port(endp.port(), is_input); - } - - msg << "unable to resolve" << (is_input ? " input " : " output ") - << "endpoint " << endp; - throw std::runtime_error(msg.str()); -} - -void -gr_hier_block2_detail::flatten_aux(gr_flat_flowgraph_sptr sfg) const -{ - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << " ** Flattening " << d_owner->name() << std::endl; - - // Add my edges to the flow graph, resolving references to actual endpoints - gr_edge_vector_t edges = d_fg->edges(); - gr_msg_edge_vector_t msg_edges = d_fg->msg_edges(); - gr_edge_viter_t p; - gr_msg_edge_viter_t q,u; - - // Only run setup_rpc if ControlPort config param is enabled. - bool ctrlport_on = gr_prefs::singleton()->get_bool("ControlPort", "on", false); - - // For every block (gr_block and gr_hier_block2), set up the RPC - // interface. - for(p = edges.begin(); p != edges.end(); p++) { - gr_basic_block_sptr b; - b = p->src().block(); - - if(ctrlport_on) { - if(!b->is_rpc_set()) { - b->setup_rpc(); - b->rpc_set(); - } - } - - b = p->dst().block(); - if(ctrlport_on) { - if(!b->is_rpc_set()) { - b->setup_rpc(); - b->rpc_set(); - } - } - } - - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "Flattening stream connections: " << std::endl; - - for (p = edges.begin(); p != edges.end(); p++) { - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "Flattening edge " << (*p) << std::endl; - - gr_endpoint_vector_t src_endps = resolve_endpoint(p->src(), false); - gr_endpoint_vector_t dst_endps = resolve_endpoint(p->dst(), true); - - gr_endpoint_viter_t s, d; - for (s = src_endps.begin(); s != src_endps.end(); s++) { - for (d = dst_endps.begin(); d != dst_endps.end(); d++) { - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << (*s) << "->" << (*d) << std::endl; - sfg->connect(*s, *d); - } - } - } - - // loop through flattening hierarchical connections - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "Flattening msg connections: " << std::endl; - - - std::vector<std::pair<gr_msg_endpoint, bool> > resolved_endpoints; - for(q = msg_edges.begin(); q != msg_edges.end(); q++) { - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << boost::format(" flattening edge ( %s, %s, %d) -> ( %s, %s, %d)\n") % q->src().block() % q->src().port() % q->src().is_hier() % q->dst().block() % q->dst().port() % q->dst().is_hier(); - - bool normal_connection = true; - - // resolve existing connections to hier ports - if(q->dst().is_hier()){ - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << boost::format(" resolve hier output (%s, %s)") % q->dst().block() % q->dst().port() << std::endl; - sfg->replace_endpoint( q->dst(), q->src(), true ); - resolved_endpoints.push_back(std::pair<gr_msg_endpoint, bool>(q->dst(),true)); - normal_connection = false; - } - - if(q->src().is_hier()){ - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << boost::format(" resolve hier input (%s, %s)") % q->src().block() % q->src().port() << std::endl; - sfg->replace_endpoint( q->src(), q->dst(), false ); - resolved_endpoints.push_back(std::pair<gr_msg_endpoint, bool>(q->src(),false)); - normal_connection = false; - } - - // propogate non hier connections through - if(normal_connection){ - sfg->connect( q->src(), q->dst() ); - } - } - for(std::vector<std::pair<gr_msg_endpoint, bool> >::iterator it = resolved_endpoints.begin(); it != resolved_endpoints.end(); it++){ - sfg->clear_endpoint( (*it).first, (*it).second ); - } - -/* // connect primitive edges in the new fg - for(q = msg_edges.begin(); q != msg_edges.end(); q++) { - if( (!q->src().is_hier()) && (!q->dst().is_hier()) ){ - sfg->connect( q->src(), q->dst() ); - } else { - std::cout << "not connecting hier connection!" << std::endl; - } - }*/ - - // Construct unique list of blocks used either in edges, inputs, - // outputs, or by themselves. I still hate STL. - gr_basic_block_vector_t blocks; // unique list of used blocks - gr_basic_block_vector_t tmp = d_fg->calc_used_blocks(); - - // First add the list of singleton blocks - std::vector<gr_basic_block_sptr>::const_iterator b; // Because flatten_aux is const - for (b = d_blocks.begin(); b != d_blocks.end(); b++) - tmp.push_back(*b); - - // Now add the list of connected input blocks - std::stringstream msg; - for (unsigned int i = 0; i < d_inputs.size(); i++) { - if (d_inputs[i].size() == 0) { - msg << "In hierarchical block " << d_owner->name() << ", input " << i - << " is not connected internally"; - throw std::runtime_error(msg.str()); - } - - for (unsigned int j = 0; j < d_inputs[i].size(); j++) - tmp.push_back(d_inputs[i][j].block()); - } - - for (unsigned int i = 0; i < d_outputs.size(); i++) { - gr_basic_block_sptr blk = d_outputs[i].block(); - if (!blk) { - msg << "In hierarchical block " << d_owner->name() << ", output " << i - << " is not connected internally"; - throw std::runtime_error(msg.str()); - } - tmp.push_back(blk); - } - sort(tmp.begin(), tmp.end()); - - std::insert_iterator<gr_basic_block_vector_t> inserter(blocks, blocks.begin()); - unique_copy(tmp.begin(), tmp.end(), inserter); - - // Recurse hierarchical children - for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { - gr_hier_block2_sptr hier_block2(cast_to_hier_block2_sptr(*p)); - if (hier_block2 && (hier_block2.get() != d_owner)) { - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "flatten_aux: recursing into hierarchical block " << hier_block2 << std::endl; - hier_block2->d_detail->flatten_aux(sfg); - } - } -} - -void -gr_hier_block2_detail::lock() -{ - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "lock: entered in " << this << std::endl; - - if (d_parent_detail) - d_parent_detail->lock(); - else - d_owner->lock(); -} - -void -gr_hier_block2_detail::unlock() -{ - if (GR_HIER_BLOCK2_DETAIL_DEBUG) - std::cout << "unlock: entered in " << this << std::endl; - - if (d_parent_detail) - d_parent_detail->unlock(); - else - d_owner->unlock(); -} - diff --git a/gnuradio-runtime/lib/gr_hier_block2_detail.h b/gnuradio-runtime/lib/gr_hier_block2_detail.h deleted file mode 100644 index d08fe20ac0..0000000000 --- a/gnuradio-runtime/lib/gr_hier_block2_detail.h +++ /dev/null @@ -1,74 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2007,2009 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_HIER_BLOCK2_DETAIL_H -#define INCLUDED_GR_HIER_BLOCK2_DETAIL_H - -#include <gr_runtime_api.h> -#include <gr_hier_block2.h> -#include <gr_flat_flowgraph.h> -#include <boost/utility.hpp> - -/*! - * \ingroup internal - */ -class GR_RUNTIME_API gr_hier_block2_detail : boost::noncopyable -{ -public: - gr_hier_block2_detail(gr_hier_block2 *owner); - ~gr_hier_block2_detail(); - - void connect(gr_basic_block_sptr block); - void connect(gr_basic_block_sptr src, int src_port, - gr_basic_block_sptr dst, int dst_port); - void msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, - gr_basic_block_sptr dst, pmt::pmt_t dstport); - void msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport, - gr_basic_block_sptr dst, pmt::pmt_t dstport); - void disconnect(gr_basic_block_sptr block); - void disconnect(gr_basic_block_sptr, int src_port, - gr_basic_block_sptr, int dst_port); - void disconnect_all(); - void lock(); - void unlock(); - void flatten_aux(gr_flat_flowgraph_sptr sfg) const; - -private: - - // Private implementation data - gr_hier_block2 *d_owner; - gr_hier_block2_detail *d_parent_detail; - gr_flowgraph_sptr d_fg; - std::vector<gr_endpoint_vector_t> d_inputs; // Multiple internal endpoints per external input - gr_endpoint_vector_t d_outputs; // Single internal endpoint per external output - gr_basic_block_vector_t d_blocks; - - - void connect_input(int my_port, int port, gr_basic_block_sptr block); - void connect_output(int my_port, int port, gr_basic_block_sptr block); - void disconnect_input(int my_port, int port, gr_basic_block_sptr block); - void disconnect_output(int my_port, int port, gr_basic_block_sptr block); - - gr_endpoint_vector_t resolve_port(int port, bool is_input); - gr_endpoint_vector_t resolve_endpoint(const gr_endpoint &endp, bool is_input) const; -}; - -#endif /* INCLUDED_GR_HIER_BLOCK2_DETAIL_H */ diff --git a/gnuradio-runtime/lib/gr_io_signature.cc b/gnuradio-runtime/lib/gr_io_signature.cc deleted file mode 100644 index 6ac9acd17d..0000000000 --- a/gnuradio-runtime/lib/gr_io_signature.cc +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <gr_io_signature.h> -#include <stdexcept> -#include <iostream> - -gr_io_signature_sptr -gr_make_io_signaturev(int min_streams, int max_streams, - const std::vector<int> &sizeof_stream_items) -{ - return gr_io_signature_sptr (new gr_io_signature (min_streams, max_streams, - sizeof_stream_items)); -} - -gr_io_signature_sptr -gr_make_io_signature(int min_streams, int max_streams, - int sizeof_stream_item) -{ - std::vector<int> sizeof_items(1); - sizeof_items[0] = sizeof_stream_item; - return gr_make_io_signaturev(min_streams, max_streams, sizeof_items); -} - -gr_io_signature_sptr -gr_make_io_signature2(int min_streams, int max_streams, - int sizeof_stream_item1, - int sizeof_stream_item2) -{ - std::vector<int> sizeof_items(2); - sizeof_items[0] = sizeof_stream_item1; - sizeof_items[1] = sizeof_stream_item2; - return gr_make_io_signaturev(min_streams, max_streams, sizeof_items); -} - -gr_io_signature_sptr -gr_make_io_signature3(int min_streams, int max_streams, - int sizeof_stream_item1, - int sizeof_stream_item2, - int sizeof_stream_item3) -{ - std::vector<int> sizeof_items(3); - sizeof_items[0] = sizeof_stream_item1; - sizeof_items[1] = sizeof_stream_item2; - sizeof_items[2] = sizeof_stream_item3; - return gr_make_io_signaturev(min_streams, max_streams, sizeof_items); -} - -// ------------------------------------------------------------------------ - - -gr_io_signature::gr_io_signature (int min_streams, int max_streams, - const std::vector<int> &sizeof_stream_items) -{ - if (min_streams < 0 - || (max_streams != IO_INFINITE && max_streams < min_streams)) - throw std::invalid_argument ("gr_io_signature(1)"); - - if (sizeof_stream_items.size() < 1) - throw std::invalid_argument("gr_io_signature(2)"); - - for (size_t i = 0; i < sizeof_stream_items.size(); i++){ - if (max_streams != 0 && sizeof_stream_items[i] < 1) - throw std::invalid_argument("gr_io_signature(3)"); - } - - d_min_streams = min_streams; - d_max_streams = max_streams; - d_sizeof_stream_item = sizeof_stream_items; -} - -gr_io_signature::~gr_io_signature () -{ -} - -int -gr_io_signature::sizeof_stream_item (int _index) const -{ - if (_index < 0) - throw std::invalid_argument ("gr_io_signature::sizeof_stream_item"); - - size_t index = _index; - return d_sizeof_stream_item[std::min(index, d_sizeof_stream_item.size() - 1)]; -} - -std::vector<int> -gr_io_signature::sizeof_stream_items() const -{ - return d_sizeof_stream_item; -} diff --git a/gnuradio-runtime/lib/gr_local_sighandler.cc b/gnuradio-runtime/lib/gr_local_sighandler.cc deleted file mode 100644 index fb31742e13..0000000000 --- a/gnuradio-runtime/lib/gr_local_sighandler.cc +++ /dev/null @@ -1,187 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_local_sighandler.h> -#include <stdexcept> -#include <stdio.h> -#include <string.h> - - -gr_local_sighandler::gr_local_sighandler (int signum, - void (*new_handler)(int)) - : d_signum (signum) -{ -#ifdef HAVE_SIGACTION - struct sigaction new_action; - memset (&new_action, 0, sizeof (new_action)); - - new_action.sa_handler = new_handler; - sigemptyset (&new_action.sa_mask); - new_action.sa_flags = 0; - - if (sigaction (d_signum, &new_action, &d_old_action) < 0){ - perror ("sigaction (install new)"); - throw std::runtime_error ("sigaction"); - } -#endif -} - -gr_local_sighandler::~gr_local_sighandler () -{ -#ifdef HAVE_SIGACTION - if (sigaction (d_signum, &d_old_action, 0) < 0){ - perror ("sigaction (restore old)"); - throw std::runtime_error ("sigaction"); - } -#endif -} - -void -gr_local_sighandler::throw_signal (int signum) -{ - throw gr_signal (signum); -} - -/* - * Semi-hideous way to may a signal number into a signal name - */ - -#define SIGNAME(x) case x: return #x - -std::string -gr_signal::name () const -{ - char tmp[128]; - - switch (signal ()){ -#ifdef SIGHUP - SIGNAME (SIGHUP); -#endif -#ifdef SIGINT - SIGNAME (SIGINT); -#endif -#ifdef SIGQUIT - SIGNAME (SIGQUIT); -#endif -#ifdef SIGILL - SIGNAME (SIGILL); -#endif -#ifdef SIGTRAP - SIGNAME (SIGTRAP); -#endif -#ifdef SIGABRT - SIGNAME (SIGABRT); -#endif -#ifdef SIGBUS - SIGNAME (SIGBUS); -#endif -#ifdef SIGFPE - SIGNAME (SIGFPE); -#endif -#ifdef SIGKILL - SIGNAME (SIGKILL); -#endif -#ifdef SIGUSR1 - SIGNAME (SIGUSR1); -#endif -#ifdef SIGSEGV - SIGNAME (SIGSEGV); -#endif -#ifdef SIGUSR2 - SIGNAME (SIGUSR2); -#endif -#ifdef SIGPIPE - SIGNAME (SIGPIPE); -#endif -#ifdef SIGALRM - SIGNAME (SIGALRM); -#endif -#ifdef SIGTERM - SIGNAME (SIGTERM); -#endif -#ifdef SIGSTKFLT - SIGNAME (SIGSTKFLT); -#endif -#ifdef SIGCHLD - SIGNAME (SIGCHLD); -#endif -#ifdef SIGCONT - SIGNAME (SIGCONT); -#endif -#ifdef SIGSTOP - SIGNAME (SIGSTOP); -#endif -#ifdef SIGTSTP - SIGNAME (SIGTSTP); -#endif -#ifdef SIGTTIN - SIGNAME (SIGTTIN); -#endif -#ifdef SIGTTOU - SIGNAME (SIGTTOU); -#endif -#ifdef SIGURG - SIGNAME (SIGURG); -#endif -#ifdef SIGXCPU - SIGNAME (SIGXCPU); -#endif -#ifdef SIGXFSZ - SIGNAME (SIGXFSZ); -#endif -#ifdef SIGVTALRM - SIGNAME (SIGVTALRM); -#endif -#ifdef SIGPROF - SIGNAME (SIGPROF); -#endif -#ifdef SIGWINCH - SIGNAME (SIGWINCH); -#endif -#ifdef SIGIO - SIGNAME (SIGIO); -#endif -#ifdef SIGPWR - SIGNAME (SIGPWR); -#endif -#ifdef SIGSYS - SIGNAME (SIGSYS); -#endif - default: -#if defined (HAVE_SNPRINTF) -#if defined (SIGRTMIN) && defined (SIGRTMAX) - if (signal () >= SIGRTMIN && signal () <= SIGRTMAX){ - snprintf (tmp, sizeof (tmp), "SIGRTMIN + %d", signal ()); - return tmp; - } -#endif - snprintf (tmp, sizeof (tmp), "SIGNAL %d", signal ()); - return tmp; -#else - return "Unknown signal"; -#endif - } -} diff --git a/gnuradio-runtime/lib/gr_logger.cc b/gnuradio-runtime/lib/gr_logger.cc deleted file mode 100644 index 6da4a6d914..0000000000 --- a/gnuradio-runtime/lib/gr_logger.cc +++ /dev/null @@ -1,295 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2012 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -/******************************************************************************* -* Author: Mark Plett -* Description: -* The gr_log module wraps the log4cpp library for logging in gnuradio. -*******************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_logger.h> -#include <stdexcept> -#include <algorithm> - -#ifdef ENABLE_GR_LOG -#ifdef HAVE_LOG4CPP - -/**************************** BEGIN LOG4CPP HELPERS ***************************/ -/* Logger config class. This is a singleton that controls how log4cpp is configured - * If watch_period>0 a thread is started to watch teh config file for changes. - */ - -// Getters of logger_config -logger_config& -logger_config::get_instance(void){ - static logger_config instance; - return instance; -}; - -std::string -logger_config::get_filename(){ - logger_config& in=get_instance(); - return in.filename; -}; - -unsigned int -logger_config::get_watch_period(){ - logger_config& in=get_instance(); - return in.watch_period; -}; - -// Method to watch config file for changes -void logger_config::watch_file(std::string filename,unsigned int watch_period){ - std::time_t last_write(boost::filesystem::last_write_time(filename)); - std::time_t current_time(0); - while(true){ - try{ - current_time = boost::filesystem::last_write_time(filename); - if(current_time>last_write){ - std::cout<<"GNURadio Reloading logger configuration:"<<filename<<std::endl; - last_write = current_time; -// Should we wipe out all old configuration or just add the new? Just adding... -// logger_reset_config(); - logger_load_config(filename); - }; - boost::this_thread::sleep(boost::posix_time::time_duration(0,0,watch_period,0)); - } - catch(const boost::thread_interrupted&){ - std::cout<<"GNURadio leaving logger config file watch."<<std::endl; - break; - }; - }; -}; - -// Method to load the confifuration. It only loads if the filename or watch has changed -void logger_config::load_config(std::string filename,unsigned int watch_period){ - logger_config& instance = get_instance(); -// Only reconfigure if filename or watch has changed - if(instance.filename!=filename || watch_period!=instance.watch_period){ - instance.filename = filename; - instance.watch_period = watch_period; -// Stop any file watching thread - if(instance.watch_thread!=NULL) stop_watch(); -// Load configuration - std::cout<<"GNURadio Loading logger configuration:"<<instance.filename<<std::endl; - logger_load_config(instance.filename); -// Start watch if required - if(instance.watch_period>0){ - instance.watch_thread = new boost::thread(watch_file,instance.filename,instance.watch_period); - } - }; -}; - -// Method to stop the watcher thread -void logger_config::stop_watch(){ - logger_config& instance = get_instance(); - if(instance.watch_thread){ - instance.watch_thread->interrupt(); - instance.watch_thread->join(); - delete(instance.watch_thread); - instance.watch_thread=NULL; - }; -}; - -// Method to reset logger configuration -void -logger_config::reset_config(void){ - logger_config& instance = get_instance(); - stop_watch(); - std::vector<log4cpp::Category*> *loggers = log4cpp::Category::getCurrentCategories(); - std::vector<log4cpp::Category*>::iterator logger = loggers->begin(); -// We can't destroy categories but we can neuter them by removing all appenders. - for (;logger!=loggers->end();logger++){ - (*logger)->removeAllAppenders(); - }; - instance.filename=std::string(""); - instance.watch_period=0; -} - -/***************** Functions to call log4cpp methods *************************/ - -gr_logger_ptr -logger_get_logger(std::string name) -{ - if(log4cpp::Category::exists(name)){ - gr_logger_ptr logger = &log4cpp::Category::getInstance(name); - return logger; - } - else - { - gr_logger_ptr logger = &log4cpp::Category::getInstance(name); - logger->setPriority(log4cpp::Priority::NOTSET); - return logger; - }; -}; - -void -logger_load_config(const std::string &config_filename) -{ - if(config_filename.size() != 0) { - try - { - log4cpp::PropertyConfigurator::configure(config_filename); - } - catch( log4cpp::ConfigureFailure &e ) - { - std::cout << "Logger config failed :" << e.what() << std::endl; - } - }; -} - -void -logger_set_level(gr_logger_ptr logger, const std::string &level) -{ - std::string nocase = level; - std::transform(level.begin(), level.end(), nocase.begin(), ::tolower); - - if(nocase == "off" || nocase == "notset") - logger_set_level(logger, log4cpp::Priority::NOTSET); - else if(nocase == "all" || nocase == "debug") - logger_set_level(logger, log4cpp::Priority::DEBUG); - else if(nocase == "info") - logger_set_level(logger, log4cpp::Priority::INFO); - else if(nocase == "notice") - logger_set_level(logger, log4cpp::Priority::NOTICE); - else if(nocase == "warn") - logger_set_level(logger, log4cpp::Priority::WARN); - else if(nocase == "error") - logger_set_level(logger, log4cpp::Priority::ERROR); - else if(nocase == "crit") - logger_set_level(logger, log4cpp::Priority::CRIT); - else if(nocase == "alert") - logger_set_level(logger, log4cpp::Priority::ALERT); - else if(nocase=="fatal") - logger_set_level(logger, log4cpp::Priority::FATAL); - else if(nocase == "emerg") - logger_set_level(logger, log4cpp::Priority::EMERG); - else - throw std::runtime_error("logger_set_level: Bad level type.\n"); -} - -void -logger_set_level(gr_logger_ptr logger, log4cpp::Priority::Value level) -{ - logger->setPriority(level); -} - -void -logger_get_level(gr_logger_ptr logger, std::string &level) -{ - log4cpp::Priority::Value levelPtr = logger->getPriority(); - if(levelPtr == log4cpp::Priority::NOTSET) level = "noset"; - if(levelPtr == log4cpp::Priority::DEBUG) level = "debug"; - if(levelPtr == log4cpp::Priority::INFO) level = "info"; - if(levelPtr == log4cpp::Priority::NOTICE) level = "notice"; - if(levelPtr == log4cpp::Priority::WARN) level = "warn"; - if(levelPtr == log4cpp::Priority::ERROR) level = "error"; - if(levelPtr == log4cpp::Priority::CRIT) level = "crit"; - if(levelPtr == log4cpp::Priority::ALERT) level = "alert"; - if(levelPtr == log4cpp::Priority::FATAL) level = "fatal"; - if(levelPtr == log4cpp::Priority::EMERG) level = "emerg"; -}; - -void -logger_get_level(gr_logger_ptr logger,log4cpp::Priority::Value level) -{ - level = logger->getPriority(); -} - -void -logger_add_console_appender(gr_logger_ptr logger,std::string target,std::string pattern) -{ - - log4cpp::PatternLayout* layout = new log4cpp::PatternLayout(); - log4cpp::Appender* app; - if(target=="stdout") - app = new log4cpp::OstreamAppender("ConsoleAppender::",&std::cout); - else - app = new log4cpp::OstreamAppender("ConsoleAppender::",&std::cerr); - - layout->setConversionPattern(pattern); - app->setLayout(layout); - logger->setAppender(app); - -} - -void -logger_add_file_appender(gr_logger_ptr logger,std::string filename,bool append,std::string pattern) -{ - - log4cpp::PatternLayout* layout = new log4cpp::PatternLayout(); - log4cpp::Appender* app = new - log4cpp::FileAppender("FileAppender::"+filename, - filename); - layout->setConversionPattern(pattern); - app->setLayout(layout); - logger->setAppender(app); - -} - -void -logger_add_rollingfile_appender(gr_logger_ptr logger,std::string filename, - size_t filesize,int bkup_index,bool append,mode_t mode,std::string pattern) -{ - log4cpp::PatternLayout* layout = new log4cpp::PatternLayout(); - log4cpp::Appender* app = new - log4cpp::RollingFileAppender("RollFileAppender::"+filename,filename,filesize,bkup_index,append,mode); - layout->setConversionPattern(pattern); - app->setLayout(layout); - logger->setAppender(app); -} - -std::vector<std::string> -logger_get_logger_names(void){ - std::vector<std::string> names; - std::vector<log4cpp::Category*> *loggers = log4cpp::Category::getCurrentCategories(); - std::vector<log4cpp::Category*>::iterator logger = loggers->begin(); - - for (;logger!=loggers->end();logger++){ - names.push_back((*logger)->getName()); - }; - return names; - -} - -#endif /* HAVE_LOG4CPP */ - -/****** Start Methods to provide Python the capabilities of the macros ********/ -void gr_logger_config(const std::string config_filename, unsigned int watch_period){ - GR_CONFIG_AND_WATCH_LOGGER(config_filename,watch_period); -}; -std::vector<std::string> gr_logger_get_logger_names(void){ - std::vector<std::string> names; - GR_GET_LOGGER_NAMES(names); - return names; -}; -void gr_logger_reset_config(void){ - GR_RESET_CONFIGURATION(); -}; - -// Remaining capability provided by gr_logger class in gr_logger.h - -#endif /* ENABLE_GR_LOGGER */ diff --git a/gnuradio-runtime/lib/gr_message.cc b/gnuradio-runtime/lib/gr_message.cc deleted file mode 100644 index a99dcd7653..0000000000 --- a/gnuradio-runtime/lib/gr_message.cc +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include <gr_message.h> -#include <assert.h> -#include <string.h> - -static long s_ncurrently_allocated = 0; - -gr_message_sptr -gr_make_message (long type, double arg1, double arg2, size_t length) -{ - return gr_message_sptr (new gr_message (type, arg1, arg2, length)); -} - -gr_message_sptr -gr_make_message_from_string(const std::string s, long type, double arg1, double arg2) -{ - gr_message_sptr m = gr_make_message(type, arg1, arg2, s.size()); - memcpy(m->msg(), s.data(), s.size()); - return m; -} - - -gr_message::gr_message (long type, double arg1, double arg2, size_t length) - : d_type(type), d_arg1(arg1), d_arg2(arg2) -{ - if (length == 0) - d_buf_start = d_msg_start = d_msg_end = d_buf_end = 0; - else { - d_buf_start = new unsigned char [length]; - d_msg_start = d_buf_start; - d_msg_end = d_buf_end = d_buf_start + length; - } - s_ncurrently_allocated++; -} - -gr_message::~gr_message () -{ - assert (d_next == 0); - delete [] d_buf_start; - d_msg_start = d_msg_end = d_buf_end = 0; - s_ncurrently_allocated--; -} - -std::string -gr_message::to_string() const -{ - return std::string((char *)d_msg_start, length()); -} - -long -gr_message_ncurrently_allocated () -{ - return s_ncurrently_allocated; -} diff --git a/gnuradio-runtime/lib/gr_misc.cc b/gnuradio-runtime/lib/gr_misc.cc deleted file mode 100644 index 1ed2a03d7f..0000000000 --- a/gnuradio-runtime/lib/gr_misc.cc +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include <gr_misc.h> - -unsigned int -gr_rounduppow2(unsigned int n) -{ - int i; - for (i=0;((n-1)>>i) != 0;i++) - ; - return 1<<i; -} - -// ---------------------------------------------------------------- - -void -gr_zero_vector(std::vector<float> &v) -{ - for(unsigned int i=0; i < v.size(); i++) - v[i] = 0; -} - -void -gr_zero_vector(std::vector<double> &v) -{ - for(unsigned int i=0; i < v.size(); i++) - v[i] = 0; -} - -void -gr_zero_vector(std::vector<int> &v) -{ - for(unsigned int i=0; i < v.size(); i++) - v[i] = 0; -} - -void -gr_zero_vector(std::vector<gr_complex> &v) -{ - for(unsigned int i=0; i < v.size(); i++) - v[i] = 0; -} diff --git a/gnuradio-runtime/lib/gr_msg_queue.cc b/gnuradio-runtime/lib/gr_msg_queue.cc deleted file mode 100644 index 03bbe046a4..0000000000 --- a/gnuradio-runtime/lib/gr_msg_queue.cc +++ /dev/null @@ -1,125 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005,2009 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include <gr_msg_queue.h> -#include <stdexcept> - -gr_msg_queue_sptr -gr_make_msg_queue(unsigned int limit) -{ - return gr_msg_queue_sptr (new gr_msg_queue(limit)); -} - -gr_msg_queue::gr_msg_queue(unsigned int limit) - : d_not_empty(), d_not_full(), - /*d_head(0), d_tail(0),*/ d_count(0), d_limit(limit) -{ -} - -gr_msg_queue::~gr_msg_queue() -{ - flush (); -} - -void -gr_msg_queue::insert_tail(gr_message_sptr msg) -{ - if (msg->d_next) - throw std::invalid_argument("gr_msg_queue::insert_tail: msg already in queue"); - - gr::thread::scoped_lock guard(d_mutex); - - while (full_p()) - d_not_full.wait(guard); - - if (d_tail == 0){ - d_tail = d_head = msg; - //msg->d_next = 0; - msg->d_next.reset(); - } - else { - d_tail->d_next = msg; - d_tail = msg; - //msg->d_next = 0; - msg->d_next.reset(); - } - d_count++; - d_not_empty.notify_one(); -} - -gr_message_sptr -gr_msg_queue::delete_head() -{ - gr::thread::scoped_lock guard(d_mutex); - gr_message_sptr m; - - while ((m = d_head) == 0) - d_not_empty.wait(guard); - - d_head = m->d_next; - if (d_head == 0){ - //d_tail = 0; - d_tail.reset(); - } - - d_count--; - // m->d_next = 0; - m->d_next.reset(); - d_not_full.notify_one(); - return m; -} - -gr_message_sptr -gr_msg_queue::delete_head_nowait() -{ - gr::thread::scoped_lock guard(d_mutex); - gr_message_sptr m; - - if ((m = d_head) == 0){ - //return 0; - return gr_message_sptr(); - } - - d_head = m->d_next; - if (d_head == 0){ - //d_tail = 0; - d_tail.reset(); - } - - d_count--; - //m->d_next = 0; - m->d_next.reset(); - d_not_full.notify_one(); - return m; -} - -void -gr_msg_queue::flush() -{ - gr_message_sptr m; - - while ((m = delete_head_nowait ()) != 0) - ; -} diff --git a/gnuradio-runtime/lib/gr_preferences.cc b/gnuradio-runtime/lib/gr_preferences.cc deleted file mode 100644 index a0f5616603..0000000000 --- a/gnuradio-runtime/lib/gr_preferences.cc +++ /dev/null @@ -1,108 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003,2010,2011 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_preferences.h> -#include <gr_sys_paths.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <string.h> - -#include <boost/filesystem/operations.hpp> -#include <boost/filesystem/path.hpp> -namespace fs = boost::filesystem; - -/* - * The simplest thing that could possibly work: - * the key is the filename; the value is the file contents. - */ - -static const char * -pathname (const char *key) -{ - static fs::path path; - path = fs::path(gr_appdata_path()) / ".gnuradio" / "prefs" / key; - return path.string().c_str(); -} - -static void -ensure_dir_path () -{ - fs::path path = fs::path(gr_appdata_path()) / ".gnuradio"; - if (!fs::is_directory(path)) fs::create_directory(path); - - path = path / "prefs"; - if (!fs::is_directory(path)) fs::create_directory(path); -} - -const char * -gr_preferences::get (const char *key) -{ - static char buf[1024]; - - FILE *fp = fopen (pathname (key), "r"); - if (fp == 0) { - perror (pathname (key)); - return 0; - } - - memset (buf, 0, sizeof (buf)); - size_t ret = fread (buf, 1, sizeof (buf) - 1, fp); - if(ret == 0) { - if(ferror(fp) != 0) { - perror (pathname (key)); - fclose (fp); - return 0; - } - } - fclose (fp); - return buf; -} - -void -gr_preferences::set (const char *key, const char *value) -{ - ensure_dir_path (); - - FILE *fp = fopen (pathname (key), "w"); - if (fp == 0){ - perror (pathname (key)); - return; - } - - size_t ret = fwrite (value, 1, strlen (value), fp); - if(ret == 0) { - if(ferror(fp) != 0) { - perror (pathname (key)); - fclose (fp); - return; - } - } - fclose (fp); -}; diff --git a/gnuradio-runtime/lib/gr_prefs.cc b/gnuradio-runtime/lib/gr_prefs.cc deleted file mode 100644 index 8a79c3335f..0000000000 --- a/gnuradio-runtime/lib/gr_prefs.cc +++ /dev/null @@ -1,391 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gr_prefs.h> -#include <gr_sys_paths.h> -#include <gr_constants.h> -#include <algorithm> - -#include <boost/filesystem/operations.hpp> -#include <boost/filesystem/path.hpp> -#include <boost/filesystem/fstream.hpp> -namespace fs = boost::filesystem; - -/* - * Stub implementations - */ - -static gr_prefs s_default_singleton; -static gr_prefs *s_singleton = &s_default_singleton; - -gr_prefs * -gr_prefs::singleton() -{ - return s_singleton; -} - -void -gr_prefs::set_singleton(gr_prefs *p) -{ - s_singleton = p; -} - -gr_prefs::gr_prefs() -{ - _read_files(); -} - -gr_prefs::~gr_prefs() -{ - // nop -} - -std::vector<std::string> -gr_prefs::_sys_prefs_filenames() -{ - std::vector<std::string> fnames; - - fs::path dir = gr_prefsdir(); - if(!fs::is_directory(dir)) - return fnames; - - fs::directory_iterator diritr(dir); - while(diritr != fs::directory_iterator()) { - fs::path p = *diritr++; - if(p.extension() != ".swp") - fnames.push_back(p.string()); - } - std::sort(fnames.begin(), fnames.end()); - - // Find if there is a ~/.gnuradio/config.conf file and add this to - // the end of the file list to override any preferences in the - // installed path config files. - fs::path homedir = fs::path(gr_appdata_path()); - homedir = homedir/".gnuradio/config.conf"; - if(fs::exists(homedir)) { - fnames.push_back(homedir.string()); - } - - return fnames; -} - -void -gr_prefs::_read_files() -{ - std::string config; - - std::vector<std::string> filenames = _sys_prefs_filenames(); - std::vector<std::string>::iterator sitr; - char tmp[1024]; - for(sitr = filenames.begin(); sitr != filenames.end(); sitr++) { - fs::ifstream fin(*sitr); - while(!fin.eof()) { - fin.getline(tmp, 1024); - std::string t(tmp); - // ignore empty lines or lines of just comments - if((t.size() > 0) && (t[0] != '#')) { - // remove any comments in the line - size_t hash = t.find("#"); - - // Use hash marks at the end of each segment as a delimiter - config += t.substr(0, hash) + '#'; - } - } - fin.close(); - } - - // Remove all whitespace. - config.erase(std::remove_if(config.begin(), config.end(), ::isspace), config.end()); - - // Convert the string into a map - _convert_to_map(config); -} - -void -gr_prefs::_convert_to_map(const std::string &conf) -{ - // Convert the string into an map of maps - // Map is structured as {section name: map of options} - // And options map is simply: {option name: option value} - std::string sub = conf; - size_t sec_start = sub.find("["); - while(sec_start != std::string::npos) { - sub = sub.substr(sec_start); - - size_t sec_end = sub.find("]"); - if(sec_end == std::string::npos) - throw std::runtime_error("Config file error: Mismatched section label.\n"); - - std::string sec = sub.substr(1, sec_end-1); - size_t next_sec_start = sub.find("[", sec_end); - std::string subsec = sub.substr(sec_end+1, next_sec_start-sec_end-2); - - std::transform(sec.begin(), sec.end(), sec.begin(), ::tolower); - - std::map<std::string, std::string> options_map = d_config_map[sec]; - size_t next_opt = 0; - size_t next_val = 0; - next_opt = subsec.find("#"); - while(next_opt < subsec.size()-1) { - next_val = subsec.find("=", next_opt); - std::string option = subsec.substr(next_opt+1, next_val-next_opt-1); - - next_opt = subsec.find("#", next_val); - std::string value = subsec.substr(next_val+1, next_opt-next_val-1); - - std::transform(option.begin(), option.end(), option.begin(), ::tolower); - options_map[option] = value; - } - - d_config_map[sec] = options_map; - - sec_start = sub.find("[", sec_end); - } -} - -std::string -gr_prefs::to_string() -{ - gr_config_map_itr sections; - gr_config_map_elem_itr options; - std::stringstream s; - - for(sections = d_config_map.begin(); sections != d_config_map.end(); sections++) { - s << "[" << sections->first << "]" << std::endl; - for(options = sections->second.begin(); options != sections->second.end(); options++) { - s << options->first << " = " << options->second << std::endl; - } - s << std::endl; - } - - return s.str(); -} - -void -gr_prefs::save() -{ - std::string conf = to_string(); - - fs::path homedir = fs::path(gr_appdata_path()); - homedir = homedir/".gnuradio/config.conf"; - fs::ofstream fout(homedir); - fout << conf; - fout.close(); -} - -char * -gr_prefs::option_to_env(std::string section, std::string option) -{ - std::stringstream envname; - std::string secname=section, optname=option; - - std::transform(section.begin(), section.end(), secname.begin(), ::toupper); - std::transform(option.begin(), option.end(), optname.begin(), ::toupper); - envname << "GR_CONF_" << secname << "_" << optname; - - return getenv(envname.str().c_str()); -} - -bool -gr_prefs::has_section(const std::string §ion) -{ - std::string s = section; - std::transform(section.begin(), section.end(), s.begin(), ::tolower); - return d_config_map.count(s) > 0; -} - -bool -gr_prefs::has_option(const std::string §ion, const std::string &option) -{ - if(option_to_env(section, option)) - return true; - - if(has_section(section)) { - std::string s = section; - std::transform(section.begin(), section.end(), s.begin(), ::tolower); - - std::string o = option; - std::transform(option.begin(), option.end(), o.begin(), ::tolower); - - gr_config_map_itr sec = d_config_map.find(s); - return sec->second.count(o) > 0; - } - else { - return false; - } -} - -const std::string -gr_prefs::get_string(const std::string §ion, const std::string &option, - const std::string &default_val) -{ - char *env = option_to_env(section, option); - if(env) - return std::string(env); - - if(has_option(section, option)) { - std::string s = section; - std::transform(section.begin(), section.end(), s.begin(), ::tolower); - - std::string o = option; - std::transform(option.begin(), option.end(), o.begin(), ::tolower); - - gr_config_map_itr sec = d_config_map.find(s); - gr_config_map_elem_itr opt = sec->second.find(o); - return opt->second; - } - else { - return default_val; - } -} - -void -gr_prefs::set_string(const std::string §ion, const std::string &option, - const std::string &val) -{ - std::string s = section; - std::transform(section.begin(), section.end(), s.begin(), ::tolower); - - std::string o = option; - std::transform(option.begin(), option.end(), o.begin(), ::tolower); - - std::map<std::string, std::string> opt_map = d_config_map[s]; - - opt_map[o] = val; - - d_config_map[s] = opt_map; -} - -bool -gr_prefs::get_bool(const std::string §ion, const std::string &option, bool default_val) -{ - if(has_option(section, option)) { - std::string str = get_string(section, option, ""); - if(str == "") { - return default_val; - } - std::transform(str.begin(), str.end(), str.begin(), ::tolower); - if((str == "true") || (str == "on") || (str == "1")) - return true; - else if((str == "false") || (str == "off") || (str == "0")) - return false; - else - return default_val; - } - else { - return default_val; - } -} - -void -gr_prefs::set_bool(const std::string §ion, const std::string &option, bool val) -{ - std::string s = section; - std::transform(section.begin(), section.end(), s.begin(), ::tolower); - - std::string o = option; - std::transform(option.begin(), option.end(), o.begin(), ::tolower); - - std::map<std::string, std::string> opt_map = d_config_map[s]; - - std::stringstream sstr; - sstr << (val == true); - opt_map[o] = sstr.str(); - - d_config_map[s] = opt_map; -} - -long -gr_prefs::get_long(const std::string §ion, const std::string &option, long default_val) -{ - if(has_option(section, option)) { - std::string str = get_string(section, option, ""); - if(str == "") { - return default_val; - } - std::stringstream sstr(str); - long n; - sstr >> n; - return n; - } - else { - return default_val; - } -} - -void -gr_prefs::set_long(const std::string §ion, const std::string &option, long val) -{ - std::string s = section; - std::transform(section.begin(), section.end(), s.begin(), ::tolower); - - std::string o = option; - std::transform(option.begin(), option.end(), o.begin(), ::tolower); - - std::map<std::string, std::string> opt_map = d_config_map[s]; - - std::stringstream sstr; - sstr << val; - opt_map[o] = sstr.str(); - - d_config_map[s] = opt_map; -} - -double -gr_prefs::get_double(const std::string §ion, const std::string &option, double default_val) -{ - if(has_option(section, option)) { - std::string str = get_string(section, option, ""); - if(str == "") { - return default_val; - } - std::stringstream sstr(str); - double n; - sstr >> n; - return n; - } - else { - return default_val; - } -} - -void -gr_prefs::set_double(const std::string §ion, const std::string &option, double val) -{ - std::string s = section; - std::transform(section.begin(), section.end(), s.begin(), ::tolower); - - std::string o = option; - std::transform(option.begin(), option.end(), o.begin(), ::tolower); - - std::map<std::string, std::string> opt_map = d_config_map[s]; - - std::stringstream sstr; - sstr << val; - opt_map[o] = sstr.str(); - - d_config_map[s] = opt_map; -} diff --git a/gnuradio-runtime/lib/gr_random.cc b/gnuradio-runtime/lib/gr_random.cc deleted file mode 100644 index 323839acc7..0000000000 --- a/gnuradio-runtime/lib/gr_random.cc +++ /dev/null @@ -1,183 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2002 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -/* - * Copyright 1997 Massachusetts Institute of Technology - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, provided that - * the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation, and that the name of M.I.T. not be used in advertising or - * publicity pertaining to distribution of the software without specific, - * written prior permission. M.I.T. makes no representations about the - * suitability of this software for any purpose. It is provided "as is" - * without express or implied warranty. - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <math.h> -#include <gr_random.h> - -#define IA 16807 -#define IM 2147483647 -#define AM (1.0/IM) -#define IQ 127773 -#define IR 2836 -#define NDIV (1+(IM-1)/NTAB) -#define EPS 1.2e-7 -#define RNMX (1.0-EPS) - - -gr_random::gr_random (long seed) -{ - reseed (seed); -} - -void -gr_random::reseed (long seed) -{ - d_seed = seed; - d_iy = 0; - for (int i = 0; i < NTAB; i++) - d_iv[i] = 0; - d_iset = 0; - d_gset = 0; -} - -/* - * This looks like it returns a uniform random deviate between 0.0 and 1.0 - * It looks similar to code from "Numerical Recipes in C". - */ -float gr_random::ran1() -{ - int j; - long k; - float temp; - - if (d_seed <= 0 || !d_iy) { - if (-d_seed < 1) - d_seed=1; - else - d_seed = -d_seed; - for (j=NTAB+7;j>=0;j--) { - k=d_seed/IQ; - d_seed=IA*(d_seed-k*IQ)-IR*k; - if (d_seed < 0) - d_seed += IM; - if (j < NTAB) - d_iv[j] = d_seed; - } - d_iy=d_iv[0]; - } - k=(d_seed)/IQ; - d_seed=IA*(d_seed-k*IQ)-IR*k; - if (d_seed < 0) - d_seed += IM; - j=d_iy/NDIV; - d_iy=d_iv[j]; - d_iv[j] = d_seed; - temp=AM * d_iy; - if (temp > RNMX) - temp = RNMX; - return temp; -} - -/* - * Returns a normally distributed deviate with zero mean and variance 1. - * Also looks like it's from "Numerical Recipes in C". - */ -float gr_random::gasdev() -{ - float fac,rsq,v1,v2; - d_iset = 1 - d_iset; - if (d_iset) { - do { - v1=2.0*ran1()-1.0; - v2=2.0*ran1()-1.0; - rsq=v1*v1+v2*v2; - } while (rsq >= 1.0 || rsq == 0.0); - fac= sqrt(-2.0*log(rsq)/rsq); - d_gset=v1*fac; - return v2*fac; - } - return d_gset; -} - -/* - * Copied from The KC7WW / OH2BNS Channel Simulator - * FIXME Need to check how good this is at some point - */ - -float gr_random::laplacian() -{ - float z = ran1(); - if (z < 0.5) - return log(2.0 * z) / M_SQRT2; - else - return -log(2.0 * (1.0 - z)) / M_SQRT2; -} - -/* - * Copied from The KC7WW / OH2BNS Channel Simulator - * FIXME Need to check how good this is at some point - */ - - // 5 => scratchy, 8 => Geiger - -float gr_random::impulse(float factor = 5) -{ - float z = -M_SQRT2 * log(ran1()); - if (fabsf(z) <= factor) - return 0.0; - else - return z; -} - -/* - * Complex rayleigh is really gaussian I and gaussian Q - * It can also be generated by real rayleigh magnitude and - * uniform random angle - * Adapted from The KC7WW / OH2BNS Channel Simulator - * FIXME Need to check how good this is at some point - */ - -gr_complex gr_random::rayleigh_complex() -{ - return gr_complex(gasdev(),gasdev()); -} - -/* Other option - mag = rayleigh(); - ang = 2.0 * M_PI * RNG(); - *Rx = rxx * cos(z); - *Iy = rxx * sin(z); -*/ - - -float gr_random::rayleigh() -{ - return sqrt(-2.0 * log(ran1())); -} diff --git a/gnuradio-runtime/lib/gr_random.h b/gnuradio-runtime/lib/gr_random.h deleted file mode 100644 index 783c05f920..0000000000 --- a/gnuradio-runtime/lib/gr_random.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2002 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_RANDOM_H -#define INCLUDED_GR_RANDOM_H - -#include <gr_runtime_api.h> -#include <gr_complex.h> - -/*! - * \brief pseudo random number generator - * \ingroup math_blk - */ -class GR_RUNTIME_API gr_random { -protected: - static const int NTAB = 32; - long d_seed; - long d_iy; - long d_iv[NTAB]; - int d_iset; - float d_gset; - - -public: - gr_random (long seed=3021); - - void reseed (long seed); - - /*! - * \brief uniform random deviate in the range [0.0, 1.0) - */ - float ran1 (); - - /*! - * \brief normally distributed deviate with zero mean and variance 1 - */ - float gasdev (); - - float laplacian (); - float impulse (float factor); - float rayleigh (); - gr_complex rayleigh_complex (); -}; - -#endif /* INCLUDED_GR_RANDOM_H */ - diff --git a/gnuradio-runtime/lib/gr_realtime.cc b/gnuradio-runtime/lib/gr_realtime.cc deleted file mode 100644 index d7a7eab5ba..0000000000 --- a/gnuradio-runtime/lib/gr_realtime.cc +++ /dev/null @@ -1,33 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2007,2008 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gr_realtime.h> - -gr_rt_status_t -gr_enable_realtime_scheduling() -{ - return gr_enable_realtime_scheduling(); -} diff --git a/gnuradio-runtime/lib/gr_reverse.h b/gnuradio-runtime/lib/gr_reverse.h deleted file mode 100644 index aa8619619f..0000000000 --- a/gnuradio-runtime/lib/gr_reverse.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef INCLUDED_GR_REVERSE_H -#define INCLUDED_GR_REVERSE_H - -#include <gr_runtime_api.h> -#include <vector> -#include <gr_complex.h> - -// reverse the order of taps -std::vector<float> gr_reverse (const std::vector<float> &taps); -std::vector<gr_complex> gr_reverse (const std::vector<gr_complex> &taps); - - -#endif /* INCLUDED_GR_REVERSE_H */ diff --git a/gnuradio-runtime/lib/gr_scheduler.h b/gnuradio-runtime/lib/gr_scheduler.h deleted file mode 100644 index 097f575c21..0000000000 --- a/gnuradio-runtime/lib/gr_scheduler.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 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 3, 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_GR_SCHEDULER_H -#define INCLUDED_GR_SCHEDULER_H - -#include <gr_runtime_api.h> -#include <boost/utility.hpp> -#include <gr_block.h> -#include <gr_flat_flowgraph.h> - - -class gr_scheduler; -typedef boost::shared_ptr<gr_scheduler> gr_scheduler_sptr; - - -/*! - * \brief Abstract scheduler that takes a flattened flow graph and runs it. - * - * Preconditions: details, buffers and buffer readers have been assigned. - */ -class GR_RUNTIME_API gr_scheduler : boost::noncopyable -{ - -public: - /*! - * \brief Construct a scheduler and begin evaluating the graph. - * - * The scheduler will continue running until all blocks until they - * report that they are done or the stop method is called. - */ - gr_scheduler(gr_flat_flowgraph_sptr ffg, int max_noutput_items); - - virtual ~gr_scheduler(); - - /*! - * \brief Tell the scheduler to stop executing. - */ - virtual void stop() = 0; - - /*! - * \brief Block until the graph is done. - */ - virtual void wait() = 0; -}; - -#endif /* INCLUDED_GR_SCHEDULER_H */ diff --git a/gnuradio-runtime/lib/gr_scheduler_sts.cc b/gnuradio-runtime/lib/gr_scheduler_sts.cc deleted file mode 100644 index 10f01edaf6..0000000000 --- a/gnuradio-runtime/lib/gr_scheduler_sts.cc +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 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 3, 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 <config.h> -#endif -#include <gr_scheduler_sts.h> -#include <gr_single_threaded_scheduler.h> -#include <thread/thread_body_wrapper.h> - -class sts_container -{ - gr_block_vector_t d_blocks; - -public: - - sts_container(gr_block_vector_t blocks) - : d_blocks(blocks) {} - - void operator()() - { - gr_make_single_threaded_scheduler(d_blocks)->run(); - } -}; - - -gr_scheduler_sptr -gr_scheduler_sts::make(gr_flat_flowgraph_sptr ffg, int max_noutput_items) -{ - return gr_scheduler_sptr(new gr_scheduler_sts(ffg, max_noutput_items)); -} - -gr_scheduler_sts::gr_scheduler_sts(gr_flat_flowgraph_sptr ffg, int max_noutput_items) - : gr_scheduler(ffg, max_noutput_items) -{ - // Split the flattened flow graph into discrete partitions, each - // of which is topologically sorted. - - std::vector<gr_basic_block_vector_t> graphs = ffg->partition(); - - // For each partition, create a thread to evaluate it using - // an instance of the gr_single_threaded_scheduler - - for (std::vector<gr_basic_block_vector_t>::iterator p = graphs.begin(); - p != graphs.end(); p++) { - - gr_block_vector_t blocks = gr_flat_flowgraph::make_block_vector(*p); - d_threads.create_thread( - gr::thread::thread_body_wrapper<sts_container>(sts_container(blocks), - "single-threaded-scheduler")); - } -} - -gr_scheduler_sts::~gr_scheduler_sts() -{ - stop(); -} - -void -gr_scheduler_sts::stop() -{ - d_threads.interrupt_all(); -} - -void -gr_scheduler_sts::wait() -{ - d_threads.join_all(); -} diff --git a/gnuradio-runtime/lib/gr_scheduler_sts.h b/gnuradio-runtime/lib/gr_scheduler_sts.h deleted file mode 100644 index af98c6d8ba..0000000000 --- a/gnuradio-runtime/lib/gr_scheduler_sts.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 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 3, 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_GR_SCHEDULER_STS_H -#define INCLUDED_GR_SCHEDULER_STS_H - -#include <gr_runtime_api.h> -#include <gr_scheduler.h> -#include <thread/thread_group.h> - -/*! - * \brief Concrete scheduler that uses the single_threaded_scheduler - */ -class GR_RUNTIME_API gr_scheduler_sts : public gr_scheduler -{ - gr::thread::thread_group d_threads; - -protected: - /*! - * \brief Construct a scheduler and begin evaluating the graph. - * - * The scheduler will continue running until all blocks until they - * report that they are done or the stop method is called. - */ - gr_scheduler_sts(gr_flat_flowgraph_sptr ffg, int max_noutput_items); - -public: - static gr_scheduler_sptr make(gr_flat_flowgraph_sptr ffg, int max_noutput_items); - - ~gr_scheduler_sts(); - - /*! - * \brief Tell the scheduler to stop executing. - */ - void stop(); - - /*! - * \brief Block until the graph is done. - */ - void wait(); -}; - - - - -#endif /* INCLUDED_GR_SCHEDULER_STS_H */ diff --git a/gnuradio-runtime/lib/gr_scheduler_tpb.cc b/gnuradio-runtime/lib/gr_scheduler_tpb.cc deleted file mode 100644 index e67078632f..0000000000 --- a/gnuradio-runtime/lib/gr_scheduler_tpb.cc +++ /dev/null @@ -1,103 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 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 3, 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 <config.h> -#endif -#include <gr_scheduler_tpb.h> -#include <gr_tpb_thread_body.h> -#include <thread/thread_body_wrapper.h> -#include <sstream> - -/* - * You know, a lambda expression would be sooo much easier... - */ -class tpb_container -{ - gr_block_sptr d_block; - int d_max_noutput_items; - -public: - tpb_container(gr_block_sptr block, int max_noutput_items) - : d_block(block), d_max_noutput_items(max_noutput_items) {} - - void operator()() - { - gr_tpb_thread_body body(d_block, d_max_noutput_items); - } -}; - - -gr_scheduler_sptr -gr_scheduler_tpb::make(gr_flat_flowgraph_sptr ffg, int max_noutput_items) -{ - return gr_scheduler_sptr(new gr_scheduler_tpb(ffg, max_noutput_items)); -} - -gr_scheduler_tpb::gr_scheduler_tpb(gr_flat_flowgraph_sptr ffg, int max_noutput_items) - : gr_scheduler(ffg, max_noutput_items) -{ - // Get a topologically sorted vector of all the blocks in use. - // Being topologically sorted probably isn't going to matter, but - // there's a non-zero chance it might help... - - gr_basic_block_vector_t used_blocks = ffg->calc_used_blocks(); - used_blocks = ffg->topological_sort(used_blocks); - gr_block_vector_t blocks = gr_flat_flowgraph::make_block_vector(used_blocks); - - // Ensure that the done flag is clear on all blocks - - for (size_t i = 0; i < blocks.size(); i++){ - blocks[i]->detail()->set_done(false); - } - - // Fire off a thead for each block - - for (size_t i = 0; i < blocks.size(); i++){ - std::stringstream name; - name << "thread-per-block[" << i << "]: " << blocks[i]; - - // If set, use internal value instead of global value - if(blocks[i]->is_set_max_noutput_items()) - max_noutput_items = blocks[i]->max_noutput_items(); - - d_threads.create_thread( - gr::thread::thread_body_wrapper<tpb_container>(tpb_container(blocks[i], max_noutput_items), - name.str())); - } -} - -gr_scheduler_tpb::~gr_scheduler_tpb() -{ - stop(); -} - -void -gr_scheduler_tpb::stop() -{ - d_threads.interrupt_all(); -} - -void -gr_scheduler_tpb::wait() -{ - d_threads.join_all(); -} diff --git a/gnuradio-runtime/lib/gr_scheduler_tpb.h b/gnuradio-runtime/lib/gr_scheduler_tpb.h deleted file mode 100644 index 4ab7bb16d2..0000000000 --- a/gnuradio-runtime/lib/gr_scheduler_tpb.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008 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 3, 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_GR_SCHEDULER_TPB_H -#define INCLUDED_GR_SCHEDULER_TPB_H - -#include <gr_runtime_api.h> -#include <gr_scheduler.h> -#include <thread/thread_group.h> - -/*! - * \brief Concrete scheduler that uses a kernel thread-per-block - */ -class GR_RUNTIME_API gr_scheduler_tpb : public gr_scheduler -{ - gr::thread::thread_group d_threads; - -protected: - /*! - * \brief Construct a scheduler and begin evaluating the graph. - * - * The scheduler will continue running until all blocks until they - * report that they are done or the stop method is called. - */ - gr_scheduler_tpb(gr_flat_flowgraph_sptr ffg, int max_noutput_items); - -public: - static gr_scheduler_sptr make(gr_flat_flowgraph_sptr ffg, int max_noutput_items=100000); - - ~gr_scheduler_tpb(); - - /*! - * \brief Tell the scheduler to stop executing. - */ - void stop(); - - /*! - * \brief Block until the graph is done. - */ - void wait(); -}; - - -#endif /* INCLUDED_GR_SCHEDULER_TPB_H */ diff --git a/gnuradio-runtime/lib/gr_single_threaded_scheduler.cc b/gnuradio-runtime/lib/gr_single_threaded_scheduler.cc deleted file mode 100644 index 1bb9e9b0a8..0000000000 --- a/gnuradio-runtime/lib/gr_single_threaded_scheduler.cc +++ /dev/null @@ -1,364 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_single_threaded_scheduler.h> -#include <gr_block.h> -#include <gr_block_detail.h> -#include <gr_buffer.h> -#include <boost/thread.hpp> -#include <boost/format.hpp> -#include <iostream> -#include <limits> -#include <assert.h> -#include <stdio.h> - -// must be defined to either 0 or 1 -#define ENABLE_LOGGING 0 - -#if (ENABLE_LOGGING) -#define LOG(x) do { x; } while(0) -#else -#define LOG(x) do {;} while(0) -#endif - -static int which_scheduler = 0; - -gr_single_threaded_scheduler_sptr -gr_make_single_threaded_scheduler (const std::vector<gr_block_sptr> &blocks) -{ - return - gr_single_threaded_scheduler_sptr (new gr_single_threaded_scheduler (blocks)); -} - -gr_single_threaded_scheduler::gr_single_threaded_scheduler ( - const std::vector<gr_block_sptr> &blocks) - : d_blocks (blocks), d_enabled (true), d_log(0) -{ - if (ENABLE_LOGGING){ - std::string name = str(boost::format("sst-%d.log") % which_scheduler++); - d_log = new std::ofstream(name.c_str()); - *d_log << "gr_single_threaded_scheduler: " - << d_blocks.size () - << " blocks\n"; - } -} - -gr_single_threaded_scheduler::~gr_single_threaded_scheduler () -{ - if (ENABLE_LOGGING) - delete d_log; -} - -void -gr_single_threaded_scheduler::run () -{ - // d_enabled = true; // KLUDGE - main_loop (); -} - -void -gr_single_threaded_scheduler::stop () -{ - if (0) - std::cout << "gr_singled_threaded_scheduler::stop() " - << this << std::endl; - d_enabled = false; -} - -inline static unsigned int -round_up (unsigned int n, unsigned int multiple) -{ - return ((n + multiple - 1) / multiple) * multiple; -} - -inline static unsigned int -round_down (unsigned int n, unsigned int multiple) -{ - return (n / multiple) * multiple; -} - -// -// Return minimum available write space in all our downstream buffers -// or -1 if we're output blocked and the output we're blocked -// on is done. -// -static int -min_available_space (gr_block_detail *d, int output_multiple) -{ - int min_space = std::numeric_limits<int>::max(); - - for (int i = 0; i < d->noutputs (); i++){ - int n = round_down (d->output(i)->space_available (), output_multiple); - if (n == 0){ // We're blocked on output. - if (d->output(i)->done()){ // Downstream is done, therefore we're done. - return -1; - } - return 0; - } - min_space = std::min (min_space, n); - } - return min_space; -} - -void -gr_single_threaded_scheduler::main_loop () -{ - static const int DEFAULT_CAPACITY = 16; - - int noutput_items; - gr_vector_int ninput_items_required (DEFAULT_CAPACITY); - gr_vector_int ninput_items (DEFAULT_CAPACITY); - gr_vector_const_void_star input_items (DEFAULT_CAPACITY); - gr_vector_void_star output_items (DEFAULT_CAPACITY); - unsigned int bi; - unsigned int nalive; - int max_items_avail; - bool made_progress_last_pass; - bool making_progress; - - for (unsigned i = 0; i < d_blocks.size (); i++) - d_blocks[i]->detail()->set_done (false); // reset any done flags - - for (unsigned i = 0; i < d_blocks.size (); i++) // enable any drivers, etc. - d_blocks[i]->start(); - - - bi = 0; - made_progress_last_pass = true; - making_progress = false; - - // Loop while there are still blocks alive - - nalive = d_blocks.size (); - while (d_enabled && nalive > 0){ - - if (boost::this_thread::interruption_requested()) - break; - - gr_block *m = d_blocks[bi].get (); - gr_block_detail *d = m->detail().get (); - - LOG(*d_log << std::endl << m); - - if (d->done ()) - goto next_block; - - if (d->source_p ()){ - // Invoke sources as a last resort. As long as the previous pass - // made progress, don't call a source. - if (made_progress_last_pass){ - LOG(*d_log << " Skipping source\n"); - goto next_block; - } - - ninput_items_required.resize (0); - ninput_items.resize (0); - input_items.resize (0); - output_items.resize (d->noutputs ()); - - // determine the minimum available output space - noutput_items = min_available_space (d, m->output_multiple ()); - LOG(*d_log << " source\n noutput_items = " << noutput_items << std::endl); - if (noutput_items == -1) // we're done - goto were_done; - - if (noutput_items == 0){ // we're output blocked - LOG(*d_log << " BLKD_OUT\n"); - goto next_block; - } - - goto setup_call_to_work; // jump to common code - } - - else if (d->sink_p ()){ - ninput_items_required.resize (d->ninputs ()); - ninput_items.resize (d->ninputs ()); - input_items.resize (d->ninputs ()); - output_items.resize (0); - LOG(*d_log << " sink\n"); - - max_items_avail = 0; - for (int i = 0; i < d->ninputs (); i++){ - ninput_items[i] = d->input(i)->items_available(); - //if (ninput_items[i] == 0 && d->input(i)->done()) - if (ninput_items[i] < m->output_multiple() && d->input(i)->done()) - goto were_done; - - max_items_avail = std::max (max_items_avail, ninput_items[i]); - } - - // take a swag at how much output we can sink - noutput_items = (int) (max_items_avail * m->relative_rate ()); - noutput_items = round_down (noutput_items, m->output_multiple ()); - LOG(*d_log << " max_items_avail = " << max_items_avail << std::endl); - LOG(*d_log << " noutput_items = " << noutput_items << std::endl); - - if (noutput_items == 0){ // we're blocked on input - LOG(*d_log << " BLKD_IN\n"); - goto next_block; - } - - goto try_again; // Jump to code shared with regular case. - } - - else { - // do the regular thing - ninput_items_required.resize (d->ninputs ()); - ninput_items.resize (d->ninputs ()); - input_items.resize (d->ninputs ()); - output_items.resize (d->noutputs ()); - - max_items_avail = 0; - for (int i = 0; i < d->ninputs (); i++){ - ninput_items[i] = d->input(i)->items_available (); - max_items_avail = std::max (max_items_avail, ninput_items[i]); - } - - // determine the minimum available output space - noutput_items = min_available_space (d, m->output_multiple ()); - if (ENABLE_LOGGING){ - *d_log << " regular "; - if (m->relative_rate() >= 1.0) - *d_log << "1:" << m->relative_rate() << std::endl; - else - *d_log << 1.0/m->relative_rate() << ":1\n"; - *d_log << " max_items_avail = " << max_items_avail << std::endl; - *d_log << " noutput_items = " << noutput_items << std::endl; - } - if (noutput_items == -1) // we're done - goto were_done; - - if (noutput_items == 0){ // we're output blocked - LOG(*d_log << " BLKD_OUT\n"); - goto next_block; - } - -#if 0 - // Compute best estimate of noutput_items that we can really use. - noutput_items = - std::min ((unsigned) noutput_items, - std::max ((unsigned) m->output_multiple(), - round_up ((unsigned) (max_items_avail * m->relative_rate()), - m->output_multiple ()))); - - LOG(*d_log << " revised noutput_items = " << noutput_items << std::endl); -#endif - - try_again: - if (m->fixed_rate()){ - // try to work it forward starting with max_items_avail. - // We want to try to consume all the input we've got. - int reqd_noutput_items = m->fixed_rate_ninput_to_noutput(max_items_avail); - reqd_noutput_items = round_up(reqd_noutput_items, m->output_multiple()); - if (reqd_noutput_items > 0 && reqd_noutput_items <= noutput_items) - noutput_items = reqd_noutput_items; - } - - // ask the block how much input they need to produce noutput_items - m->forecast (noutput_items, ninput_items_required); - - // See if we've got sufficient input available - - int i; - for (i = 0; i < d->ninputs (); i++) - if (ninput_items_required[i] > ninput_items[i]) // not enough - break; - - if (i < d->ninputs ()){ // not enough input on input[i] - // if we can, try reducing the size of our output request - if (noutput_items > m->output_multiple ()){ - noutput_items /= 2; - noutput_items = round_up (noutput_items, m->output_multiple ()); - goto try_again; - } - - // We're blocked on input - LOG(*d_log << " BLKD_IN\n"); - if (d->input(i)->done()) // If the upstream block is done, we're done - goto were_done; - - // Is it possible to ever fulfill this request? - if (ninput_items_required[i] > d->input(i)->max_possible_items_available ()){ - // Nope, never going to happen... - std::cerr << "\nsched: <gr_block " << m->name() - << " (" << m->unique_id() << ")>" - << " is requesting more input data\n" - << " than we can provide.\n" - << " ninput_items_required = " - << ninput_items_required[i] << "\n" - << " max_possible_items_available = " - << d->input(i)->max_possible_items_available() << "\n" - << " If this is a filter, consider reducing the number of taps.\n"; - goto were_done; - } - - goto next_block; - } - - // We've got enough data on each input to produce noutput_items. - // Finish setting up the call to work. - - for (int i = 0; i < d->ninputs (); i++) - input_items[i] = d->input(i)->read_pointer(); - - setup_call_to_work: - - for (int i = 0; i < d->noutputs (); i++) - output_items[i] = d->output(i)->write_pointer(); - - // Do the actual work of the block - int n = m->general_work (noutput_items, ninput_items, - input_items, output_items); - LOG(*d_log << " general_work: noutput_items = " << noutput_items - << " result = " << n << std::endl); - - if (n == -1) // block is done - goto were_done; - - d->produce_each (n); // advance write pointers - if (n > 0) - making_progress = true; - - goto next_block; - } - assert (0); - - were_done: - LOG(*d_log << " were_done\n"); - d->set_done (true); - nalive--; - - next_block: - if (++bi >= d_blocks.size ()){ - bi = 0; - made_progress_last_pass = making_progress; - making_progress = false; - } - } - - for (unsigned i = 0; i < d_blocks.size (); i++) // disable any drivers, etc. - d_blocks[i]->stop(); -} diff --git a/gnuradio-runtime/lib/gr_sync_block.cc b/gnuradio-runtime/lib/gr_sync_block.cc deleted file mode 100644 index 94efcdc8ee..0000000000 --- a/gnuradio-runtime/lib/gr_sync_block.cc +++ /dev/null @@ -1,68 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_sync_block.h> - -gr_sync_block::gr_sync_block (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature) - : gr_block(name, input_signature, output_signature) -{ - set_fixed_rate(true); -} - - -void -gr_sync_block::forecast (int noutput_items, gr_vector_int &ninput_items_required) -{ - unsigned ninputs = ninput_items_required.size(); - for (unsigned i = 0; i < ninputs; i++) - ninput_items_required[i] = fixed_rate_noutput_to_ninput (noutput_items); -} - -int -gr_sync_block::fixed_rate_noutput_to_ninput(int noutput_items) -{ - return noutput_items + history() - 1; -} - -int -gr_sync_block::fixed_rate_ninput_to_noutput(int ninput_items) -{ - return std::max(0, ninput_items - (int)history() + 1); -} - -int -gr_sync_block::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - int r = work (noutput_items, input_items, output_items); - if (r > 0) - consume_each (r); - return r; -} diff --git a/gnuradio-runtime/lib/gr_sync_decimator.cc b/gnuradio-runtime/lib/gr_sync_decimator.cc deleted file mode 100644 index a0f907db53..0000000000 --- a/gnuradio-runtime/lib/gr_sync_decimator.cc +++ /dev/null @@ -1,69 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_sync_decimator.h> - -gr_sync_decimator::gr_sync_decimator (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature, - unsigned decimation) - : gr_sync_block (name, input_signature, output_signature) -{ - set_decimation (decimation); -} - -void -gr_sync_decimator::forecast (int noutput_items, gr_vector_int &ninput_items_required) -{ - unsigned ninputs = ninput_items_required.size (); - for (unsigned i = 0; i < ninputs; i++) - ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items); -} - -int -gr_sync_decimator::fixed_rate_noutput_to_ninput(int noutput_items) -{ - return noutput_items * decimation() + history() - 1; -} - -int -gr_sync_decimator::fixed_rate_ninput_to_noutput(int ninput_items) -{ - return std::max(0, ninput_items - (int)history() + 1) / decimation(); -} - -int -gr_sync_decimator::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - int r = work (noutput_items, input_items, output_items); - if (r > 0) - consume_each (r * decimation ()); - return r; -} - diff --git a/gnuradio-runtime/lib/gr_sync_interpolator.cc b/gnuradio-runtime/lib/gr_sync_interpolator.cc deleted file mode 100644 index ece873c14a..0000000000 --- a/gnuradio-runtime/lib/gr_sync_interpolator.cc +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2008 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_sync_interpolator.h> - -gr_sync_interpolator::gr_sync_interpolator (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature, - unsigned interpolation) - : gr_sync_block (name, input_signature, output_signature) -{ - set_interpolation (interpolation); -} - -void -gr_sync_interpolator::forecast (int noutput_items, gr_vector_int &ninput_items_required) -{ - unsigned ninputs = ninput_items_required.size (); - for (unsigned i = 0; i < ninputs; i++) - ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items); -} - -int -gr_sync_interpolator::fixed_rate_noutput_to_ninput(int noutput_items) -{ - return noutput_items / interpolation() + history() - 1; -} - -int -gr_sync_interpolator::fixed_rate_ninput_to_noutput(int ninput_items) -{ - return std::max(0, ninput_items - (int)history() + 1) * interpolation(); -} - -int -gr_sync_interpolator::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - int r = work (noutput_items, input_items, output_items); - if (r > 0) - consume_each (r / interpolation ()); - return r; -} - - diff --git a/gnuradio-runtime/lib/gr_tagged_stream_block.cc b/gnuradio-runtime/lib/gr_tagged_stream_block.cc deleted file mode 100644 index a60515f481..0000000000 --- a/gnuradio-runtime/lib/gr_tagged_stream_block.cc +++ /dev/null @@ -1,146 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <boost/format.hpp> -#include <gr_tagged_stream_block.h> - -gr_tagged_stream_block::gr_tagged_stream_block (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature, - const std::string &length_tag_key) - : gr_block(name, input_signature, output_signature), - d_length_tag_key(pmt::string_to_symbol(length_tag_key)), - d_n_input_items_reqd(input_signature->min_streams(), 0), - d_length_tag_key_str(length_tag_key) -{ -} - - -// This is evil hackery: We trick the scheduler into creating the right number of input items -void -gr_tagged_stream_block::forecast (int noutput_items, gr_vector_int &ninput_items_required) -{ - unsigned ninputs = ninput_items_required.size(); - for (unsigned i = 0; i < ninputs; i++) { - if (i < d_n_input_items_reqd.size() && d_n_input_items_reqd[i] != 0) { - ninput_items_required[i] = d_n_input_items_reqd[i]; - } else { - // If there's no item, there's no tag--so there must at least be one! - ninput_items_required[i] = std::max(1, (int) std::floor((double) noutput_items / relative_rate() + 0.5)); - } - } -} - - -void -gr_tagged_stream_block::parse_length_tags( - const std::vector<std::vector<gr_tag_t> > &tags, - gr_vector_int &n_input_items_reqd -){ - for (unsigned i = 0; i < tags.size(); i++) { - for (unsigned k = 0; k < tags[i].size(); k++) { - if (tags[i][k].key == d_length_tag_key) { - n_input_items_reqd[i] = pmt::to_long(tags[i][k].value); - remove_item_tag(i, tags[i][k]); - } - } - } -} - - -int -gr_tagged_stream_block::calculate_output_stream_length(const gr_vector_int &ninput_items) -{ - int noutput_items = *std::max_element(ninput_items.begin(), ninput_items.end()); - return (int) std::floor(relative_rate() * noutput_items + 0.5); -} - - -void -gr_tagged_stream_block::update_length_tags(int n_produced, int n_ports) -{ - for (int i = 0; i < n_ports; i++) { - add_item_tag(i, nitems_written(i), - d_length_tag_key, - pmt::from_long(n_produced) - ); - } - return; -} - - -int -gr_tagged_stream_block::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - if (d_length_tag_key_str.empty()) { - return work(noutput_items, ninput_items, input_items, output_items); - } - - if (d_n_input_items_reqd[0] == 0) { // Otherwise, it's already set from a previous call - std::vector<std::vector<gr_tag_t> > tags(input_items.size(), std::vector<gr_tag_t>()); - for (unsigned i = 0; i < input_items.size(); i++) { - get_tags_in_range(tags[i], i, nitems_read(i), nitems_read(i)+1); - } - d_n_input_items_reqd.assign(input_items.size(), -1); - parse_length_tags(tags, d_n_input_items_reqd); - } - for (unsigned i = 0; i < input_items.size(); i++) { - if (d_n_input_items_reqd[i] == -1) { - GR_LOG_FATAL(d_logger, boost::format("Missing a required length tag on port %1% at item #%2%") % i % nitems_read(i)); - throw std::runtime_error("Missing length tag."); - } - if (d_n_input_items_reqd[i] > ninput_items[i]) { - return 0; - } - } - - int min_output_size = calculate_output_stream_length(d_n_input_items_reqd); - if (noutput_items < min_output_size) { - set_min_noutput_items(min_output_size); - return 0; - } - set_min_noutput_items(1); - - // WORK CALLED HERE // - int n_produced = work(noutput_items, d_n_input_items_reqd, input_items, output_items); - ////////////////////// - - if (n_produced == WORK_DONE) { - return n_produced; - } - for (int i = 0; i < (int) d_n_input_items_reqd.size(); i++) { - consume(i, d_n_input_items_reqd[i]); - } - update_length_tags(n_produced, output_items.size()); - - d_n_input_items_reqd.assign(input_items.size(), 0); - - return n_produced; -} - diff --git a/gnuradio-runtime/lib/gr_test.cc b/gnuradio-runtime/lib/gr_test.cc deleted file mode 100644 index cd5ef83611..0000000000 --- a/gnuradio-runtime/lib/gr_test.cc +++ /dev/null @@ -1,177 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2008,2010 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_test.h> -#include <gr_io_signature.h> -#include <stdexcept> -#include <iostream> -#include <string.h> - -gr_test_sptr gr_make_test (const std::string &name, - int min_inputs, int max_inputs, unsigned int sizeof_input_item, - int min_outputs, int max_outputs, unsigned int sizeof_output_item, - unsigned int history,unsigned int output_multiple,double relative_rate, - bool fixed_rate,gr_consume_type_t cons_type, gr_produce_type_t prod_type) -{ - return gnuradio::get_initial_sptr(new gr_test (name, min_inputs,max_inputs,sizeof_input_item, - min_outputs,max_outputs,sizeof_output_item, - history,output_multiple,relative_rate,fixed_rate,cons_type, prod_type)); -} - - gr_test::gr_test (const std::string &name,int min_inputs, int max_inputs, unsigned int sizeof_input_item, - int min_outputs, int max_outputs, unsigned int sizeof_output_item, - unsigned int history,unsigned int output_multiple,double relative_rate, - bool fixed_rate,gr_consume_type_t cons_type, gr_produce_type_t prod_type): gr_block (name, - gr_make_io_signature (min_inputs, max_inputs, sizeof_input_item), - gr_make_io_signature (min_outputs, max_outputs, sizeof_output_item)), - d_sizeof_input_item(sizeof_input_item), - d_sizeof_output_item(sizeof_output_item), - d_check_topology(true), - d_consume_type(cons_type), - d_min_consume(0), - d_max_consume(0), - d_produce_type(prod_type), - d_min_produce(0), - d_max_produce(0) - { - set_history(history); - set_output_multiple(output_multiple); - set_relative_rate(relative_rate); - set_fixed_rate(fixed_rate); - } - -int -gr_test::general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) - { - //touch all inputs and outputs to detect segfaults - unsigned ninputs = input_items.size (); - unsigned noutputs= output_items.size(); - for (unsigned i = 0; i < ninputs; i++) - { - char * in=(char *)input_items[i]; - if (ninput_items[i]< (int)(noutput_items+history())) - { - std::cerr << "ERROR: ninput_items[" << i << "] < noutput_items+history()" << std::endl; - std::cerr << "ninput_items[" << i << "] = " << ninput_items[i] << std::endl; - std::cerr << "noutput_items+history() = " << noutput_items+history() << std::endl; - std::cerr << "noutput_items = " << noutput_items << std::endl; - std::cerr << "history() = " << history() << std::endl; - throw std::runtime_error ("gr_test"); - } else - { - for (int j=0;j<ninput_items[i];j++) - { - //Touch every available input_item - //We use a class variable to avoid the compiler to optimize this away - for(unsigned int k=0;k<d_sizeof_input_item;k++) - d_temp= in[j*d_sizeof_input_item+k]; - } - switch (d_consume_type) - { - case CONSUME_NOUTPUT_ITEMS: - consume(i,noutput_items); - break; - case CONSUME_NOUTPUT_ITEMS_LIMIT_MAX: - consume(i,std::min(noutput_items,d_max_consume)); - break; - case CONSUME_NOUTPUT_ITEMS_LIMIT_MIN: - consume(i,std::min(std::max(noutput_items,d_min_consume),ninput_items[i])); - break; - case CONSUME_ALL_AVAILABLE: - consume(i,ninput_items[i]); - break; - case CONSUME_ALL_AVAILABLE_LIMIT_MAX: - consume(i,std::min(ninput_items[i],d_max_consume)); - break; -/* //This could result in segfault, uncomment if you want to test this - case CONSUME_ALL_AVAILABLE_LIMIT_MIN: - consume(i,std::max(ninput_items[i],d_max_consume)); - break;*/ - case CONSUME_ZERO: - consume(i,0); - break; - case CONSUME_ONE: - consume(i,1); - break; - case CONSUME_MINUS_ONE: - consume(i,-1); - break; - default: - consume(i,noutput_items); - } - } - } - for (unsigned i = 0; i < noutputs; i++) - { - char * out=(char *)output_items[i]; - { - for (int j=0;j<noutput_items;j++) - { - //Touch every available output_item - for(unsigned int k=0;k<d_sizeof_output_item;k++) - out[j*d_sizeof_input_item+k]=0; - } - } - } - //Now copy input to output until max ninputs or max noutputs is reached - int common_nports=std::min(ninputs,noutputs); - if(d_sizeof_output_item==d_sizeof_input_item) - for (int i = 0; i < common_nports; i++) - { - memcpy(output_items[i],input_items[i],noutput_items*d_sizeof_input_item); - } - int noutput_items_produced=0; - switch (d_produce_type){ - case PRODUCE_NOUTPUT_ITEMS: - noutput_items_produced=noutput_items; - break; - case PRODUCE_NOUTPUT_ITEMS_LIMIT_MAX: - noutput_items_produced=std::min(noutput_items,d_max_produce); - break; -/* //This could result in segfault, uncomment if you want to test this - case PRODUCE_NOUTPUT_ITEMS_LIMIT_MIN: - noutput_items_produced=std::max(noutput_items,d_min_produce); - break;*/ - case PRODUCE_ZERO: - noutput_items_produced=0; - break; - case PRODUCE_ONE: - noutput_items_produced=1; - break; - case PRODUCE_MINUS_ONE: - noutput_items_produced=-1; - break; - default: - noutput_items_produced=noutput_items; - } - return noutput_items_produced; - } - - - diff --git a/gnuradio-runtime/lib/gr_test.h b/gnuradio-runtime/lib/gr_test.h deleted file mode 100644 index 2276ab1967..0000000000 --- a/gnuradio-runtime/lib/gr_test.h +++ /dev/null @@ -1,195 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_TEST_H -#define INCLUDED_GR_TEST_H - -#include <gr_runtime_api.h> -#include <gr_block.h> -#include <string> -#include "gr_test_types.h" - -class gr_test; -typedef boost::shared_ptr<gr_test> gr_test_sptr; - -// public constructor -GR_RUNTIME_API gr_test_sptr gr_make_test (const std::string &name=std::string("gr_test"), - int min_inputs=1, int max_inputs=1, unsigned int sizeof_input_item=1, - int min_outputs=1, int max_outputs=1, unsigned int sizeof_output_item=1, - unsigned int history=1,unsigned int output_multiple=1,double relative_rate=1.0, - bool fixed_rate=true,gr_consume_type_t cons_type=CONSUME_NOUTPUT_ITEMS, gr_produce_type_t prod_type=PRODUCE_NOUTPUT_ITEMS); - -/*! - * \brief Test class for testing runtime system (setting up buffers and such.) - * \ingroup misc - * - * This block does not do any usefull actual data processing. - * It just exposes setting all standard block parameters using the contructor or public methods. - * - * This block can be usefull when testing the runtime system. - * You can force this block to have a large history, decimation - * factor and/or large output_multiple. - * The runtime system should detect this and create large enough buffers - * all through the signal chain. - */ -class GR_RUNTIME_API gr_test : public gr_block { - - public: - - ~gr_test (){} - -int general_work (int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - // ---------------------------------------------------------------- - // override these to define your behavior - // ---------------------------------------------------------------- - - /*! - * \brief Estimate input requirements given output request - * - * \param noutput_items number of output items to produce - * \param ninput_items_required number of input items required on each input stream - * - * Given a request to product \p noutput_items, estimate the number of - * data items required on each input stream. The estimate doesn't have - * to be exact, but should be close. - */ - void forecast (int noutput_items, - gr_vector_int &ninput_items_required) - { - unsigned ninputs = ninput_items_required.size (); - for (unsigned i = 0; i < ninputs; i++) - ninput_items_required[i] = (int)((double)noutput_items / relative_rate()) + (int)history(); - } - - - /*! - * \brief Force check topology to return true or false. - * - * \param check_topology value to return when check_topology is called (true or false) - * default check_topology returns true - * - */ - void set_check_topology (bool check_topology){ d_check_topology=check_topology;} - - /*! - * \brief Confirm that ninputs and noutputs is an acceptable combination. - * - * \param ninputs number of input streams connected - * \param noutputs number of output streams connected - * - * \returns true if this is a valid configuration for this block. - * - * This function is called by the runtime system whenever the - * topology changes. Most classes do not need to override this. - * This check is in addition to the constraints specified by the input - * and output gr_io_signatures. - */ - bool check_topology (int ninputs, int noutputs) { return d_check_topology;} - - // ---------------------------------------------------------------- - /* - * The following two methods provide special case info to the - * scheduler in the event that a block has a fixed input to output - * ratio. gr_sync_block, gr_sync_decimator and gr_sync_interpolator - * override these. If you're fixed rate, subclass one of those. - */ - /*! - * \brief Given ninput samples, return number of output samples that will be produced. - * N.B. this is only defined if fixed_rate returns true. - * Generally speaking, you don't need to override this. - */ - int fixed_rate_ninput_to_noutput(int ninput) { return (int)((double)ninput/relative_rate()); } - - /*! - * \brief Given noutput samples, return number of input samples required to produce noutput. - * N.B. this is only defined if fixed_rate returns true. - */ - int fixed_rate_noutput_to_ninput(int noutput) { return (int)((double)noutput*relative_rate()); } - - /*! - * \brief Set if fixed rate should return true. - * N.B. This is normally a private method but we make it available here as public. - */ - void set_fixed_rate_public(bool fixed_rate){ set_fixed_rate(fixed_rate);} - - /*! - * \brief Set the consume pattern. - * - * \param cons_type which consume pattern to use - */ - void set_consume_type (gr_consume_type_t cons_type) { d_consume_type=cons_type;} - - /*! - * \brief Set the consume limit. - * - * \param limit min or maximum items to consume (depending on consume_type) - */ - void set_consume_limit (unsigned int limit) { d_min_consume=limit; d_max_consume=limit;} - - /*! - * \brief Set the produce pattern. - * - * \param prod_type which produce pattern to use - */ - void set_produce_type (gr_produce_type_t prod_type) { d_produce_type=prod_type;} - - /*! - * \brief Set the produce limit. - * - * \param limit min or maximum items to produce (depending on produce_type) - */ - void set_produce_limit (unsigned int limit) { d_min_produce=limit; d_max_produce=limit;} - - // ---------------------------------------------------------------------------- - - - - protected: - unsigned int d_sizeof_input_item; - unsigned int d_sizeof_output_item; - bool d_check_topology; - char d_temp; - gr_consume_type_t d_consume_type; - int d_min_consume; - int d_max_consume; - gr_produce_type_t d_produce_type; - int d_min_produce; - int d_max_produce; - gr_test (const std::string &name,int min_inputs, int max_inputs, unsigned int sizeof_input_item, - int min_outputs, int max_outputs, unsigned int sizeof_output_item, - unsigned int history,unsigned int output_multiple,double relative_rate, - bool fixed_rate,gr_consume_type_t cons_type, gr_produce_type_t prod_type); - - - - friend GR_RUNTIME_API gr_test_sptr gr_make_test (const std::string &name,int min_inputs, int max_inputs, unsigned int sizeof_input_item, - int min_outputs, int max_outputs, unsigned int sizeof_output_item, - unsigned int history,unsigned int output_multiple,double relative_rate, - bool fixed_rate,gr_consume_type_t cons_type, gr_produce_type_t prod_type); -}; - - - -#endif /* INCLUDED_GR_TEST_H */ diff --git a/gnuradio-runtime/lib/gr_top_block.cc b/gnuradio-runtime/lib/gr_top_block.cc deleted file mode 100644 index 362057aadb..0000000000 --- a/gnuradio-runtime/lib/gr_top_block.cc +++ /dev/null @@ -1,162 +0,0 @@ -/* -*- 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <unistd.h> -#include <gr_top_block.h> -#include <gr_top_block_impl.h> -#include <gr_io_signature.h> -#include <gr_prefs.h> -#include <iostream> - -gr_top_block_sptr -gr_make_top_block(const std::string &name) -{ - return gnuradio::get_initial_sptr(new gr_top_block(name)); -} - -gr_top_block::gr_top_block(const std::string &name) - : gr_hier_block2(name, - gr_make_io_signature(0,0,0), - gr_make_io_signature(0,0,0)) - -{ - d_impl = new gr_top_block_impl(this); -} - -gr_top_block::~gr_top_block() -{ - stop(); - wait(); - - delete d_impl; -} - -void -gr_top_block::start(int max_noutput_items) -{ - d_impl->start(max_noutput_items); - - if(gr_prefs::singleton()->get_bool("ControlPort", "on", false)) { - setup_rpc(); - } -} - -void -gr_top_block::stop() -{ - d_impl->stop(); -} - -void -gr_top_block::wait() -{ - d_impl->wait(); -} - -void -gr_top_block::run(int max_noutput_items) -{ - start(max_noutput_items); - wait(); -} - -void -gr_top_block::lock() -{ - d_impl->lock(); -} - -void -gr_top_block::unlock() -{ - d_impl->unlock(); -} - -std::string -gr_top_block::edge_list() -{ - return d_impl->edge_list(); -} - -void -gr_top_block::dump() -{ - d_impl->dump(); -} - -int -gr_top_block::max_noutput_items() -{ - return d_impl->max_noutput_items(); -} - -void -gr_top_block::set_max_noutput_items(int nmax) -{ - d_impl->set_max_noutput_items(nmax); -} - -gr_top_block_sptr -gr_top_block::to_top_block() -{ - return cast_to_top_block_sptr(shared_from_this()); -} - -void -gr_top_block::setup_rpc() -{ -#ifdef GR_CTRLPORT - if(is_rpc_set()) return; - // Getters - add_rpc_variable( - rpcbasic_sptr(new rpcbasic_register_get<gr_top_block, int>( - alias(), "max noutput_items", - &gr_top_block::max_noutput_items, - pmt::mp(0), pmt::mp(8192), pmt::mp(8192), - "items", "Max number of output items", - RPC_PRIVLVL_MIN, DISPNULL))); - - if(gr_prefs::singleton()->get_bool("ControlPort", "edges_list", false)) { - add_rpc_variable( - rpcbasic_sptr(new rpcbasic_register_get<gr_top_block, std::string>( - alias(), "edge list", - &gr_top_block::edge_list, - pmt::mp(""), pmt::mp(""), pmt::mp(""), - "edges", "List of edges in the graph", - RPC_PRIVLVL_MIN, DISPNULL))); - } - - // Setters - add_rpc_variable( - rpcbasic_sptr(new rpcbasic_register_set<gr_top_block, int>( - alias(), "max noutput_items", - &gr_top_block::set_max_noutput_items, - pmt::mp(0), pmt::mp(8192), pmt::mp(8192), - "items", "Max number of output items", - RPC_PRIVLVL_MIN, DISPNULL))); - rpc_set(); -#endif /* GR_CTRLPORT */ -} diff --git a/gnuradio-runtime/lib/gr_top_block_impl.cc b/gnuradio-runtime/lib/gr_top_block_impl.cc deleted file mode 100644 index ef645ea57d..0000000000 --- a/gnuradio-runtime/lib/gr_top_block_impl.cc +++ /dev/null @@ -1,211 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007,2008 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <gr_top_block.h> -#include <gr_top_block_impl.h> -#include <gr_flat_flowgraph.h> -#include <gr_scheduler_sts.h> -#include <gr_scheduler_tpb.h> -#include <gr_prefs.h> - -#include <stdexcept> -#include <iostream> -#include <string.h> -#include <unistd.h> -#include <stdlib.h> - -#define GR_TOP_BLOCK_IMPL_DEBUG 0 - - -typedef gr_scheduler_sptr (*scheduler_maker)(gr_flat_flowgraph_sptr ffg, - int max_noutput_items); - -static struct scheduler_table { - const char *name; - scheduler_maker f; -} scheduler_table[] = { - { "TPB", gr_scheduler_tpb::make }, // first entry is default - { "STS", gr_scheduler_sts::make } -}; - -static gr_scheduler_sptr -make_scheduler(gr_flat_flowgraph_sptr ffg, int max_noutput_items) -{ - static scheduler_maker factory = 0; - - if (factory == 0){ - char *v = getenv("GR_SCHEDULER"); - if (!v) - factory = scheduler_table[0].f; // use default - else { - for (size_t i = 0; i < sizeof(scheduler_table)/sizeof(scheduler_table[0]); i++){ - if (strcmp(v, scheduler_table[i].name) == 0){ - factory = scheduler_table[i].f; - break; - } - } - if (factory == 0){ - std::cerr << "warning: Invalid GR_SCHEDULER environment variable value \"" - << v << "\". Using \"" << scheduler_table[0].name << "\"\n"; - factory = scheduler_table[0].f; - } - } - } - return factory(ffg, max_noutput_items); -} - - -gr_top_block_impl::gr_top_block_impl(gr_top_block *owner) - : d_owner(owner), d_ffg(), - d_state(IDLE), d_lock_count(0) -{ -} - -gr_top_block_impl::~gr_top_block_impl() -{ - d_owner = 0; -} - -void -gr_top_block_impl::start(int max_noutput_items) -{ - gr::thread::scoped_lock l(d_mutex); - - d_max_noutput_items = max_noutput_items; - - if (d_state != IDLE) - throw std::runtime_error("top_block::start: top block already running or wait() not called after previous stop()"); - - if (d_lock_count > 0) - throw std::runtime_error("top_block::start: can't start with flow graph locked"); - - // Create new flat flow graph by flattening hierarchy - d_ffg = d_owner->flatten(); - - // Validate new simple flow graph and wire it up - d_ffg->validate(); - d_ffg->setup_connections(); - - // Only export perf. counters if ControlPort config param is enabled - // and if the PerfCounter option 'export' is turned on. - gr_prefs *p = gr_prefs::singleton(); - if(p->get_bool("ControlPort", "on", false) && p->get_bool("PerfCounters", "export", false)) - d_ffg->enable_pc_rpc(); - - d_scheduler = make_scheduler(d_ffg, d_max_noutput_items); - d_state = RUNNING; -} - -void -gr_top_block_impl::stop() -{ - if (d_scheduler) - d_scheduler->stop(); -} - - -void -gr_top_block_impl::wait() -{ - if (d_scheduler) - d_scheduler->wait(); - - d_state = IDLE; -} - -// N.B. lock() and unlock() cannot be called from a flow graph thread or -// deadlock will occur when reconfiguration happens -void -gr_top_block_impl::lock() -{ - gr::thread::scoped_lock lock(d_mutex); - d_lock_count++; -} - -void -gr_top_block_impl::unlock() -{ - gr::thread::scoped_lock lock(d_mutex); - - if (d_lock_count <= 0){ - d_lock_count = 0; // fix it, then complain - throw std::runtime_error("unpaired unlock() call"); - } - - d_lock_count--; - if (d_lock_count > 0 || d_state == IDLE) // nothing to do - return; - - restart(); -} - -/* - * restart is called with d_mutex held - */ -void -gr_top_block_impl::restart() -{ - stop(); // Stop scheduler and wait for completion - wait(); - - // Create new simple flow graph - gr_flat_flowgraph_sptr new_ffg = d_owner->flatten(); - new_ffg->validate(); // check consistency, sanity, etc - new_ffg->merge_connections(d_ffg); // reuse buffers, etc - d_ffg = new_ffg; - - // Create a new scheduler to execute it - d_scheduler = make_scheduler(d_ffg, d_max_noutput_items); - d_state = RUNNING; -} - -std::string -gr_top_block_impl::edge_list() -{ - if(d_ffg) - return d_ffg->edge_list(); - else - return ""; -} - -void -gr_top_block_impl::dump() -{ - if (d_ffg) - d_ffg->dump(); -} - -int -gr_top_block_impl::max_noutput_items() -{ - return d_max_noutput_items; -} - -void -gr_top_block_impl::set_max_noutput_items(int nmax) -{ - d_max_noutput_items = nmax; -} diff --git a/gnuradio-runtime/lib/gr_top_block_impl.h b/gnuradio-runtime/lib/gr_top_block_impl.h deleted file mode 100644 index 345a33152f..0000000000 --- a/gnuradio-runtime/lib/gr_top_block_impl.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2007,2008 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GR_TOP_BLOCK_IMPL_H -#define INCLUDED_GR_TOP_BLOCK_IMPL_H - -#include <gr_runtime_api.h> -#include <gr_scheduler.h> -#include <thread/thread.h> - -/*! - *\brief Abstract implementation details of gr_top_block - * \ingroup internal - * - * The actual implementation of gr_top_block. Separate class allows - * decoupling of changes from dependent classes. - * - */ -class GR_RUNTIME_API gr_top_block_impl -{ -public: - gr_top_block_impl(gr_top_block *owner); - ~gr_top_block_impl(); - - // Create and start scheduler threads - void start(int max_noutput_items=100000000); - - // Signal scheduler threads to stop - void stop(); - - // Wait for scheduler threads to exit - void wait(); - - // Lock the top block to allow reconfiguration - void lock(); - - // Unlock the top block at end of reconfiguration - void unlock(); - - // Return a string list of edges - std::string edge_list(); - - // Dump the flowgraph to stdout - void dump(); - - // Get the number of max noutput_items in the flowgraph - int max_noutput_items(); - - // Set the maximum number of noutput_items in the flowgraph - void set_max_noutput_items(int nmax); - -protected: - - enum tb_state { IDLE, RUNNING }; - - gr_top_block *d_owner; - gr_flat_flowgraph_sptr d_ffg; - gr_scheduler_sptr d_scheduler; - - gr::thread::mutex d_mutex; // protects d_state and d_lock_count - tb_state d_state; - int d_lock_count; - int d_max_noutput_items; - -private: - void restart(); -}; - -#endif /* INCLUDED_GR_TOP_BLOCK_IMPL_H */ diff --git a/gnuradio-runtime/lib/gr_tpb_detail.cc b/gnuradio-runtime/lib/gr_tpb_detail.cc deleted file mode 100644 index 46eb6bbe0d..0000000000 --- a/gnuradio-runtime/lib/gr_tpb_detail.cc +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2009 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 3, 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 <config.h> -#endif -#include <gr_tpb_detail.h> -#include <gr_block.h> -#include <gr_block_detail.h> -#include <gr_buffer.h> - -using namespace pmt; - -/* - * We assume that no worker threads are ever running when the - * graph structure is being manipulated, thus it's safe for us to poke - * around in our neighbors w/o holding any locks. - */ - -void -gr_tpb_detail::notify_upstream(gr_block_detail *d) -{ - // For each of our inputs, tell the guy upstream that we've consumed - // some input, and that he most likely has more output buffer space - // available. - - for (size_t i = 0; i < d->d_input.size(); i++){ - // Can you say, "pointer chasing?" - d->d_input[i]->buffer()->link()->detail()->d_tpb.set_output_changed(); - } -} - -void -gr_tpb_detail::notify_downstream(gr_block_detail *d) -{ - // For each of our outputs, tell the guys downstream that they have - // new input available. - - for (size_t i = 0; i < d->d_output.size(); i++){ - gr_buffer_sptr buf = d->d_output[i]; - for (size_t j = 0, k = buf->nreaders(); j < k; j++) - buf->reader(j)->link()->detail()->d_tpb.set_input_changed(); - } -} - -void -gr_tpb_detail::notify_neighbors(gr_block_detail *d) -{ - notify_downstream(d); - notify_upstream(d); -} - diff --git a/gnuradio-runtime/lib/gr_tpb_thread_body.cc b/gnuradio-runtime/lib/gr_tpb_thread_body.cc deleted file mode 100644 index 11934dbf09..0000000000 --- a/gnuradio-runtime/lib/gr_tpb_thread_body.cc +++ /dev/null @@ -1,151 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2008,2009,2011 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 3, 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 <config.h> -#endif -#include <gr_tpb_thread_body.h> -#include <gr_prefs.h> -#include <iostream> -#include <boost/thread.hpp> -#include <pmt/pmt.h> -#include <boost/foreach.hpp> - -using namespace pmt; - -gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_items) - : d_exec(block, max_noutput_items) -{ - //std::cerr << "gr_tpb_thread_body: " << block << std::endl; - - gr_block_detail *d = block->detail().get(); - gr_block_executor::state s; - pmt_t msg; - - d->threaded = true; - d->thread = gr::thread::get_current_thread_id(); - - gr_prefs *p = gr_prefs::singleton(); - size_t max_nmsgs = static_cast<size_t>(p->get_long("DEFAULT", "max_messages", 100)); - - // Set thread affinity if it was set before fg was started. - if(block->processor_affinity().size() > 0) { - gr::thread::thread_bind_to_processor(d->thread, block->processor_affinity()); - } - - while (1){ - boost::this_thread::interruption_point(); - - // handle any queued up messages - //BOOST_FOREACH( pmt::pmt_t port, block->msg_queue.keys() ) - - BOOST_FOREACH( gr_basic_block::msg_queue_map_t::value_type &i, block->msg_queue ) - { - // Check if we have a message handler attached before getting - // any messages. This is mostly a protection for the unknown - // startup sequence of the threads. - if(block->has_msg_handler(i.first)) { - while ((msg = block->delete_head_nowait(i.first))){ - block->dispatch_msg(i.first,msg); - } - } - else { - // If we don't have a handler but are building up messages, - // prune the queue from the front to keep memory in check. - if(block->nmsgs(i.first) > max_nmsgs) - msg = block->delete_head_nowait(i.first); - } - } - - d->d_tpb.clear_changed(); - // run one iteration if we are a connected stream block - if(d->noutputs() >0 || d->ninputs()>0){ - s = d_exec.run_one_iteration(); - } else { - s = gr_block_executor::BLKD_IN; - } - - switch(s){ - case gr_block_executor::READY: // Tell neighbors we made progress. - d->d_tpb.notify_neighbors(d); - break; - - case gr_block_executor::READY_NO_OUTPUT: // Notify upstream only - d->d_tpb.notify_upstream(d); - break; - - case gr_block_executor::DONE: // Game over. - d->d_tpb.notify_neighbors(d); - return; - - case gr_block_executor::BLKD_IN: // Wait for input. - { - gr::thread::scoped_lock guard(d->d_tpb.mutex); - while (!d->d_tpb.input_changed){ - - // wait for input or message - while(!d->d_tpb.input_changed && block->empty_p()) - d->d_tpb.input_cond.wait(guard); - - // handle all pending messages - BOOST_FOREACH( gr_basic_block::msg_queue_map_t::value_type &i, block->msg_queue ) - { - while ((msg = block->delete_head_nowait(i.first))){ - guard.unlock(); // release lock while processing msg - block->dispatch_msg(i.first, msg); - guard.lock(); - } - } - } - } - break; - - - case gr_block_executor::BLKD_OUT: // Wait for output buffer space. - { - gr::thread::scoped_lock guard(d->d_tpb.mutex); - while (!d->d_tpb.output_changed){ - - // wait for output room or message - while(!d->d_tpb.output_changed && block->empty_p()) - d->d_tpb.output_cond.wait(guard); - - // handle all pending messages - BOOST_FOREACH( gr_basic_block::msg_queue_map_t::value_type &i, block->msg_queue ) - { - while ((msg = block->delete_head_nowait(i.first))){ - guard.unlock(); // release lock while processing msg - block->dispatch_msg(i.first,msg); - guard.lock(); - } - } - } - } - break; - - default: - assert(0); - } - } -} - -gr_tpb_thread_body::~gr_tpb_thread_body() -{ -} diff --git a/gnuradio-runtime/lib/gr_vco.h b/gnuradio-runtime/lib/gr_vco.h deleted file mode 100644 index 3ceaf15dd4..0000000000 --- a/gnuradio-runtime/lib/gr_vco.h +++ /dev/null @@ -1,94 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ -#ifndef _GR_VCO_H_ -#define _GR_VCO_H_ - - -#include <vector> -#include <gr_sincos.h> -#include <cmath> -#include <gr_complex.h> - -/*! - * \brief base class template for Voltage Controlled Oscillator (VCO) - * \ingroup misc - */ - -//FIXME Eventually generalize this to fixed point - -template<class o_type, class i_type> -class gr_vco { -public: - gr_vco () : d_phase (0) {} - - virtual ~gr_vco () {} - - // radians - void set_phase (double angle) { - d_phase = angle; - } - - void adjust_phase (double delta_phase) { - d_phase += delta_phase; - if (fabs (d_phase) > M_PI){ - - while (d_phase > M_PI) - d_phase -= 2*M_PI; - - while (d_phase < -M_PI) - d_phase += 2*M_PI; - } - } - - double get_phase () const { return d_phase; } - - // compute sin and cos for current phase angle - void sincos (float *sinx, float *cosx) const; - - // compute cos or sin for current phase angle - float cos () const { return std::cos (d_phase); } - float sin () const { return std::sin (d_phase); } - - // compute a block at a time - void cos (float *output, const float *input, int noutput_items, double k, double ampl = 1.0); - -protected: - double d_phase; -}; - -template<class o_type, class i_type> -void -gr_vco<o_type,i_type>::sincos (float *sinx, float *cosx) const -{ - gr_sincosf (d_phase, sinx, cosx); -} - -template<class o_type, class i_type> -void -gr_vco<o_type,i_type>::cos (float *output, const float *input, int noutput_items, double k, double ampl) -{ - for (int i = 0; i < noutput_items; i++){ - output[i] = cos() * ampl; - adjust_phase(input[i] * k); - } -} -#endif /* _GR_VCO_H_ */ diff --git a/gnuradio-runtime/lib/gr_vmcircbuf.cc b/gnuradio-runtime/lib/gr_vmcircbuf.cc deleted file mode 100644 index 522d9515d0..0000000000 --- a/gnuradio-runtime/lib/gr_vmcircbuf.cc +++ /dev/null @@ -1,295 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include <gr_vmcircbuf.h> -#include <assert.h> -#include <stdexcept> -#include <gr_preferences.h> -#include <stdio.h> -#include <string.h> -#include <gr_local_sighandler.h> -#include <vector> -#include <boost/format.hpp> - -// all the factories we know about -#include <gr_vmcircbuf_createfilemapping.h> -#include <gr_vmcircbuf_sysv_shm.h> -#include <gr_vmcircbuf_mmap_shm_open.h> -#include <gr_vmcircbuf_mmap_tmpfile.h> - -static const char *FACTORY_PREF_KEY = "gr_vmcircbuf_default_factory"; - -gr_vmcircbuf::~gr_vmcircbuf () -{ -} - -gr_vmcircbuf_factory::~gr_vmcircbuf_factory () -{ -} - -// ---------------------------------------------------------------- - -static gr_vmcircbuf_factory *s_default_factory = 0; - -gr_vmcircbuf_factory * -gr_vmcircbuf_sysconfig::get_default_factory () -{ - if (s_default_factory) - return s_default_factory; - - bool verbose = false; - - std::vector<gr_vmcircbuf_factory *> all = all_factories (); - - const char *name = gr_preferences::get (FACTORY_PREF_KEY); - - if (name){ - for (unsigned int i = 0; i < all.size (); i++){ - if (strcmp (name, all[i]->name ()) == 0){ - s_default_factory = all[i]; - if (verbose) - fprintf (stderr, "gr_vmcircbuf_sysconfig: using %s\n", - s_default_factory->name ()); - return s_default_factory; - } - } - } - - // either we don't have a default, or the default named is not in our - // list of factories. Find the first factory that works. - - if (verbose) - fprintf (stderr, "gr_vmcircbuf_sysconfig: finding a working factory...\n"); - - for (unsigned int i = 0; i < all.size (); i++){ - if (test_factory (all[i], verbose)){ - set_default_factory (all[i]); - return s_default_factory; - } - } - - // We're screwed! - - fprintf (stderr, "gr_vmcircbuf_sysconfig: unable to find a working factory!\n"); - throw std::runtime_error ("gr_vmcircbuf_sysconfig"); -} - -std::vector<gr_vmcircbuf_factory *> -gr_vmcircbuf_sysconfig::all_factories () -{ - std::vector<gr_vmcircbuf_factory *> result; - - result.push_back (gr_vmcircbuf_createfilemapping_factory::singleton ()); -#ifdef TRY_SHM_VMCIRCBUF - result.push_back (gr_vmcircbuf_sysv_shm_factory::singleton ()); - result.push_back (gr_vmcircbuf_mmap_shm_open_factory::singleton ()); -#endif - result.push_back (gr_vmcircbuf_mmap_tmpfile_factory::singleton ()); - - return result; -} - -void -gr_vmcircbuf_sysconfig::set_default_factory (gr_vmcircbuf_factory *f) -{ - gr_preferences::set (FACTORY_PREF_KEY, f->name ()); - s_default_factory = f; -} - - -// ------------------------------------------------------------------------ -// test code for vmcircbuf factories -// ------------------------------------------------------------------------ - -static void -init_buffer (gr_vmcircbuf *c, int counter, int size) -{ - unsigned int *p = (unsigned int *) c->pointer_to_first_copy (); - for (unsigned int i = 0; i < size / sizeof (int); i++) - p[i] = counter + i; -} - -static bool -check_mapping (gr_vmcircbuf *c, int counter, int size, const char *msg, bool verbose) -{ - bool ok = true; - - if (verbose) - fprintf (stderr, "... %s", msg); - - unsigned int *p1 = (unsigned int *) c->pointer_to_first_copy (); - unsigned int *p2 = (unsigned int *) c->pointer_to_second_copy (); - - // fprintf (stderr, "p1 = %p, p2 = %p\n", p1, p2); - - for (unsigned int i = 0; i < size / sizeof (int); i++){ - if (p1[i] != counter + i){ - ok = false; - if (verbose) - fprintf (stderr, " p1[%d] == %u, expected %u\n", i, p1[i], counter + i); - break; - } - if (p2[i] != counter + i){ - if (verbose) - fprintf (stderr, " p2[%d] == %u, expected %u\n", i, p2[i], counter + i); - ok = false; - break; - } - } - - if (ok && verbose){ - fprintf (stderr, " OK\n"); - } - return ok; -} - -static const char * -memsize (int size) -{ - static std::string buf; - if (size >= (1 << 20)){ - buf = str(boost::format("%dMB") % (size / (1 << 20))); - } - else if (size >= (1 << 10)){ - buf = str(boost::format("%dKB") % (size / (1 << 10))); - } - else { - buf = str(boost::format("%d") % size); - } - return buf.c_str(); -} - -static bool -test_a_bunch (gr_vmcircbuf_factory *factory, int n, int size, int *start_ptr, bool verbose) -{ - bool ok = true; - std::vector<int> counter(n); - std::vector<gr_vmcircbuf *> c(n); - int cum_size = 0; - - for (int i = 0; i < n; i++){ - counter[i] = *start_ptr; - *start_ptr += size; - if ((c[i] = factory->make (size)) == 0){ - if (verbose) - fprintf (stderr, - "Failed to allocate gr_vmcircbuf number %d of size %d (cum = %s)\n", - i + 1, size, memsize (cum_size)); - return false; - } - init_buffer (c[i], counter[i], size); - cum_size += size; - } - - for (int i = 0; i < n; i++){ - std::string msg = str(boost::format("test_a_bunch_%dx%s[%d]") % n % memsize (size) % i); - ok &= check_mapping (c[i], counter[i], size, msg.c_str(), verbose); - } - - for (int i = 0; i < n; i++){ - delete c[i]; - c[i] = 0; - } - - return ok; -} - -static bool -standard_tests (gr_vmcircbuf_factory *f, int verbose) -{ - if (verbose >= 1) - fprintf (stderr, "Testing %s...\n", f->name ()); - - bool v = verbose >= 2; - int granularity = f->granularity (); - int start = 0; - bool ok = true; - - ok &= test_a_bunch (f, 1, 1 * granularity, &start, v); // 1 x 4KB = 4KB - - if (ok){ - ok &= test_a_bunch (f, 64, 4 * granularity, &start, v); // 64 x 16KB = 1MB - ok &= test_a_bunch (f, 4, 4 * (1L << 20), &start, v); // 4 x 4MB = 16MB -// ok &= test_a_bunch (f, 256, 256 * (1L << 10), &start, v); // 256 x 256KB = 64MB - } - - if (verbose >= 1) - fprintf (stderr, "....... %s: %s", f->name (), ok ? "OK\n" : "Doesn't work\n"); - - return ok; -} - -bool -gr_vmcircbuf_sysconfig::test_factory (gr_vmcircbuf_factory *f, int verbose) -{ - // Install local signal handlers for SIGSEGV and SIGBUS. - // If something goes wrong, these signals may be invoked. - -#ifdef SIGSEGV - gr_local_sighandler sigsegv (SIGSEGV, gr_local_sighandler::throw_signal); -#endif -#ifdef SIGBUS - gr_local_sighandler sigbus (SIGBUS, gr_local_sighandler::throw_signal); -#endif -#ifdef SIGSYS - gr_local_sighandler sigsys (SIGSYS, gr_local_sighandler::throw_signal); -#endif - - try { - return standard_tests (f, verbose); - } - catch (gr_signal &sig){ - if (verbose){ - fprintf (stderr, "....... %s: %s", f->name (), "Doesn't work\n"); - fprintf (stderr, - "gr_vmcircbuf_factory::test_factory (%s): caught %s\n", - f->name (), sig.name().c_str()); - return false; - } - } - catch (...){ - if (verbose){ - fprintf (stderr, "....... %s: %s", f->name (), "Doesn't work\n"); - fprintf (stderr, - "gr_vmcircbuf_factory::test_factory (%s): some kind of uncaught exception\n", - f->name ()); - } - return false; - } - return false; // never gets here. shut compiler up. -} - -bool -gr_vmcircbuf_sysconfig::test_all_factories (int verbose) -{ - bool ok = false; - - std::vector<gr_vmcircbuf_factory *> all = all_factories (); - - for (unsigned int i = 0; i < all.size (); i++) - ok |= test_factory (all[i], verbose); - - return ok; -} diff --git a/gnuradio-runtime/lib/gr_vmcircbuf.h b/gnuradio-runtime/lib/gr_vmcircbuf.h deleted file mode 100644 index e7f492a8bd..0000000000 --- a/gnuradio-runtime/lib/gr_vmcircbuf.h +++ /dev/null @@ -1,122 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef _GR_VMCIRCBUF_H_ -#define _GR_VMCIRCBUF_H_ - -#include <gr_runtime_api.h> -#include <vector> - -/*! - * \brief abstract class to implement doubly mapped virtual memory circular buffers - * \ingroup internal - */ -class GR_RUNTIME_API gr_vmcircbuf { - protected: - int d_size; - char *d_base; - - // CREATORS - gr_vmcircbuf (int size) : d_size (size), d_base (0) {}; - - public: - virtual ~gr_vmcircbuf (); - - // ACCESSORS - void *pointer_to_first_copy () const { return d_base; } - void *pointer_to_second_copy () const { return d_base + d_size; } -}; - -/*! - * \brief abstract factory for creating circular buffers - */ -class GR_RUNTIME_API gr_vmcircbuf_factory { - protected: - gr_vmcircbuf_factory () {}; - virtual ~gr_vmcircbuf_factory (); - - public: - - /*! - * \brief return name of this factory - */ - virtual const char *name () const = 0; - - /*! - * \brief return granularity of mapping, typically equal to page size - */ - virtual int granularity () = 0; - - /*! - * \brief return a gr_vmcircbuf, or 0 if unable. - * - * Call this to create a doubly mapped circular buffer. - */ - virtual gr_vmcircbuf *make (int size) = 0; -}; - -/* - * \brief pulls together all implementations of gr_vmcircbuf - */ -class GR_RUNTIME_API gr_vmcircbuf_sysconfig { - public: - - /* - * \brief return the single instance of the default factory. - * - * returns the default factory to use if it's already defined, - * else find the first working factory and use it. - */ - static gr_vmcircbuf_factory *get_default_factory (); - - - static int granularity () { return get_default_factory()->granularity(); } - static gr_vmcircbuf *make (int size) { return get_default_factory()->make(size); } - - - // N.B. not all factories are guaranteed to work. - // It's too hard to check everything at config time, so we check at runtime - static std::vector<gr_vmcircbuf_factory *> all_factories (); - - // make this factory the default - static void set_default_factory (gr_vmcircbuf_factory *f); - - /*! - * \brief Does this factory really work? - * - * verbose = 0: silent - * verbose = 1: names of factories tested and results - * verbose = 2: all intermediate results - */ - static bool test_factory (gr_vmcircbuf_factory *f, int verbose); - - /*! - * \brief Test all factories, return true if at least one of them works - * verbose = 0: silent - * verbose = 1: names of factories tested and results - * verbose = 2: all intermediate results - */ - static bool test_all_factories (int verbose); -}; - - -#endif /* _GR_VMCIRCBUF_H_ */ diff --git a/gnuradio-runtime/lib/gr_vmcircbuf_createfilemapping.cc b/gnuradio-runtime/lib/gr_vmcircbuf_createfilemapping.cc deleted file mode 100644 index 1b4d9700a5..0000000000 --- a/gnuradio-runtime/lib/gr_vmcircbuf_createfilemapping.cc +++ /dev/null @@ -1,204 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003,2005,2011 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include <stdexcept> -#include <assert.h> -#include <unistd.h> -#include <fcntl.h> -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif -#include <errno.h> -#include <stdio.h> -#include <gr_pagesize.h> -#include <gr_vmcircbuf_createfilemapping.h> -#include <boost/format.hpp> - -#ifdef HAVE_CREATEFILEMAPPING -// Print Windows error (could/should be global?) -static void -werror( char *where, DWORD last_error ) -{ - char buf[1024]; - - FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - last_error, - 0, // default language - buf, - sizeof(buf)/sizeof(TCHAR), // buffer size - NULL ); - fprintf( stderr, "%s: Error %d: %s", where, last_error, buf ); - return; -} -#endif - - -gr_vmcircbuf_createfilemapping::gr_vmcircbuf_createfilemapping (int size) - : gr_vmcircbuf (size) -{ -#if !defined(HAVE_CREATEFILEMAPPING) - fprintf (stderr, "%s: createfilemapping is not available\n",__FUNCTION__); - throw std::runtime_error ("gr_vmcircbuf_createfilemapping"); -#else - static int s_seg_counter = 0; - - if (size <= 0 || (size % gr_pagesize ()) != 0){ - fprintf (stderr, "gr_vmcircbuf_createfilemapping: invalid size = %d\n", size); - throw std::runtime_error ("gr_vmcircbuf_createfilemapping"); - } - - std::string seg_name = str(boost::format("/gnuradio-%d-%d") % getpid () % s_seg_counter); - - d_handle = CreateFileMapping(INVALID_HANDLE_VALUE, // use paging file - NULL, // default security - PAGE_READWRITE, // read/write access - 0, // max. object size - size, // buffer size - seg_name.c_str()); // name of mapping object - - s_seg_counter++; - if (d_handle == NULL || d_handle == INVALID_HANDLE_VALUE){ - std::string msg = str(boost::format( - "gr_vmcircbuf_mmap_createfilemapping: CreateFileMapping [%s]") % - seg_name ); - werror((char *) msg.c_str(), GetLastError() ); - throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping"); - } - - // Allocate virtual memory of the needed size, then free it so we can use it - LPVOID first_tmp; - first_tmp = VirtualAlloc( NULL, 2*size, MEM_RESERVE, PAGE_NOACCESS ); - if (first_tmp == NULL){ - werror( "gr_vmcircbuf_mmap_createfilemapping: VirtualAlloc", GetLastError()); - CloseHandle(d_handle); // cleanup - throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping"); - } - - if (VirtualFree(first_tmp, 0, MEM_RELEASE) == 0){ - werror( "gr_vmcircbuf_mmap_createfilemapping: VirtualFree", GetLastError()); - CloseHandle(d_handle); // cleanup - throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping"); - } - - d_first_copy = MapViewOfFileEx((HANDLE)d_handle, // handle to map object - FILE_MAP_WRITE, // read/write permission - 0, - 0, - size, - first_tmp); - if (d_first_copy != first_tmp){ - werror( "gr_vmcircbuf_mmap_createfilemapping: MapViewOfFileEx(1)", GetLastError()); - CloseHandle(d_handle); // cleanup - throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping"); - } - - d_second_copy = MapViewOfFileEx((HANDLE)d_handle, // handle to map object - FILE_MAP_WRITE, // read/write permission - 0, - 0, - size, - (char *)first_tmp + size);//(LPVOID) ((char *)d_first_copy + size)); - - if (d_second_copy != (char *)first_tmp + size){ - werror( "gr_vmcircbuf_mmap_createfilemapping: MapViewOfFileEx(2)", GetLastError()); - UnmapViewOfFile(d_first_copy); - CloseHandle(d_handle); // cleanup - throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping"); - } - -#ifdef DEBUG - fprintf (stderr,"gr_vmcircbuf_mmap_createfilemapping: contiguous? mmap %p %p %p %p\n", - (char *)d_first_copy, (char *)d_second_copy, size, (char *)d_first_copy + size); -#endif - - // Now remember the important stuff - d_base = (char *) d_first_copy; - d_size = size; -#endif /*HAVE_CREATEFILEMAPPING*/ -} - -gr_vmcircbuf_createfilemapping::~gr_vmcircbuf_createfilemapping () -{ -#ifdef HAVE_CREATEFILEMAPPING - if (UnmapViewOfFile(d_first_copy) == 0) - { - werror("gr_vmcircbuf_createfilemapping: UnmapViewOfFile(d_first_copy)", GetLastError()); - } - d_base=NULL; - if (UnmapViewOfFile(d_second_copy) == 0) - { - werror("gr_vmcircbuf_createfilemapping: UnmapViewOfFile(d_second_copy)", GetLastError()); - } - //d_second=NULL; - CloseHandle(d_handle); -#endif -} - -// ---------------------------------------------------------------- -// The factory interface -// ---------------------------------------------------------------- - - -gr_vmcircbuf_factory *gr_vmcircbuf_createfilemapping_factory::s_the_factory = 0; - -gr_vmcircbuf_factory * -gr_vmcircbuf_createfilemapping_factory::singleton () -{ - if (s_the_factory) - return s_the_factory; - s_the_factory = new gr_vmcircbuf_createfilemapping_factory (); - return s_the_factory; -} - -int -gr_vmcircbuf_createfilemapping_factory::granularity () -{ -#ifdef HAVE_CREATEFILEMAPPING - // return 65536;//TODO, check, is this needed or can we just use gr_pagesize() - SYSTEM_INFO system_info; - GetSystemInfo(&system_info); - //fprintf(stderr,"win32 AllocationGranularity %p\n",(int)system_info.dwAllocationGranularity); - return (int)system_info.dwAllocationGranularity; -#else - return gr_pagesize (); -#endif -} - -gr_vmcircbuf * -gr_vmcircbuf_createfilemapping_factory::make (int size) -{ - try - { - return new gr_vmcircbuf_createfilemapping (size); - } - catch (...) - { - return 0; - } -} diff --git a/gnuradio-runtime/lib/gr_vmcircbuf_createfilemapping.h b/gnuradio-runtime/lib/gr_vmcircbuf_createfilemapping.h deleted file mode 100644 index a4bb5cbe92..0000000000 --- a/gnuradio-runtime/lib/gr_vmcircbuf_createfilemapping.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003,2005 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef _GR_VMCIRCBUF_CREATEFILEMAPPING_H_ -#define _GR_VMCIRCBUF_CREATEFILEMAPPING_H_ - -#include <gr_runtime_api.h> -#include <gr_vmcircbuf.h> - -#ifdef HAVE_CREATEFILEMAPPING -#include <windows.h> -#endif -/*! - * \brief concrete class to implement circular buffers with mmap and shm_open - * \ingroup internal - */ -class GR_RUNTIME_API gr_vmcircbuf_createfilemapping : public gr_vmcircbuf -{ - public: - // CREATORS - gr_vmcircbuf_createfilemapping (int size); - virtual ~gr_vmcircbuf_createfilemapping (); -#ifdef HAVE_CREATEFILEMAPPING - private: - HANDLE d_handle; - LPVOID d_first_copy; - LPVOID d_second_copy; -#endif -}; - -/*! - * \brief concrete factory for circular buffers built using mmap and shm_open - */ -class GR_RUNTIME_API gr_vmcircbuf_createfilemapping_factory : public gr_vmcircbuf_factory -{ - private: - static gr_vmcircbuf_factory *s_the_factory; - - public: - static gr_vmcircbuf_factory *singleton (); - - virtual const char *name () const { return "gr_vmcircbuf_createfilemapping_factory"; } - - /*! - * \brief return granularity of mapping, typically equal to page size - */ - virtual int granularity (); - - /*! - * \brief return a gr_vmcircbuf, or 0 if unable. - * - * Call this to create a doubly mapped circular buffer. - */ - virtual gr_vmcircbuf *make (int size); -}; - -#endif /* _GR_VMCIRCBUF_CREATEFILEMAPPING_H_ */ diff --git a/gnuradio-runtime/lib/gr_vmcircbuf_mmap_shm_open.cc b/gnuradio-runtime/lib/gr_vmcircbuf_mmap_shm_open.cc deleted file mode 100644 index 3d170081d0..0000000000 --- a/gnuradio-runtime/lib/gr_vmcircbuf_mmap_shm_open.cc +++ /dev/null @@ -1,205 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003,2011 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include <gr_vmcircbuf_mmap_shm_open.h> -#include <stdexcept> -#include <assert.h> -#include <unistd.h> -#include <fcntl.h> -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif -#include <errno.h> -#include <stdio.h> -#include <gr_pagesize.h> -#include <gr_sys_paths.h> - - -gr_vmcircbuf_mmap_shm_open::gr_vmcircbuf_mmap_shm_open (int size) - : gr_vmcircbuf (size) -{ -#if !defined(HAVE_MMAP) || !defined(HAVE_SHM_OPEN) - fprintf (stderr, "gr_vmcircbuf_mmap_shm_open: mmap or shm_open is not available\n"); - throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); -#else - static int s_seg_counter = 0; - - if (size <= 0 || (size % gr_pagesize ()) != 0){ - fprintf (stderr, "gr_vmcircbuf_mmap_shm_open: invalid size = %d\n", size); - throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); - } - - int shm_fd = -1; - char seg_name[1024]; - static bool portable_format = true; - - // open a new named shared memory segment - - while (1){ - if (portable_format){ - - // This is the POSIX recommended "portable format". - // Of course the "portable format" doesn't work on some systems... - - snprintf (seg_name, sizeof (seg_name), - "/gnuradio-%d-%d", getpid (), s_seg_counter); - } - else { - - // Where the "portable format" doesn't work, we try building - // a full filesystem pathname pointing into a suitable temporary directory. - - snprintf (seg_name, sizeof (seg_name), - "%s/gnuradio-%d-%d", gr_tmp_path (), getpid (), s_seg_counter); - } - - shm_fd = shm_open (seg_name, O_RDWR | O_CREAT | O_EXCL, 0600); - if (shm_fd == -1 && errno == EACCES && portable_format){ - portable_format = false; - continue; // try again using "non-portable format" - } - - s_seg_counter++; - - if (shm_fd == -1){ - if (errno == EEXIST) // Named segment already exists (shouldn't happen). Try again - continue; - - char msg[1024]; - snprintf (msg, sizeof (msg), "gr_vmcircbuf_mmap_shm_open: shm_open [%s]", seg_name); - perror (msg); - throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); - } - break; - } - - // We've got a new shared memory segment fd open. - // Now set it's length to 2x what we really want and mmap it in. - - if (ftruncate (shm_fd, (off_t) 2 * size) == -1){ - close (shm_fd); // cleanup - perror ("gr_vmcircbuf_mmap_shm_open: ftruncate (1)"); - throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); - } - - void *first_copy = mmap (0, 2 * size, - PROT_READ | PROT_WRITE, MAP_SHARED, - shm_fd, (off_t) 0); - - if (first_copy == MAP_FAILED){ - close (shm_fd); // cleanup - perror ("gr_vmcircbuf_mmap_shm_open: mmap (1)"); - throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); - } - - // unmap the 2nd half - if (munmap ((char *) first_copy + size, size) == -1){ - close (shm_fd); // cleanup - perror ("gr_vmcircbuf_mmap_shm_open: munmap (1)"); - throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); - } - - // map the first half into the now available hole where the - // second half used to be. - - void *second_copy = mmap ((char *) first_copy + size, size, - PROT_READ | PROT_WRITE, MAP_SHARED, - shm_fd, (off_t) 0); - - if (second_copy == MAP_FAILED){ - close (shm_fd); // cleanup - perror ("gr_vmcircbuf_mmap_shm_open: mmap (2)"); - throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); - } - -#if 0 // OS/X doesn't allow you to resize the segment - - // cut the shared memory segment down to size - if (ftruncate (shm_fd, (off_t) size) == -1){ - close (shm_fd); // cleanup - perror ("gr_vmcircbuf_mmap_shm_open: ftruncate (2)"); - throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); - } -#endif - - close (shm_fd); // fd no longer needed. The mapping is retained. - - if (shm_unlink (seg_name) == -1){ // unlink the seg_name. - perror ("gr_vmcircbuf_mmap_shm_open: shm_unlink"); - throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); - } - - // Now remember the important stuff - - d_base = (char *) first_copy; - d_size = size; -#endif -} - -gr_vmcircbuf_mmap_shm_open::~gr_vmcircbuf_mmap_shm_open () -{ -#if defined(HAVE_MMAP) - if (munmap (d_base, 2 * d_size) == -1){ - perror ("gr_vmcircbuf_mmap_shm_open: munmap (2)"); - } -#endif -} - -// ---------------------------------------------------------------- -// The factory interface -// ---------------------------------------------------------------- - - -gr_vmcircbuf_factory *gr_vmcircbuf_mmap_shm_open_factory::s_the_factory = 0; - -gr_vmcircbuf_factory * -gr_vmcircbuf_mmap_shm_open_factory::singleton () -{ - if (s_the_factory) - return s_the_factory; - - s_the_factory = new gr_vmcircbuf_mmap_shm_open_factory (); - return s_the_factory; -} - -int -gr_vmcircbuf_mmap_shm_open_factory::granularity () -{ - return gr_pagesize (); -} - -gr_vmcircbuf * -gr_vmcircbuf_mmap_shm_open_factory::make (int size) -{ - try { - return new gr_vmcircbuf_mmap_shm_open (size); - } - catch (...){ - return 0; - } -} diff --git a/gnuradio-runtime/lib/gr_vmcircbuf_mmap_shm_open.h b/gnuradio-runtime/lib/gr_vmcircbuf_mmap_shm_open.h deleted file mode 100644 index d35df80839..0000000000 --- a/gnuradio-runtime/lib/gr_vmcircbuf_mmap_shm_open.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef _GR_VMCIRCBUF_MMAP_SHM_OPEN_H_ -#define _GR_VMCIRCBUF_MMAP_SHM_OPEN_H_ - -#include <gr_runtime_api.h> -#include <gr_vmcircbuf.h> - -/*! - * \brief concrete class to implement circular buffers with mmap and shm_open - * \ingroup internal - */ -class GR_RUNTIME_API gr_vmcircbuf_mmap_shm_open : public gr_vmcircbuf { - public: - - // CREATORS - - gr_vmcircbuf_mmap_shm_open (int size); - virtual ~gr_vmcircbuf_mmap_shm_open (); -}; - -/*! - * \brief concrete factory for circular buffers built using mmap and shm_open - */ -class GR_RUNTIME_API gr_vmcircbuf_mmap_shm_open_factory : public gr_vmcircbuf_factory { - private: - static gr_vmcircbuf_factory *s_the_factory; - - public: - static gr_vmcircbuf_factory *singleton (); - - virtual const char *name () const { return "gr_vmcircbuf_mmap_shm_open_factory"; } - - /*! - * \brief return granularity of mapping, typically equal to page size - */ - virtual int granularity (); - - /*! - * \brief return a gr_vmcircbuf, or 0 if unable. - * - * Call this to create a doubly mapped circular buffer. - */ - virtual gr_vmcircbuf *make (int size); -}; - -#endif /* _GR_VMCIRCBUF_MMAP_SHM_OPEN_H_ */ diff --git a/gnuradio-runtime/lib/gr_vmcircbuf_mmap_tmpfile.cc b/gnuradio-runtime/lib/gr_vmcircbuf_mmap_tmpfile.cc deleted file mode 100644 index 35de64699e..0000000000 --- a/gnuradio-runtime/lib/gr_vmcircbuf_mmap_tmpfile.cc +++ /dev/null @@ -1,197 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003,2011 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include <gr_vmcircbuf_mmap_tmpfile.h> -#include <stdexcept> -#include <assert.h> -#include <unistd.h> -#include <stdlib.h> -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_MMAN_H -#include <sys/mman.h> -#endif -#include <fcntl.h> -#include <errno.h> -#include <stdio.h> -#include <string.h> -#include <gr_pagesize.h> -#include <gr_sys_paths.h> - -gr_vmcircbuf_mmap_tmpfile::gr_vmcircbuf_mmap_tmpfile (int size) - : gr_vmcircbuf (size) -{ -#if !defined(HAVE_MMAP) - fprintf (stderr, "gr_vmcircbuf_mmap_tmpfile: mmap or mkstemp is not available\n"); - throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); -#else - - if (size <= 0 || (size % gr_pagesize ()) != 0){ - fprintf (stderr, "gr_vmcircbuf_mmap_tmpfile: invalid size = %d\n", size); - throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); - } - - int seg_fd = -1; - char seg_name[1024]; - - static int s_seg_counter = 0; - - - // open a temporary file that we'll map in a bit later - - while (1){ - snprintf (seg_name, sizeof (seg_name), - "%s/gnuradio-%d-%d-XXXXXX", gr_tmp_path (), getpid (), s_seg_counter); - s_seg_counter++; - - seg_fd = open (seg_name, O_RDWR | O_CREAT | O_EXCL, 0600); - if (seg_fd == -1){ - if (errno == EEXIST) // File already exists (shouldn't happen). Try again - continue; - - char msg[1024]; - snprintf (msg, sizeof (msg), - "gr_vmcircbuf_mmap_tmpfile: open [%s]", seg_name); - perror (msg); - throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); - } - break; - } - - if (unlink (seg_name) == -1){ - perror ("gr_vmcircbuf_mmap_tmpfile: unlink"); - throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); - } - - // We've got a valid file descriptor to a tmp file. - // Now set it's length to 2x what we really want and mmap it in. - - if (ftruncate (seg_fd, (off_t) 2 * size) == -1){ - close (seg_fd); // cleanup - perror ("gr_vmcircbuf_mmap_tmpfile: ftruncate (1)"); - throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); - } - - void *first_copy = mmap (0, 2 * size, - PROT_READ | PROT_WRITE, MAP_SHARED, - seg_fd, (off_t) 0); - - if (first_copy == MAP_FAILED){ - close (seg_fd); // cleanup - perror ("gr_vmcircbuf_mmap_tmpfile: mmap (1)"); - throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); - } - - // unmap the 2nd half - if (munmap ((char *) first_copy + size, size) == -1){ - close (seg_fd); // cleanup - perror ("gr_vmcircbuf_mmap_tmpfile: munmap (1)"); - throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); - } - - // map the first half into the now available hole where the - // second half used to be. - - void *second_copy = mmap ((char *) first_copy + size, size, - PROT_READ | PROT_WRITE, MAP_SHARED, - seg_fd, (off_t) 0); - - if (second_copy == MAP_FAILED){ - munmap(first_copy, size); // cleanup - close (seg_fd); - perror ("gr_vmcircbuf_mmap_tmpfile: mmap (2)"); - throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); - } - - // check for contiguity - if ((char *) second_copy != (char *) first_copy + size){ - munmap(first_copy, size); // cleanup - munmap(second_copy, size); - close (seg_fd); - perror ("gr_vmcircbuf_mmap_tmpfile: non-contiguous second copy"); - throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); - } - - // cut the tmp file down to size - if (ftruncate (seg_fd, (off_t) size) == -1){ - munmap(first_copy, size); // cleanup - munmap(second_copy, size); - close (seg_fd); - perror ("gr_vmcircbuf_mmap_tmpfile: ftruncate (2)"); - throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); - } - - close (seg_fd); // fd no longer needed. The mapping is retained. - - // Now remember the important stuff - - d_base = (char *) first_copy; - d_size = size; -#endif -} - -gr_vmcircbuf_mmap_tmpfile::~gr_vmcircbuf_mmap_tmpfile () -{ -#if defined(HAVE_MMAP) - if (munmap (d_base, 2 * d_size) == -1){ - perror ("gr_vmcircbuf_mmap_tmpfile: munmap (2)"); - } -#endif -} - -// ---------------------------------------------------------------- -// The factory interface -// ---------------------------------------------------------------- - - -gr_vmcircbuf_factory *gr_vmcircbuf_mmap_tmpfile_factory::s_the_factory = 0; - -gr_vmcircbuf_factory * -gr_vmcircbuf_mmap_tmpfile_factory::singleton () -{ - if (s_the_factory) - return s_the_factory; - - s_the_factory = new gr_vmcircbuf_mmap_tmpfile_factory (); - return s_the_factory; -} - -int -gr_vmcircbuf_mmap_tmpfile_factory::granularity () -{ - return gr_pagesize (); -} - -gr_vmcircbuf * -gr_vmcircbuf_mmap_tmpfile_factory::make (int size) -{ - try { - return new gr_vmcircbuf_mmap_tmpfile (size); - } - catch (...){ - return 0; - } -} diff --git a/gnuradio-runtime/lib/gr_vmcircbuf_mmap_tmpfile.h b/gnuradio-runtime/lib/gr_vmcircbuf_mmap_tmpfile.h deleted file mode 100644 index cd865734f2..0000000000 --- a/gnuradio-runtime/lib/gr_vmcircbuf_mmap_tmpfile.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef _GR_VMCIRCBUF_MMAP_TMPFILE_H_ -#define _GR_VMCIRCBUF_MMAP_TMPFILE_H_ - -#include <gr_runtime_api.h> -#include <gr_vmcircbuf.h> - -/*! - * \brief concrete class to implement circular buffers with mmap and shm_open - * \ingroup internal - */ -class GR_RUNTIME_API gr_vmcircbuf_mmap_tmpfile : public gr_vmcircbuf { - public: - - // CREATORS - - gr_vmcircbuf_mmap_tmpfile (int size); - virtual ~gr_vmcircbuf_mmap_tmpfile (); -}; - -/*! - * \brief concrete factory for circular buffers built using mmap and shm_open - */ -class GR_RUNTIME_API gr_vmcircbuf_mmap_tmpfile_factory : public gr_vmcircbuf_factory { - private: - static gr_vmcircbuf_factory *s_the_factory; - - public: - static gr_vmcircbuf_factory *singleton (); - - virtual const char *name () const { return "gr_vmcircbuf_mmap_tmpfile_factory"; } - - /*! - * \brief return granularity of mapping, typically equal to page size - */ - virtual int granularity (); - - /*! - * \brief return a gr_vmcircbuf, or 0 if unable. - * - * Call this to create a doubly mapped circular buffer. - */ - virtual gr_vmcircbuf *make (int size); -}; - -#endif /* _GR_VMCIRCBUF_MMAP_TMPFILE_H_ */ diff --git a/gnuradio-runtime/lib/gr_vmcircbuf_sysv_shm.cc b/gnuradio-runtime/lib/gr_vmcircbuf_sysv_shm.cc deleted file mode 100644 index d9cf75e70f..0000000000 --- a/gnuradio-runtime/lib/gr_vmcircbuf_sysv_shm.cc +++ /dev/null @@ -1,194 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include <gr_vmcircbuf_sysv_shm.h> -#include <stdexcept> -#include <assert.h> -#include <unistd.h> -#include <stdlib.h> -#include <fcntl.h> -#ifdef HAVE_SYS_IPC_H -#include <sys/ipc.h> -#endif -#ifdef HAVE_SYS_SHM_H -#include <sys/shm.h> -#endif -#include <errno.h> -#include <stdio.h> -#include <gr_pagesize.h> - - -gr_vmcircbuf_sysv_shm::gr_vmcircbuf_sysv_shm (int size) - : gr_vmcircbuf (size) -{ -#if !defined(HAVE_SYS_SHM_H) - fprintf (stderr, "gr_vmcircbuf_sysv_shm: sysv shared memory is not available\n"); - throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); -#else - - int pagesize = gr_pagesize(); - - if (size <= 0 || (size % pagesize) != 0){ - fprintf (stderr, "gr_vmcircbuf_sysv_shm: invalid size = %d\n", size); - throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); - } - - int shmid_guard = -1; - int shmid1 = -1; - int shmid2 = -1; - - // We use this as a guard page. We'll map it read-only on both ends of the buffer. - // Ideally we'd map it no access, but I don't think that's possible with SysV - if ((shmid_guard = shmget (IPC_PRIVATE, pagesize, IPC_CREAT | 0400)) == -1){ - perror ("gr_vmcircbuf_sysv_shm: shmget (0)"); - throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); - } - - if ((shmid2 = shmget (IPC_PRIVATE, 2 * size + 2 * pagesize, IPC_CREAT | 0700)) == -1){ - perror ("gr_vmcircbuf_sysv_shm: shmget (1)"); - shmctl (shmid_guard, IPC_RMID, 0); - throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); - } - - if ((shmid1 = shmget (IPC_PRIVATE, size, IPC_CREAT | 0700)) == -1){ - perror ("gr_vmcircbuf_sysv_shm: shmget (2)"); - shmctl (shmid_guard, IPC_RMID, 0); - shmctl (shmid2, IPC_RMID, 0); - throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); - } - - void *first_copy = shmat (shmid2, 0, 0); - if (first_copy == (void *) -1){ - perror ("gr_vmcircbuf_sysv_shm: shmat (1)"); - shmctl (shmid_guard, IPC_RMID, 0); - shmctl (shmid2, IPC_RMID, 0); - shmctl (shmid1, IPC_RMID, 0); - throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); - } - - shmctl (shmid2, IPC_RMID, 0); - - // There may be a race between our detach and attach. - // - // If the system allocates all shared memory segments at the same - // virtual addresses in all processes and if the system allocates - // some other segment to first_copy or first_copoy + size between - // our detach and attach, the attaches below could fail [I've never - // seen it fail for this reason]. - - shmdt (first_copy); - - // first read-only guard page - if (shmat (shmid_guard, first_copy, SHM_RDONLY) == (void *) -1){ - perror ("gr_vmcircbuf_sysv_shm: shmat (2)"); - shmctl (shmid_guard, IPC_RMID, 0); - shmctl (shmid1, IPC_RMID, 0); - throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); - } - - // first copy - if (shmat (shmid1, (char *) first_copy + pagesize, 0) == (void *) -1){ - perror ("gr_vmcircbuf_sysv_shm: shmat (3)"); - shmctl (shmid_guard, IPC_RMID, 0); - shmctl (shmid1, IPC_RMID, 0); - shmdt (first_copy); - throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); - } - - // second copy - if (shmat (shmid1, (char *) first_copy + pagesize + size, 0) == (void *) -1){ - perror ("gr_vmcircbuf_sysv_shm: shmat (4)"); - shmctl (shmid_guard, IPC_RMID, 0); - shmctl (shmid1, IPC_RMID, 0); - shmdt ((char *)first_copy + pagesize); - throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); - } - - // second read-only guard page - if (shmat (shmid_guard, (char *) first_copy + pagesize + 2 * size, SHM_RDONLY) == (void *) -1){ - perror ("gr_vmcircbuf_sysv_shm: shmat (5)"); - shmctl (shmid_guard, IPC_RMID, 0); - shmctl (shmid1, IPC_RMID, 0); - shmdt (first_copy); - shmdt ((char *)first_copy + pagesize); - shmdt ((char *)first_copy + pagesize + size); - throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); - } - - shmctl (shmid1, IPC_RMID, 0); - shmctl (shmid_guard, IPC_RMID, 0); - - // Now remember the important stuff - - d_base = (char *) first_copy + pagesize; - d_size = size; -#endif -} - -gr_vmcircbuf_sysv_shm::~gr_vmcircbuf_sysv_shm () -{ -#if defined(HAVE_SYS_SHM_H) - if (shmdt (d_base - gr_pagesize()) == -1 - || shmdt (d_base) == -1 - || shmdt (d_base + d_size) == -1 - || shmdt (d_base + 2 * d_size) == -1){ - perror ("gr_vmcircbuf_sysv_shm: shmdt (2)"); - } -#endif -} - -// ---------------------------------------------------------------- -// The factory interface -// ---------------------------------------------------------------- - - -gr_vmcircbuf_factory *gr_vmcircbuf_sysv_shm_factory::s_the_factory = 0; - -gr_vmcircbuf_factory * -gr_vmcircbuf_sysv_shm_factory::singleton () -{ - if (s_the_factory) - return s_the_factory; - - s_the_factory = new gr_vmcircbuf_sysv_shm_factory (); - return s_the_factory; -} - -int -gr_vmcircbuf_sysv_shm_factory::granularity () -{ - return gr_pagesize (); -} - -gr_vmcircbuf * -gr_vmcircbuf_sysv_shm_factory::make (int size) -{ - try { - return new gr_vmcircbuf_sysv_shm (size); - } - catch (...){ - return 0; - } -} diff --git a/gnuradio-runtime/lib/gr_vmcircbuf_sysv_shm.h b/gnuradio-runtime/lib/gr_vmcircbuf_sysv_shm.h deleted file mode 100644 index abebd93f1c..0000000000 --- a/gnuradio-runtime/lib/gr_vmcircbuf_sysv_shm.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef _GR_VMCIRCBUF_SYSV_SHM_H_ -#define _GR_VMCIRCBUF_SYSV_SHM_H_ - -#include <gr_runtime_api.h> -#include <gr_vmcircbuf.h> - -/*! - * \brief concrete class to implement circular buffers with mmap and shm_open - * \ingroup internal - */ -class GR_RUNTIME_API gr_vmcircbuf_sysv_shm : public gr_vmcircbuf { - public: - - // CREATORS - - gr_vmcircbuf_sysv_shm (int size); - virtual ~gr_vmcircbuf_sysv_shm (); -}; - -/*! - * \brief concrete factory for circular buffers built using mmap and shm_open - */ -class GR_RUNTIME_API gr_vmcircbuf_sysv_shm_factory : public gr_vmcircbuf_factory { - private: - static gr_vmcircbuf_factory *s_the_factory; - - public: - static gr_vmcircbuf_factory *singleton (); - - virtual const char *name () const { return "gr_vmcircbuf_sysv_shm_factory"; } - - /*! - * \brief return granularity of mapping, typically equal to page size - */ - virtual int granularity (); - - /*! - * \brief return a gr_vmcircbuf, or 0 if unable. - * - * Call this to create a doubly mapped circular buffer. - */ - virtual gr_vmcircbuf *make (int size); -}; - -#endif /* _GR_VMCIRCBUF_SYSV_SHM_H_ */ diff --git a/gnuradio-runtime/lib/gri_debugger_hook.cc b/gnuradio-runtime/lib/gri_debugger_hook.cc deleted file mode 100644 index d9270c435f..0000000000 --- a/gnuradio-runtime/lib/gri_debugger_hook.cc +++ /dev/null @@ -1,29 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include <gri_debugger_hook.h> - -void -gri_debugger_hook () -{ - // nop. set a breakpoint here -} diff --git a/gnuradio-runtime/lib/gri_debugger_hook.h b/gnuradio-runtime/lib/gri_debugger_hook.h deleted file mode 100644 index 6d31ed1b2c..0000000000 --- a/gnuradio-runtime/lib/gri_debugger_hook.h +++ /dev/null @@ -1,30 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef INCLUDED_GRI_DEBUGGER_HOOK_H -#define INCLUDED_GRI_DEBUGGER_HOOK_H - -#include <gr_runtime_api.h> - -GR_RUNTIME_API void gri_debugger_hook (); - -#endif /* INCLUDED_GRI_DEBUGGER_HOOK_H */
\ No newline at end of file diff --git a/gnuradio-runtime/lib/hier_block2.cc b/gnuradio-runtime/lib/hier_block2.cc new file mode 100644 index 0000000000..f26da18e54 --- /dev/null +++ b/gnuradio-runtime/lib/hier_block2.cc @@ -0,0 +1,160 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006-2008,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/hier_block2.h> +#include <gnuradio/io_signature.h> +#include "hier_block2_detail.h" +#include <iostream> + +namespace gr { + +#define GR_HIER_BLOCK2_DEBUG 0 + + hier_block2_sptr + make_hier_block2(const std::string &name, + gr::io_signature::sptr input_signature, + gr::io_signature::sptr output_signature) + { + return gnuradio::get_initial_sptr + (new hier_block2(name, input_signature, output_signature)); + } + + hier_block2::hier_block2(const std::string &name, + gr::io_signature::sptr input_signature, + gr::io_signature::sptr output_signature) + : basic_block(name, input_signature, output_signature), + d_detail(new hier_block2_detail(this)), + hier_message_ports_in(pmt::PMT_NIL), + hier_message_ports_out(pmt::PMT_NIL) + { + // This bit of magic ensures that self() works in the constructors of derived classes. + gnuradio::detail::sptr_magic::create_and_stash_initial_sptr(this); + } + + hier_block2::~hier_block2() + { + delete d_detail; + } + + hier_block2::opaque_self + hier_block2::self() + { + return shared_from_this(); + } + + hier_block2_sptr + hier_block2::to_hier_block2() + { + return cast_to_hier_block2_sptr(shared_from_this()); + } + + void + hier_block2::connect(basic_block_sptr block) + { + d_detail->connect(block); + } + + void + hier_block2::connect(basic_block_sptr src, int src_port, + basic_block_sptr dst, int dst_port) + { + d_detail->connect(src, src_port, dst, dst_port); + } + + void + hier_block2::msg_connect(basic_block_sptr src, pmt::pmt_t srcport, + basic_block_sptr dst, pmt::pmt_t dstport) + { + if(!pmt::is_symbol(srcport)) { + throw std::runtime_error("bad port id"); + } + d_detail->msg_connect(src, srcport, dst, dstport); + } + + void + hier_block2::msg_connect(basic_block_sptr src, std::string srcport, + basic_block_sptr dst, std::string dstport) + { + d_detail->msg_connect(src, pmt::mp(srcport), dst, pmt::mp(dstport)); + } + + void + hier_block2::msg_disconnect(basic_block_sptr src, pmt::pmt_t srcport, + basic_block_sptr dst, pmt::pmt_t dstport) + { + if(!pmt::is_symbol(srcport)) { + throw std::runtime_error("bad port id"); + } + d_detail->msg_disconnect(src, srcport, dst, dstport); + } + + void + hier_block2::msg_disconnect(basic_block_sptr src, std::string srcport, + basic_block_sptr dst, std::string dstport) + { + d_detail->msg_disconnect(src, pmt::mp(srcport), dst, pmt::mp(dstport)); + } + + void + hier_block2::disconnect(basic_block_sptr block) + { + d_detail->disconnect(block); + } + + void + hier_block2::disconnect(basic_block_sptr src, int src_port, + basic_block_sptr dst, int dst_port) + { + d_detail->disconnect(src, src_port, dst, dst_port); + } + + void + hier_block2::disconnect_all() + { + d_detail->disconnect_all(); + } + + void + hier_block2::lock() + { + d_detail->lock(); + } + + void + hier_block2::unlock() + { + d_detail->unlock(); + } + + flat_flowgraph_sptr + hier_block2::flatten() const + { + flat_flowgraph_sptr new_ffg = make_flat_flowgraph(); + d_detail->flatten_aux(new_ffg); + return new_ffg; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/hier_block2_detail.cc b/gnuradio-runtime/lib/hier_block2_detail.cc new file mode 100644 index 0000000000..83207d978c --- /dev/null +++ b/gnuradio-runtime/lib/hier_block2_detail.cc @@ -0,0 +1,657 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2007,2009,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "hier_block2_detail.h" +#include <gnuradio/io_signature.h> +#include <gnuradio/prefs.h> +#include <stdexcept> +#include <sstream> +#include <boost/format.hpp> + +namespace gr { + +#define HIER_BLOCK2_DETAIL_DEBUG 0 + + hier_block2_detail::hier_block2_detail(hier_block2 *owner) + : d_owner(owner), + d_parent_detail(0), + d_fg(make_flowgraph()) + { + int min_inputs = owner->input_signature()->min_streams(); + int max_inputs = owner->input_signature()->max_streams(); + int min_outputs = owner->output_signature()->min_streams(); + int max_outputs = owner->output_signature()->max_streams(); + + if(max_inputs == io_signature::IO_INFINITE || + max_outputs == io_signature::IO_INFINITE || + (min_inputs != max_inputs) ||(min_outputs != max_outputs) ) { + std::stringstream msg; + msg << "Hierarchical blocks do not yet support arbitrary or" + << " variable numbers of inputs or outputs (" << d_owner->name() << ")"; + throw std::runtime_error(msg.str()); + } + + d_inputs = std::vector<endpoint_vector_t>(max_inputs); + d_outputs = endpoint_vector_t(max_outputs); + } + + hier_block2_detail::~hier_block2_detail() + { + d_owner = 0; // Don't use delete, we didn't allocate + } + + void + hier_block2_detail::connect(basic_block_sptr block) + { + std::stringstream msg; + + // Check if duplicate + if(std::find(d_blocks.begin(), d_blocks.end(), block) != d_blocks.end()) { + msg << "Block " << block << " already connected."; + throw std::invalid_argument(msg.str()); + } + + // Check if has inputs or outputs + if(block->input_signature()->max_streams() != 0 || + block->output_signature()->max_streams() != 0) { + msg << "Block " << block << " must not have any input or output ports"; + throw std::invalid_argument(msg.str()); + } + + hier_block2_sptr hblock(cast_to_hier_block2_sptr(block)); + + if(hblock && hblock.get() != d_owner) { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "connect: block is hierarchical, setting parent to " << this << std::endl; + hblock->d_detail->d_parent_detail = this; + } + + d_blocks.push_back(block); + } + + void + hier_block2_detail::connect(basic_block_sptr src, int src_port, + basic_block_sptr dst, int dst_port) + { + std::stringstream msg; + + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "connecting: " << endpoint(src, src_port) + << " -> " << endpoint(dst, dst_port) << std::endl; + + if(src.get() == dst.get()) + throw std::invalid_argument("connect: src and destination blocks cannot be the same"); + + hier_block2_sptr src_block(cast_to_hier_block2_sptr(src)); + hier_block2_sptr dst_block(cast_to_hier_block2_sptr(dst)); + + if(src_block && src.get() != d_owner) { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "connect: src is hierarchical, setting parent to " << this << std::endl; + src_block->d_detail->d_parent_detail = this; + } + + if(dst_block && dst.get() != d_owner) { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "connect: dst is hierarchical, setting parent to " << this << std::endl; + dst_block->d_detail->d_parent_detail = this; + } + + // Connections to block inputs or outputs + int max_port; + if(src.get() == d_owner) { + max_port = src->input_signature()->max_streams(); + if((max_port != -1 && (src_port >= max_port)) || src_port < 0) { + msg << "source port " << src_port << " out of range for " << src; + throw std::invalid_argument(msg.str()); + } + + return connect_input(src_port, dst_port, dst); + } + + if(dst.get() == d_owner) { + max_port = dst->output_signature()->max_streams(); + if((max_port != -1 && (dst_port >= max_port)) || dst_port < 0) { + msg << "destination port " << dst_port << " out of range for " << dst; + throw std::invalid_argument(msg.str()); + } + + return connect_output(dst_port, src_port, src); + } + + // Internal connections + d_fg->connect(src, src_port, dst, dst_port); + + // TODO: connects to NC + } + + void + hier_block2_detail::msg_connect(basic_block_sptr src, pmt::pmt_t srcport, + basic_block_sptr dst, pmt::pmt_t dstport) + { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "connecting message port..." << std::endl; + + // register the subscription + // this is done later... + // src->message_port_sub(srcport, pmt::cons(dst->alias_pmt(), dstport)); + + // add block uniquely to list to internal blocks + if(std::find(d_blocks.begin(), d_blocks.end(), dst) == d_blocks.end()){ + d_blocks.push_back(src); + d_blocks.push_back(dst); + } + + bool hier_out = (d_owner == src.get()) && src->message_port_is_hier_out(srcport);; + bool hier_in = (d_owner == dst.get()) && dst->message_port_is_hier_in(dstport); + + hier_block2_sptr src_block(cast_to_hier_block2_sptr(src)); + hier_block2_sptr dst_block(cast_to_hier_block2_sptr(dst)); + + if(src_block && src.get() != d_owner) { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "connect: src is hierarchical, setting parent to " << this << std::endl; + src_block->d_detail->d_parent_detail = this; + } + + if(dst_block && dst.get() != d_owner) { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "connect: dst is hierarchical, setting parent to " << this << std::endl; + dst_block->d_detail->d_parent_detail = this; + } + + // add edge for this message connection + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << boost::format("connect( (%s, %s, %d), (%s, %s, %d) )\n") % \ + src % srcport % hier_out % + dst % dstport % hier_in; + d_fg->connect(msg_endpoint(src, srcport, hier_out), msg_endpoint(dst, dstport, hier_in)); + } + + void + hier_block2_detail::msg_disconnect(basic_block_sptr src, pmt::pmt_t srcport, + basic_block_sptr dst, pmt::pmt_t dstport) + { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "disconnecting message port..." << std::endl; + + // unregister the subscription - if already subscribed + src->message_port_unsub(srcport, pmt::cons(dst->alias_pmt(), dstport)); + + // remove edge for this message connection + bool hier_out = (d_owner == src.get()) && src->message_port_is_hier_out(srcport);; + bool hier_in = (d_owner == dst.get()) && dst->message_port_is_hier_in(dstport); + d_fg->disconnect(msg_endpoint(src, srcport, hier_out), msg_endpoint(dst, dstport, hier_in)); + } + + void + hier_block2_detail::disconnect(basic_block_sptr block) + { + // Check on singleton list + for(basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { + if(*p == block) { + d_blocks.erase(p); + + hier_block2_sptr hblock(cast_to_hier_block2_sptr(block)); + if(block && block.get() != d_owner) { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "disconnect: block is hierarchical, clearing parent" << std::endl; + hblock->d_detail->d_parent_detail = 0; + } + + return; + } + } + + // Otherwise find all edges containing block + edge_vector_t edges, tmp = d_fg->edges(); + edge_vector_t::iterator p; + for(p = tmp.begin(); p != tmp.end(); p++) { + if((*p).src().block() == block || (*p).dst().block() == block) { + edges.push_back(*p); + + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "disconnect: block found in edge " << (*p) << std::endl; + } + } + + if(edges.size() == 0) { + std::stringstream msg; + msg << "cannot disconnect block " << block << ", not found"; + throw std::invalid_argument(msg.str()); + } + + for(p = edges.begin(); p != edges.end(); p++) { + disconnect((*p).src().block(), (*p).src().port(), + (*p).dst().block(), (*p).dst().port()); + } + } + + void + hier_block2_detail::disconnect(basic_block_sptr src, int src_port, + basic_block_sptr dst, int dst_port) + { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "disconnecting: " << endpoint(src, src_port) + << " -> " << endpoint(dst, dst_port) << std::endl; + + if(src.get() == dst.get()) + throw std::invalid_argument("disconnect: source and destination blocks cannot be the same"); + + hier_block2_sptr src_block(cast_to_hier_block2_sptr(src)); + hier_block2_sptr dst_block(cast_to_hier_block2_sptr(dst)); + + if(src_block && src.get() != d_owner) { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "disconnect: src is hierarchical, clearing parent" << std::endl; + src_block->d_detail->d_parent_detail = 0; + } + + if(dst_block && dst.get() != d_owner) { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "disconnect: dst is hierarchical, clearing parent" << std::endl; + dst_block->d_detail->d_parent_detail = 0; + } + + if(src.get() == d_owner) + return disconnect_input(src_port, dst_port, dst); + + if(dst.get() == d_owner) + return disconnect_output(dst_port, src_port, src); + + // Internal connections + d_fg->disconnect(src, src_port, dst, dst_port); + } + + void + hier_block2_detail::connect_input(int my_port, int port, + basic_block_sptr block) + { + std::stringstream msg; + + if(my_port < 0 || my_port >= (signed)d_inputs.size()) { + msg << "input port " << my_port << " out of range for " << block; + throw std::invalid_argument(msg.str()); + } + + endpoint_vector_t &endps = d_inputs[my_port]; + endpoint endp(block, port); + + endpoint_viter_t p = std::find(endps.begin(), endps.end(), endp); + if(p != endps.end()) { + msg << "external input port " << my_port << " already wired to " << endp; + throw std::invalid_argument(msg.str()); + } + + endps.push_back(endp); + } + + void + hier_block2_detail::connect_output(int my_port, int port, + basic_block_sptr block) + { + std::stringstream msg; + + if(my_port < 0 || my_port >= (signed)d_outputs.size()) { + msg << "output port " << my_port << " out of range for " << block; + throw std::invalid_argument(msg.str()); + } + + if(d_outputs[my_port].block()) { + msg << "external output port " << my_port << " already connected from " + << d_outputs[my_port]; + throw std::invalid_argument(msg.str()); + } + + d_outputs[my_port] = endpoint(block, port); + } + + void + hier_block2_detail::disconnect_input(int my_port, int port, + basic_block_sptr block) + { + std::stringstream msg; + + if(my_port < 0 || my_port >= (signed)d_inputs.size()) { + msg << "input port number " << my_port << " out of range for " << block; + throw std::invalid_argument(msg.str()); + } + + endpoint_vector_t &endps = d_inputs[my_port]; + endpoint endp(block, port); + + endpoint_viter_t p = std::find(endps.begin(), endps.end(), endp); + if(p == endps.end()) { + msg << "external input port " << my_port << " not connected to " << endp; + throw std::invalid_argument(msg.str()); + } + + endps.erase(p); + } + + void + hier_block2_detail::disconnect_output(int my_port, int port, + basic_block_sptr block) + { + std::stringstream msg; + + if(my_port < 0 || my_port >= (signed)d_outputs.size()) { + msg << "output port number " << my_port << " out of range for " << block; + throw std::invalid_argument(msg.str()); + } + + if(d_outputs[my_port].block() != block) { + msg << "block " << block << " not assigned to output " + << my_port << ", can't disconnect"; + throw std::invalid_argument(msg.str()); + } + + d_outputs[my_port] = endpoint(); + } + + endpoint_vector_t + hier_block2_detail::resolve_port(int port, bool is_input) + { + std::stringstream msg; + + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "Resolving port " << port << " as an " + << (is_input ? "input" : "output") + << " of " << d_owner->name() << std::endl; + + endpoint_vector_t result; + + if(is_input) { + if(port < 0 || port >= (signed)d_inputs.size()) { + msg << "resolve_port: hierarchical block '" << d_owner->name() + << "': input " << port << " is out of range"; + throw std::runtime_error(msg.str()); + } + + if(d_inputs[port].empty()) { + msg << "resolve_port: hierarchical block '" << d_owner->name() + << "': input " << port << " is not connected internally"; + throw std::runtime_error(msg.str()); + } + + endpoint_vector_t &endps = d_inputs[port]; + endpoint_viter_t p; + for(p = endps.begin(); p != endps.end(); p++) { + endpoint_vector_t tmp = resolve_endpoint(*p, true); + std::copy(tmp.begin(), tmp.end(), back_inserter(result)); + } + } + else { + if(port < 0 || port >= (signed)d_outputs.size()) { + msg << "resolve_port: hierarchical block '" << d_owner->name() + << "': output " << port << " is out of range"; + throw std::runtime_error(msg.str()); + } + + if(d_outputs[port] == endpoint()) { + msg << "resolve_port: hierarchical block '" << d_owner->name() + << "': output " << port << " is not connected internally"; + throw std::runtime_error(msg.str()); + } + + result = resolve_endpoint(d_outputs[port], false); + } + + if(result.empty()) { + msg << "resolve_port: hierarchical block '" << d_owner->name() + << "': unable to resolve " + << (is_input ? "input port " : "output port ") + << port; + throw std::runtime_error(msg.str()); + } + + return result; + } + + void + hier_block2_detail::disconnect_all() + { + d_fg->clear(); + d_blocks.clear(); + d_inputs.clear(); + d_outputs.clear(); + } + + endpoint_vector_t + hier_block2_detail::resolve_endpoint(const endpoint &endp, bool is_input) const + { + std::stringstream msg; + endpoint_vector_t result; + + // Check if endpoint is a leaf node + if(cast_to_block_sptr(endp.block())) { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "Block " << endp.block() << " is a leaf node, returning." << std::endl; + result.push_back(endp); + return result; + } + + // Check if endpoint is a hierarchical block + hier_block2_sptr hier_block2(cast_to_hier_block2_sptr(endp.block())); + if(hier_block2) { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "Resolving endpoint " << endp << " as an " + << (is_input ? "input" : "output") + << ", recursing" << std::endl; + return hier_block2->d_detail->resolve_port(endp.port(), is_input); + } + + msg << "unable to resolve" << (is_input ? " input " : " output ") + << "endpoint " << endp; + throw std::runtime_error(msg.str()); + } + + void + hier_block2_detail::flatten_aux(flat_flowgraph_sptr sfg) const + { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << " ** Flattening " << d_owner->name() << std::endl; + + // Add my edges to the flow graph, resolving references to actual endpoints + edge_vector_t edges = d_fg->edges(); + msg_edge_vector_t msg_edges = d_fg->msg_edges(); + edge_viter_t p; + msg_edge_viter_t q,u; + + // Only run setup_rpc if ControlPort config param is enabled. + bool ctrlport_on = prefs::singleton()->get_bool("ControlPort", "on", false); + + // For every block (gr::block and gr::hier_block2), set up the RPC + // interface. + for(p = edges.begin(); p != edges.end(); p++) { + basic_block_sptr b; + b = p->src().block(); + + if(ctrlport_on) { + if(!b->is_rpc_set()) { + b->setup_rpc(); + b->rpc_set(); + } + } + + b = p->dst().block(); + if(ctrlport_on) { + if(!b->is_rpc_set()) { + b->setup_rpc(); + b->rpc_set(); + } + } + } + + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "Flattening stream connections: " << std::endl; + + for(p = edges.begin(); p != edges.end(); p++) { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "Flattening edge " << (*p) << std::endl; + + endpoint_vector_t src_endps = resolve_endpoint(p->src(), false); + endpoint_vector_t dst_endps = resolve_endpoint(p->dst(), true); + + endpoint_viter_t s, d; + for(s = src_endps.begin(); s != src_endps.end(); s++) { + for(d = dst_endps.begin(); d != dst_endps.end(); d++) { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << (*s) << "->" << (*d) << std::endl; + sfg->connect(*s, *d); + } + } + } + + // loop through flattening hierarchical connections + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "Flattening msg connections: " << std::endl; + + std::vector<std::pair<msg_endpoint, bool> > resolved_endpoints; + for(q = msg_edges.begin(); q != msg_edges.end(); q++) { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << boost::format(" flattening edge ( %s, %s, %d) -> ( %s, %s, %d)\n") % \ + q->src().block() % q->src().port() % q->src().is_hier() % q->dst().block() % \ + q->dst().port() % q->dst().is_hier(); + + bool normal_connection = true; + + // resolve existing connections to hier ports + if(q->dst().is_hier()) { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << boost::format(" resolve hier output (%s, %s)") % \ + q->dst().block() % q->dst().port() << std::endl; + sfg->replace_endpoint( q->dst(), q->src(), true ); + resolved_endpoints.push_back(std::pair<msg_endpoint, bool>(q->dst(),true)); + normal_connection = false; + } + + if(q->src().is_hier()) { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << boost::format(" resolve hier input (%s, %s)") % \ + q->src().block() % q->src().port() << std::endl; + sfg->replace_endpoint( q->src(), q->dst(), false ); + resolved_endpoints.push_back(std::pair<msg_endpoint, bool>(q->src(),false)); + normal_connection = false; + } + + // propogate non hier connections through + if(normal_connection){ + sfg->connect( q->src(), q->dst() ); + } + } + + for(std::vector<std::pair<msg_endpoint, bool> >::iterator it = resolved_endpoints.begin(); + it != resolved_endpoints.end(); it++) { + sfg->clear_endpoint((*it).first, (*it).second); + } + + /* + // connect primitive edges in the new fg + for(q = msg_edges.begin(); q != msg_edges.end(); q++) { + if((!q->src().is_hier()) && (!q->dst().is_hier())) { + sfg->connect(q->src(), q->dst()); + } + else { + std::cout << "not connecting hier connection!" << std::endl; + } + } + */ + + // Construct unique list of blocks used either in edges, inputs, + // outputs, or by themselves. I still hate STL. + basic_block_vector_t blocks; // unique list of used blocks + basic_block_vector_t tmp = d_fg->calc_used_blocks(); + + // First add the list of singleton blocks + std::vector<basic_block_sptr>::const_iterator b; // Because flatten_aux is const + for(b = d_blocks.begin(); b != d_blocks.end(); b++) + tmp.push_back(*b); + + // Now add the list of connected input blocks + std::stringstream msg; + for(unsigned int i = 0; i < d_inputs.size(); i++) { + if(d_inputs[i].size() == 0) { + msg << "In hierarchical block " << d_owner->name() << ", input " << i + << " is not connected internally"; + throw std::runtime_error(msg.str()); + } + + for(unsigned int j = 0; j < d_inputs[i].size(); j++) + tmp.push_back(d_inputs[i][j].block()); + } + + for(unsigned int i = 0; i < d_outputs.size(); i++) { + basic_block_sptr blk = d_outputs[i].block(); + if(!blk) { + msg << "In hierarchical block " << d_owner->name() << ", output " << i + << " is not connected internally"; + throw std::runtime_error(msg.str()); + } + tmp.push_back(blk); + } + sort(tmp.begin(), tmp.end()); + + std::insert_iterator<basic_block_vector_t> inserter(blocks, blocks.begin()); + unique_copy(tmp.begin(), tmp.end(), inserter); + + // Recurse hierarchical children + for(basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { + hier_block2_sptr hier_block2(cast_to_hier_block2_sptr(*p)); + if(hier_block2 && (hier_block2.get() != d_owner)) { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "flatten_aux: recursing into hierarchical block " + << hier_block2 << std::endl; + hier_block2->d_detail->flatten_aux(sfg); + } + } + } + + void + hier_block2_detail::lock() + { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "lock: entered in " << this << std::endl; + + if(d_parent_detail) + d_parent_detail->lock(); + else + d_owner->lock(); + } + + void + hier_block2_detail::unlock() + { + if(HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "unlock: entered in " << this << std::endl; + + if(d_parent_detail) + d_parent_detail->unlock(); + else + d_owner->unlock(); + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/hier_block2_detail.h b/gnuradio-runtime/lib/hier_block2_detail.h new file mode 100644 index 0000000000..99bf6e8ef1 --- /dev/null +++ b/gnuradio-runtime/lib/hier_block2_detail.h @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2007,2009,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_RUNTIME_HIER_BLOCK2_DETAIL_H +#define INCLUDED_GR_RUNTIME_HIER_BLOCK2_DETAIL_H + +#include <gnuradio/api.h> +#include <gnuradio/hier_block2.h> +#include <flat_flowgraph.h> +#include <boost/utility.hpp> + +namespace gr { + + /*! + * \ingroup internal + */ + class GR_RUNTIME_API hier_block2_detail : boost::noncopyable + { + public: + hier_block2_detail(hier_block2 *owner); + ~hier_block2_detail(); + + void connect(basic_block_sptr block); + void connect(basic_block_sptr src, int src_port, + basic_block_sptr dst, int dst_port); + void msg_connect(basic_block_sptr src, pmt::pmt_t srcport, + basic_block_sptr dst, pmt::pmt_t dstport); + void msg_disconnect(basic_block_sptr src, pmt::pmt_t srcport, + basic_block_sptr dst, pmt::pmt_t dstport); + void disconnect(basic_block_sptr block); + void disconnect(basic_block_sptr, int src_port, + basic_block_sptr, int dst_port); + void disconnect_all(); + void lock(); + void unlock(); + void flatten_aux(flat_flowgraph_sptr sfg) const; + + private: + // Private implementation data + hier_block2 *d_owner; + hier_block2_detail *d_parent_detail; + flowgraph_sptr d_fg; + std::vector<endpoint_vector_t> d_inputs; // Multiple internal endpoints per external input + endpoint_vector_t d_outputs; // Single internal endpoint per external output + basic_block_vector_t d_blocks; + + void connect_input(int my_port, int port, basic_block_sptr block); + void connect_output(int my_port, int port, basic_block_sptr block); + void disconnect_input(int my_port, int port, basic_block_sptr block); + void disconnect_output(int my_port, int port, basic_block_sptr block); + + endpoint_vector_t resolve_port(int port, bool is_input); + endpoint_vector_t resolve_endpoint(const endpoint &endp, bool is_input) const; + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_RUNTIME_HIER_BLOCK2_DETAIL_H */ diff --git a/gnuradio-runtime/lib/io_signature.cc b/gnuradio-runtime/lib/io_signature.cc new file mode 100644 index 0000000000..ccfdf3c06b --- /dev/null +++ b/gnuradio-runtime/lib/io_signature.cc @@ -0,0 +1,117 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gnuradio/io_signature.h> +#include <stdexcept> +#include <iostream> + +namespace gr { + + gr::io_signature::sptr + io_signature::makev(int min_streams, int max_streams, + const std::vector<int> &sizeof_stream_items) + { + return gr::io_signature::sptr + (new io_signature(min_streams, max_streams, + sizeof_stream_items)); + } + + gr::io_signature::sptr + io_signature::make(int min_streams, int max_streams, + int sizeof_stream_item) + { + std::vector<int> sizeof_items(1); + sizeof_items[0] = sizeof_stream_item; + return io_signature::makev(min_streams, max_streams, sizeof_items); + } + + gr::io_signature::sptr + io_signature::make2(int min_streams, int max_streams, + int sizeof_stream_item1, + int sizeof_stream_item2) + { + std::vector<int> sizeof_items(2); + sizeof_items[0] = sizeof_stream_item1; + sizeof_items[1] = sizeof_stream_item2; + return io_signature::makev(min_streams, max_streams, sizeof_items); + } + + gr::io_signature::sptr + io_signature::make3(int min_streams, int max_streams, + int sizeof_stream_item1, + int sizeof_stream_item2, + int sizeof_stream_item3) + { + std::vector<int> sizeof_items(3); + sizeof_items[0] = sizeof_stream_item1; + sizeof_items[1] = sizeof_stream_item2; + sizeof_items[2] = sizeof_stream_item3; + return io_signature::makev(min_streams, max_streams, sizeof_items); + } + + // ------------------------------------------------------------------------ + + io_signature::io_signature(int min_streams, int max_streams, + const std::vector<int> &sizeof_stream_items) + { + if(min_streams < 0 + || (max_streams != IO_INFINITE && max_streams < min_streams)) + throw std::invalid_argument ("gr::io_signature(1)"); + + if(sizeof_stream_items.size() < 1) + throw std::invalid_argument("gr::io_signature(2)"); + + for(size_t i = 0; i < sizeof_stream_items.size(); i++) { + if(max_streams != 0 && sizeof_stream_items[i] < 1) + throw std::invalid_argument("gr::io_signature(3)"); + } + + d_min_streams = min_streams; + d_max_streams = max_streams; + d_sizeof_stream_item = sizeof_stream_items; + } + + io_signature::~io_signature() + { + } + + int + io_signature::sizeof_stream_item(int _index) const + { + if(_index < 0) + throw std::invalid_argument("gr::io_signature::sizeof_stream_item"); + + size_t index = _index; + return d_sizeof_stream_item[std::min(index, d_sizeof_stream_item.size() - 1)]; + } + + std::vector<int> + io_signature::sizeof_stream_items() const + { + return d_sizeof_stream_item; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/local_sighandler.cc b/gnuradio-runtime/lib/local_sighandler.cc new file mode 100644 index 0000000000..ebd9bb1362 --- /dev/null +++ b/gnuradio-runtime/lib/local_sighandler.cc @@ -0,0 +1,189 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "local_sighandler.h" +#include <stdexcept> +#include <stdio.h> +#include <string.h> + +namespace gr { + + local_sighandler::local_sighandler(int signum, + void (*new_handler)(int)) + : d_signum(signum) + { +#ifdef HAVE_SIGACTION + struct sigaction new_action; + memset(&new_action, 0, sizeof(new_action)); + + new_action.sa_handler = new_handler; + sigemptyset(&new_action.sa_mask); + new_action.sa_flags = 0; + + if(sigaction (d_signum, &new_action, &d_old_action) < 0) { + perror("sigaction (install new)"); + throw std::runtime_error("sigaction"); + } +#endif + } + + local_sighandler::~local_sighandler() + { +#ifdef HAVE_SIGACTION + if(sigaction (d_signum, &d_old_action, 0) < 0) { + perror("sigaction (restore old)"); + throw std::runtime_error("sigaction"); + } +#endif + } + + void + local_sighandler::throw_signal(int signum) + { + throw signal(signum); + } + + /* + * Semi-hideous way to may a signal number into a signal name + */ + #define SIGNAME(x) case x: return #x + + std::string + signal::name() const + { + char tmp[128]; + + switch(signum()) { +#ifdef SIGHUP + SIGNAME(SIGHUP); +#endif +#ifdef SIGINT + SIGNAME(SIGINT); +#endif +#ifdef SIGQUIT + SIGNAME(SIGQUIT); +#endif +#ifdef SIGILL + SIGNAME(SIGILL); +#endif +#ifdef SIGTRAP + SIGNAME(SIGTRAP); +#endif +#ifdef SIGABRT + SIGNAME(SIGABRT); +#endif +#ifdef SIGBUS + SIGNAME(SIGBUS); +#endif +#ifdef SIGFPE + SIGNAME(SIGFPE); +#endif +#ifdef SIGKILL + SIGNAME(SIGKILL); +#endif +#ifdef SIGUSR1 + SIGNAME(SIGUSR1); +#endif +#ifdef SIGSEGV + SIGNAME(SIGSEGV); +#endif +#ifdef SIGUSR2 + SIGNAME(SIGUSR2); +#endif +#ifdef SIGPIPE + SIGNAME(SIGPIPE); +#endif +#ifdef SIGALRM + SIGNAME(SIGALRM); +#endif +#ifdef SIGTERM + SIGNAME(SIGTERM); +#endif +#ifdef SIGSTKFLT + SIGNAME(SIGSTKFLT); +#endif +#ifdef SIGCHLD + SIGNAME(SIGCHLD); +#endif +#ifdef SIGCONT + SIGNAME(SIGCONT); +#endif +#ifdef SIGSTOP + SIGNAME(SIGSTOP); +#endif +#ifdef SIGTSTP + SIGNAME(SIGTSTP); +#endif +#ifdef SIGTTIN + SIGNAME(SIGTTIN); +#endif +#ifdef SIGTTOU + SIGNAME(SIGTTOU); +#endif +#ifdef SIGURG + SIGNAME(SIGURG); +#endif +#ifdef SIGXCPU + SIGNAME(SIGXCPU); +#endif +#ifdef SIGXFSZ + SIGNAME(SIGXFSZ); +#endif +#ifdef SIGVTALRM + SIGNAME(SIGVTALRM); +#endif +#ifdef SIGPROF + SIGNAME(SIGPROF); +#endif +#ifdef SIGWINCH + SIGNAME(SIGWINCH); +#endif +#ifdef SIGIO + SIGNAME(SIGIO); +#endif +#ifdef SIGPWR + SIGNAME(SIGPWR); +#endif +#ifdef SIGSYS + SIGNAME(SIGSYS); +#endif + default: +#if defined (HAVE_SNPRINTF) +#if defined (SIGRTMIN) && defined (SIGRTMAX) + if(signum() >= SIGRTMIN && signum() <= SIGRTMAX) { + snprintf(tmp, sizeof(tmp), "SIGRTMIN + %d", signum()); + return tmp; + } +#endif + snprintf(tmp, sizeof(tmp), "SIGNAL %d", signum()); + return tmp; +#else + return "Unknown signal"; +#endif + } + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/gr_local_sighandler.h b/gnuradio-runtime/lib/local_sighandler.h index a49ee031ca..bd322e5b00 100644 --- a/gnuradio-runtime/lib/gr_local_sighandler.h +++ b/gnuradio-runtime/lib/local_sighandler.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -27,39 +27,48 @@ #include <signal.h> #endif -#include <gr_runtime_api.h> +#include <gnuradio/api.h> #include <string> -/*! - * \brief Get and set signal handler. - * - * \ingroup internal - * Constructor installs new handler, destructor reinstalls - * original value. - */ -class GR_RUNTIME_API gr_local_sighandler { - int d_signum; +namespace gr { + + /*! + * \brief Get and set signal handler. + * + * \ingroup internal + * Constructor installs new handler, destructor reinstalls + * original value. + */ + class GR_RUNTIME_API local_sighandler + { + private: + int d_signum; #ifdef HAVE_SIGACTION - struct sigaction d_old_action; + struct sigaction d_old_action; #endif -public: - gr_local_sighandler (int signum, void (*new_handler)(int)); - ~gr_local_sighandler (); - /* throw gr_signal (signum) */ - static void throw_signal (int signum); -}; + public: + local_sighandler(int signum, void (*new_handler)(int)); + ~local_sighandler(); -/*! - * \brief Representation of signal. - */ -class GR_RUNTIME_API gr_signal -{ - int d_signum; -public: - gr_signal (int signum) : d_signum (signum) {} - int signal () const { return d_signum; } - std::string name () const; -}; + /* throw gr_signal (signum) */ + static void throw_signal(int signum); + }; + + /*! + * \brief Representation of signal. + */ + class GR_RUNTIME_API signal + { + private: + int d_signum; + + public: + signal(int signum) : d_signum(signum) {} + int signum() const { return d_signum; } + std::string name() const; + }; + +} /* namespace gr */ #endif /* INCLUDED_GR_LOCAL_SIGHANDLER_H */ diff --git a/gnuradio-runtime/lib/logger.cc b/gnuradio-runtime/lib/logger.cc new file mode 100644 index 0000000000..dceb18471f --- /dev/null +++ b/gnuradio-runtime/lib/logger.cc @@ -0,0 +1,323 @@ +/* -*- c++ -*- */ +/* + * Copyright 2012 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/******************************************************************************* +* Author: Mark Plett +* Description: +* The gr_log module wraps the log4cpp library for logging in gnuradio. +*******************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/logger.h> +#include <stdexcept> +#include <algorithm> + + +#ifdef ENABLE_GR_LOG +#ifdef HAVE_LOG4CPP + +namespace gr { + + bool logger_config::logger_configured(false); + + /************************ BEGIN LOG4CPP HELPERS ***********************/ + /* Logger config class. This is a singleton that controls how + * log4cpp is configured If watch_period>0 a thread is started to + * watch teh config file for changes. + */ + + // Getters of logger_config + logger_config& + logger_config::get_instance(void) + { + static logger_config instance; + return instance; + } + + std::string + logger_config::get_filename() + { + logger_config& in=get_instance(); + return in.filename; + } + + unsigned int + logger_config::get_watch_period() + { + logger_config& in=get_instance(); + return in.watch_period; + } + + // Method to watch config file for changes + void + logger_config::watch_file(std::string filename, unsigned int watch_period) + { + std::time_t last_write(boost::filesystem::last_write_time(filename)); + std::time_t current_time(0); + while(true) { + try { + current_time = boost::filesystem::last_write_time(filename); + if(current_time>last_write) { + std::cout<<"GNURadio Reloading logger configuration:"<<filename<<std::endl; + last_write = current_time; + // Should we wipe out all old configuration or just add the + // new? Just adding... logger_reset_config(); + logger_configured = logger_load_config(filename); + } + boost::this_thread::sleep(boost::posix_time::time_duration(0,0,watch_period,0)); + } + catch(const boost::thread_interrupted&) { + std::cout<<"GNURadio leaving logger config file watch."<<std::endl; + break; + } + } + } + + // Method to load the confifuration. It only loads if the filename + // or watch has changed + void + logger_config::load_config(std::string filename,unsigned int watch_period) + { + logger_config& instance = get_instance(); + // Only reconfigure if filename or watch has changed + if(!logger_configured) { + instance.filename = filename; + instance.watch_period = watch_period; + // Stop any file watching thread + if(instance.watch_thread!=NULL) + stop_watch(); + // Load configuration + std::cout<<"GNURadio Loading logger configuration:"<<instance.filename<<std::endl; + logger_configured = logger_load_config(instance.filename); + // Start watch if required + if(instance.watch_period>0) { + instance.watch_thread = new boost::thread(watch_file, instance.filename, + instance.watch_period); + } + } + } + + // Method to stop the watcher thread + void + logger_config::stop_watch() + { + logger_config& instance = get_instance(); + if(instance.watch_thread) { + instance.watch_thread->interrupt(); + instance.watch_thread->join(); + delete(instance.watch_thread); + instance.watch_thread=NULL; + } + } + + // Method to reset logger configuration + void + logger_config::reset_config(void) + { + logger_config& instance = get_instance(); + stop_watch(); + std::vector<log4cpp::Category*> *loggers = log4cpp::Category::getCurrentCategories(); + std::vector<log4cpp::Category*>::iterator logger = loggers->begin(); + // We can't destroy categories but we can neuter them by removing all appenders. + for(;logger!=loggers->end();logger++) { + (*logger)->removeAllAppenders(); + } + instance.filename = std::string(""); + instance.watch_period = 0; + logger_configured = false; + } + + /***************** Functions to call log4cpp methods *************************/ + + logger_ptr + logger_get_logger(std::string name) + { + if(log4cpp::Category::exists(name)) { + logger_ptr logger = &log4cpp::Category::getInstance(name); + return logger; + } + else { + logger_ptr logger = &log4cpp::Category::getInstance(name); + logger->setPriority(log4cpp::Priority::NOTSET); + return logger; + } + } + + bool + logger_load_config(const std::string &config_filename) + { + if(config_filename.size() != 0) { + try { + log4cpp::PropertyConfigurator::configure(config_filename); + return true; + } + catch(log4cpp::ConfigureFailure &e) { + std::cout << "Logger config failed :" << e.what() << std::endl; + } + } + return false; + } + + void + logger_set_level(logger_ptr logger, const std::string &level) + { + std::string nocase = level; + std::transform(level.begin(), level.end(), nocase.begin(), ::tolower); + + if(nocase == "off" || nocase == "notset") + logger_set_level(logger, log4cpp::Priority::NOTSET); + else if(nocase == "all" || nocase == "debug") + logger_set_level(logger, log4cpp::Priority::DEBUG); + else if(nocase == "info") + logger_set_level(logger, log4cpp::Priority::INFO); + else if(nocase == "notice") + logger_set_level(logger, log4cpp::Priority::NOTICE); + else if(nocase == "warn") + logger_set_level(logger, log4cpp::Priority::WARN); + else if(nocase == "error") + logger_set_level(logger, log4cpp::Priority::ERROR); + else if(nocase == "crit") + logger_set_level(logger, log4cpp::Priority::CRIT); + else if(nocase == "alert") + logger_set_level(logger, log4cpp::Priority::ALERT); + else if(nocase=="fatal") + logger_set_level(logger, log4cpp::Priority::FATAL); + else if(nocase == "emerg") + logger_set_level(logger, log4cpp::Priority::EMERG); + else + throw std::runtime_error("logger_set_level: Bad level type.\n"); + } + + void + logger_set_level(logger_ptr logger, log4cpp::Priority::Value level) + { + logger->setPriority(level); + } + + void + logger_get_level(logger_ptr logger, std::string &level) + { + log4cpp::Priority::Value levelPtr = logger->getPriority(); + if(levelPtr == log4cpp::Priority::NOTSET) level = "noset"; + if(levelPtr == log4cpp::Priority::DEBUG) level = "debug"; + if(levelPtr == log4cpp::Priority::INFO) level = "info"; + if(levelPtr == log4cpp::Priority::NOTICE) level = "notice"; + if(levelPtr == log4cpp::Priority::WARN) level = "warn"; + if(levelPtr == log4cpp::Priority::ERROR) level = "error"; + if(levelPtr == log4cpp::Priority::CRIT) level = "crit"; + if(levelPtr == log4cpp::Priority::ALERT) level = "alert"; + if(levelPtr == log4cpp::Priority::FATAL) level = "fatal"; + if(levelPtr == log4cpp::Priority::EMERG) level = "emerg"; + } + + void + logger_get_level(logger_ptr logger,log4cpp::Priority::Value level) + { + level = logger->getPriority(); + } + + void + logger_add_console_appender(logger_ptr logger, std::string target, std::string pattern) + { + log4cpp::PatternLayout* layout = new log4cpp::PatternLayout(); + log4cpp::Appender* app; + if(target=="stdout") + app = new log4cpp::OstreamAppender("ConsoleAppender::",&std::cout); + else + app = new log4cpp::OstreamAppender("ConsoleAppender::",&std::cerr); + + layout->setConversionPattern(pattern); + app->setLayout(layout); + logger->setAppender(*app); + } + + void + logger_add_file_appender(logger_ptr logger, std::string filename, + bool append, std::string pattern) + { + log4cpp::PatternLayout* layout = new log4cpp::PatternLayout(); + log4cpp::Appender* app = new + log4cpp::FileAppender("FileAppender::"+filename, + filename); + layout->setConversionPattern(pattern); + app->setLayout(layout); + logger->setAppender(app); + } + + void + logger_add_rollingfile_appender(logger_ptr logger, std::string filename, + size_t filesize, int bkup_index, bool append, + mode_t mode, std::string pattern) + { + log4cpp::PatternLayout* layout = new log4cpp::PatternLayout(); + log4cpp::Appender* app = new + log4cpp::RollingFileAppender("RollFileAppender::" + filename, filename, + filesize, bkup_index, append, mode); + layout->setConversionPattern(pattern); + app->setLayout(layout); + logger->setAppender(app); + } + + std::vector<std::string> + logger_get_logger_names(void) + { + std::vector<std::string> names; + std::vector<log4cpp::Category*> *loggers = log4cpp::Category::getCurrentCategories(); + std::vector<log4cpp::Category*>::iterator logger = loggers->begin(); + + for(;logger!=loggers->end();logger++) { + names.push_back((*logger)->getName()); + } + return names; + } + +} /* namespace gr */ + +#endif /* HAVE_LOG4CPP */ + +/****** Start Methods to provide Python the capabilities of the macros ********/ +void +gr_logger_config(const std::string config_filename, unsigned int watch_period) +{ + GR_CONFIG_AND_WATCH_LOGGER(config_filename, watch_period); +} + +std::vector<std::string> +gr_logger_get_logger_names(void) +{ + std::vector<std::string> names; + GR_GET_LOGGER_NAMES(names); + return names; +} + +void +gr_logger_reset_config(void) +{ + GR_RESET_CONFIGURATION(); +} + +// Remaining capability provided by gr::logger class in gnuradio/logger.h + +#endif /* ENABLE_GR_LOGGER */ diff --git a/gnuradio-runtime/lib/malloc16.h b/gnuradio-runtime/lib/malloc16.h index 90d1eca77a..05f80cbf4f 100644 --- a/gnuradio-runtime/lib/malloc16.h +++ b/gnuradio-runtime/lib/malloc16.h @@ -20,7 +20,7 @@ * Boston, MA 02110-1301, USA. */ -#include <gr_runtime_api.h> +#include <gnuradio/api.h> #ifdef __cplusplus extern "C" { diff --git a/gnuradio-runtime/lib/math/CMakeLists.txt b/gnuradio-runtime/lib/math/CMakeLists.txt new file mode 100644 index 0000000000..c95c84cecb --- /dev/null +++ b/gnuradio-runtime/lib/math/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright 2010,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +# This file included, use CMake directory variables +######################################################################## + +list(APPEND gnuradio_runtime_sources + ${CMAKE_CURRENT_SOURCE_DIR}/fast_atan2f.cc + ${CMAKE_CURRENT_SOURCE_DIR}/fxpt.cc + ${CMAKE_CURRENT_SOURCE_DIR}/random.cc + ${CMAKE_CURRENT_SOURCE_DIR}/sincos.cc +) diff --git a/gnuradio-runtime/lib/math/fast_atan2f.cc b/gnuradio-runtime/lib/math/fast_atan2f.cc new file mode 100644 index 0000000000..3555cf50ec --- /dev/null +++ b/gnuradio-runtime/lib/math/fast_atan2f.cc @@ -0,0 +1,202 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <gnuradio/math.h> // declaration is in here +#include <cmath> + +namespace gr { + + /***************************************************************************/ + /* Constant definitions */ + /***************************************************************************/ + + #define TAN_MAP_RES 0.003921569 /* (smallest non-zero value in table) */ + #define RAD_PER_DEG 0.017453293 + #define TAN_MAP_SIZE 256 + + /* arctangents from 0 to pi/4 radians */ + static float + fast_atan_table[257] = { + 0.000000e+00, 3.921549e-03, 7.842976e-03, 1.176416e-02, + 1.568499e-02, 1.960533e-02, 2.352507e-02, 2.744409e-02, + 3.136226e-02, 3.527947e-02, 3.919560e-02, 4.311053e-02, + 4.702413e-02, 5.093629e-02, 5.484690e-02, 5.875582e-02, + 6.266295e-02, 6.656816e-02, 7.047134e-02, 7.437238e-02, + 7.827114e-02, 8.216752e-02, 8.606141e-02, 8.995267e-02, + 9.384121e-02, 9.772691e-02, 1.016096e-01, 1.054893e-01, + 1.093658e-01, 1.132390e-01, 1.171087e-01, 1.209750e-01, + 1.248376e-01, 1.286965e-01, 1.325515e-01, 1.364026e-01, + 1.402496e-01, 1.440924e-01, 1.479310e-01, 1.517652e-01, + 1.555948e-01, 1.594199e-01, 1.632403e-01, 1.670559e-01, + 1.708665e-01, 1.746722e-01, 1.784728e-01, 1.822681e-01, + 1.860582e-01, 1.898428e-01, 1.936220e-01, 1.973956e-01, + 2.011634e-01, 2.049255e-01, 2.086818e-01, 2.124320e-01, + 2.161762e-01, 2.199143e-01, 2.236461e-01, 2.273716e-01, + 2.310907e-01, 2.348033e-01, 2.385093e-01, 2.422086e-01, + 2.459012e-01, 2.495869e-01, 2.532658e-01, 2.569376e-01, + 2.606024e-01, 2.642600e-01, 2.679104e-01, 2.715535e-01, + 2.751892e-01, 2.788175e-01, 2.824383e-01, 2.860514e-01, + 2.896569e-01, 2.932547e-01, 2.968447e-01, 3.004268e-01, + 3.040009e-01, 3.075671e-01, 3.111252e-01, 3.146752e-01, + 3.182170e-01, 3.217506e-01, 3.252758e-01, 3.287927e-01, + 3.323012e-01, 3.358012e-01, 3.392926e-01, 3.427755e-01, + 3.462497e-01, 3.497153e-01, 3.531721e-01, 3.566201e-01, + 3.600593e-01, 3.634896e-01, 3.669110e-01, 3.703234e-01, + 3.737268e-01, 3.771211e-01, 3.805064e-01, 3.838825e-01, + 3.872494e-01, 3.906070e-01, 3.939555e-01, 3.972946e-01, + 4.006244e-01, 4.039448e-01, 4.072558e-01, 4.105574e-01, + 4.138496e-01, 4.171322e-01, 4.204054e-01, 4.236689e-01, + 4.269229e-01, 4.301673e-01, 4.334021e-01, 4.366272e-01, + 4.398426e-01, 4.430483e-01, 4.462443e-01, 4.494306e-01, + 4.526070e-01, 4.557738e-01, 4.589307e-01, 4.620778e-01, + 4.652150e-01, 4.683424e-01, 4.714600e-01, 4.745676e-01, + 4.776654e-01, 4.807532e-01, 4.838312e-01, 4.868992e-01, + 4.899573e-01, 4.930055e-01, 4.960437e-01, 4.990719e-01, + 5.020902e-01, 5.050985e-01, 5.080968e-01, 5.110852e-01, + 5.140636e-01, 5.170320e-01, 5.199904e-01, 5.229388e-01, + 5.258772e-01, 5.288056e-01, 5.317241e-01, 5.346325e-01, + 5.375310e-01, 5.404195e-01, 5.432980e-01, 5.461666e-01, + 5.490251e-01, 5.518738e-01, 5.547124e-01, 5.575411e-01, + 5.603599e-01, 5.631687e-01, 5.659676e-01, 5.687566e-01, + 5.715357e-01, 5.743048e-01, 5.770641e-01, 5.798135e-01, + 5.825531e-01, 5.852828e-01, 5.880026e-01, 5.907126e-01, + 5.934128e-01, 5.961032e-01, 5.987839e-01, 6.014547e-01, + 6.041158e-01, 6.067672e-01, 6.094088e-01, 6.120407e-01, + 6.146630e-01, 6.172755e-01, 6.198784e-01, 6.224717e-01, + 6.250554e-01, 6.276294e-01, 6.301939e-01, 6.327488e-01, + 6.352942e-01, 6.378301e-01, 6.403565e-01, 6.428734e-01, + 6.453808e-01, 6.478788e-01, 6.503674e-01, 6.528466e-01, + 6.553165e-01, 6.577770e-01, 6.602282e-01, 6.626701e-01, + 6.651027e-01, 6.675261e-01, 6.699402e-01, 6.723452e-01, + 6.747409e-01, 6.771276e-01, 6.795051e-01, 6.818735e-01, + 6.842328e-01, 6.865831e-01, 6.889244e-01, 6.912567e-01, + 6.935800e-01, 6.958943e-01, 6.981998e-01, 7.004964e-01, + 7.027841e-01, 7.050630e-01, 7.073330e-01, 7.095943e-01, + 7.118469e-01, 7.140907e-01, 7.163258e-01, 7.185523e-01, + 7.207701e-01, 7.229794e-01, 7.251800e-01, 7.273721e-01, + 7.295557e-01, 7.317307e-01, 7.338974e-01, 7.360555e-01, + 7.382053e-01, 7.403467e-01, 7.424797e-01, 7.446045e-01, + 7.467209e-01, 7.488291e-01, 7.509291e-01, 7.530208e-01, + 7.551044e-01, 7.571798e-01, 7.592472e-01, 7.613064e-01, + 7.633576e-01, 7.654008e-01, 7.674360e-01, 7.694633e-01, + 7.714826e-01, 7.734940e-01, 7.754975e-01, 7.774932e-01, + 7.794811e-01, 7.814612e-01, 7.834335e-01, 7.853983e-01, + 7.853983e-01 + }; + + + /***************************************************************************** + Function: Arc tangent + + Syntax: angle = fast_atan2(y, x); + float y y component of input vector + float x x component of input vector + float angle angle of vector (x, y) in radians + + Description: This function calculates the angle of the vector (x,y) + based on a table lookup and linear interpolation. The table uses a + 256 point table covering -45 to +45 degrees and uses symetry to + determine the final angle value in the range of -180 to 180 + degrees. Note that this function uses the small angle approximation + for values close to zero. This routine calculates the arc tangent + with an average error of +/- 0.045 degrees. + *****************************************************************************/ + + float + fast_atan2f(float y, float x) + { + float x_abs, y_abs, z; + float alpha, angle, base_angle; + int index; + + /* don't divide by zero! */ // FIXME could get hosed with -0.0 + if((y == 0.0) && (x == 0.0)) + return 0.0; + + /* normalize to +/- 45 degree range */ + y_abs = fabsf(y); + x_abs = fabsf(x); + //z = (y_abs < x_abs ? y_abs / x_abs : x_abs / y_abs); + if(y_abs < x_abs) + z = y_abs / x_abs; + else + z = x_abs / y_abs; + + /* when ratio approaches the table resolution, the angle is */ + /* best approximated with the argument itself... */ + if(z < TAN_MAP_RES) + base_angle = z; + else { + /* find index and interpolation value */ + alpha = z * (float)TAN_MAP_SIZE - .5; + index = (int)alpha; + alpha -= (float)index; + /* determine base angle based on quadrant and */ + /* add or subtract table value from base angle based on quadrant */ + base_angle = fast_atan_table[index]; + base_angle += + (fast_atan_table[index + 1] - fast_atan_table[index]) * alpha; + } + + if(x_abs > y_abs) { /* -45 -> 45 or 135 -> 225 */ + if(x >= 0.0) { /* -45 -> 45 */ + if(y >= 0.0) + angle = base_angle; /* 0 -> 45, angle OK */ + else + angle = -base_angle; /* -45 -> 0, angle = -angle */ + } + else { /* 135 -> 180 or 180 -> -135 */ + angle = 3.14159265358979323846; + if(y >= 0.0) + angle -= base_angle; /* 135 -> 180, angle = 180 - angle */ + else + angle = base_angle - angle; /* 180 -> -135, angle = angle - 180 */ + } + } + else { /* 45 -> 135 or -135 -> -45 */ + if(y >= 0.0) { /* 45 -> 135 */ + angle = 1.57079632679489661923; + if(x >= 0.0) + angle -= base_angle; /* 45 -> 90, angle = 90 - angle */ + else + angle += base_angle; /* 90 -> 135, angle = 90 + angle */ + } + else { /* -135 -> -45 */ + angle = -1.57079632679489661923; + if(x >= 0.0) + angle += base_angle; /* -90 -> -45, angle = -90 + angle */ + else + angle -= base_angle; /* -135 -> -90, angle = -90 - angle */ + } + } + + #ifdef ZERO_TO_TWOPI + if (angle < 0) + return (angle + TWOPI); + else + return (angle); + #else + return (angle); + #endif + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/gr_fxpt.cc b/gnuradio-runtime/lib/math/fxpt.cc index 2ea8520e6b..23fdda1241 100644 --- a/gnuradio-runtime/lib/gr_fxpt.cc +++ b/gnuradio-runtime/lib/math/fxpt.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -24,12 +24,15 @@ #include "config.h" #endif -#include <gr_fxpt.h> +#include <gnuradio/fxpt.h> -const float gr_fxpt::s_sine_table[1 << NBITS][2] = { -#include "sine_table.h" -}; +namespace gr { -const float gr_fxpt::PI = 3.14159265358979323846; -const float gr_fxpt::TWO_TO_THE_31 = 2147483648.0; + const float fxpt::s_sine_table[1 << NBITS][2] = { + #include "sine_table.h" + }; + const float fxpt::PI = 3.14159265358979323846; + const float fxpt::TWO_TO_THE_31 = 2147483648.0; + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/gen_sine_table.py b/gnuradio-runtime/lib/math/gen_sine_table.py index d7d11eff11..d7d11eff11 100755 --- a/gnuradio-runtime/lib/gen_sine_table.py +++ b/gnuradio-runtime/lib/math/gen_sine_table.py diff --git a/gnuradio-runtime/lib/math/qa_fxpt.cc b/gnuradio-runtime/lib/math/qa_fxpt.cc new file mode 100644 index 0000000000..d368e7de82 --- /dev/null +++ b/gnuradio-runtime/lib/math/qa_fxpt.cc @@ -0,0 +1,102 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qa_fxpt.h> +#include <gnuradio/fxpt.h> +#include <cppunit/TestAssert.h> +#include <iostream> +#include <stdio.h> +#include <unistd.h> +#include <math.h> + +static const float SIN_COS_TOLERANCE = 1e-5; + +void +qa_fxpt::t0() +{ + CPPUNIT_ASSERT_DOUBLES_EQUAL(M_PI/2, gr::fxpt::fixed_to_float(0x40000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, gr::fxpt::fixed_to_float(0x00000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-M_PI, gr::fxpt::fixed_to_float(0x80000000), SIN_COS_TOLERANCE); + + if(0) { + /* + * These are disabled because of some precision issues. + * + * Different compilers seem to have different opinions on whether + * the calulations are done single or double (or extended) + * precision. Any of the answers are fine for our real purpose, but + * sometimes the answer is off by a few bits at the bottom. + * Hence, the disabled check. + */ + CPPUNIT_ASSERT_EQUAL((gr_int32)0x40000000, gr::fxpt::float_to_fixed(M_PI/2)); + CPPUNIT_ASSERT_EQUAL((gr_int32)0, gr::fxpt::float_to_fixed(0)); + CPPUNIT_ASSERT_EQUAL((gr_int32)0x80000000, gr::fxpt::float_to_fixed(-M_PI)); + } +} + +void +qa_fxpt::t1() +{ + CPPUNIT_ASSERT_DOUBLES_EQUAL( 0, gr::fxpt::sin(0x00000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.707106781, gr::fxpt::sin(0x20000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL( 1, gr::fxpt::sin(0x40000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL( 0.707106781, gr::fxpt::sin(0x60000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL( 0, gr::fxpt::sin(0x7fffffff), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL( 0, gr::fxpt::sin(0x80000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL( 0, gr::fxpt::sin(0x80000001), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-1, gr::fxpt::sin(-0x40000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL(-0.707106781, gr::fxpt::sin(-0x20000000), SIN_COS_TOLERANCE); + + for(float p = -M_PI; p < M_PI; p += 2 * M_PI / 3600) { + float expected = sin(p); + float actual = gr::fxpt::sin(gr::fxpt::float_to_fixed (p)); + CPPUNIT_ASSERT_DOUBLES_EQUAL(expected, actual, SIN_COS_TOLERANCE); + } +} + +void +qa_fxpt::t2() +{ + for(float p = -M_PI; p < M_PI; p += 2 * M_PI / 3600) { + float expected = cos(p); + float actual = gr::fxpt::cos(gr::fxpt::float_to_fixed(p)); + CPPUNIT_ASSERT_DOUBLES_EQUAL(expected, actual, SIN_COS_TOLERANCE); + } +} + +void +qa_fxpt::t3() +{ + for(float p = -M_PI; p < M_PI; p += 2 * M_PI / 3600) { + float expected_sin = sin(p); + float expected_cos = cos(p); + float actual_sin; + float actual_cos; + gr::fxpt::sincos(gr::fxpt::float_to_fixed (p), &actual_sin, &actual_cos); + CPPUNIT_ASSERT_DOUBLES_EQUAL(expected_sin, actual_sin, SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL(expected_cos, actual_cos, SIN_COS_TOLERANCE); + } +} diff --git a/gnuradio-runtime/lib/qa_gr_fxpt.h b/gnuradio-runtime/lib/math/qa_fxpt.h index 72211563e7..58a6f02d1b 100644 --- a/gnuradio-runtime/lib/qa_gr_fxpt.h +++ b/gnuradio-runtime/lib/math/qa_fxpt.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -19,28 +19,27 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ + #ifndef INCLUDED_QA_GR_FXPT_H #define INCLUDED_QA_GR_FXPT_H - #include <cppunit/extensions/HelperMacros.h> #include <cppunit/TestCase.h> -class qa_gr_fxpt : public CppUnit::TestCase { - - CPPUNIT_TEST_SUITE (qa_gr_fxpt); - CPPUNIT_TEST (t0); - CPPUNIT_TEST (t1); - CPPUNIT_TEST (t2); - CPPUNIT_TEST (t3); - CPPUNIT_TEST_SUITE_END (); +class qa_fxpt : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(qa_fxpt); + CPPUNIT_TEST(t0); + CPPUNIT_TEST(t1); + CPPUNIT_TEST(t2); + CPPUNIT_TEST(t3); + CPPUNIT_TEST_SUITE_END(); private: - void t0 (); - void t1 (); - void t2 (); - void t3 (); - + void t0(); + void t1(); + void t2(); + void t3(); }; #endif /* INCLUDED_QA_GR_FXPT_H */ diff --git a/gnuradio-runtime/lib/qa_gr_fxpt_nco.cc b/gnuradio-runtime/lib/math/qa_fxpt_nco.cc index 6f208eac80..cf229d68be 100644 --- a/gnuradio-runtime/lib/qa_gr_fxpt_nco.cc +++ b/gnuradio-runtime/lib/math/qa_fxpt_nco.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -23,9 +23,10 @@ #ifdef HAVE_CONFIG_H #include <config.h> #endif -#include <qa_gr_fxpt_nco.h> -#include <gr_fxpt_nco.h> -#include <gr_nco.h> + +#include <qa_fxpt_nco.h> +#include <gnuradio/fxpt_nco.h> +#include <gnuradio/nco.h> #include <cppunit/TestAssert.h> #include <iostream> #include <stdio.h> @@ -45,59 +46,59 @@ static double max_d(double a, double b) } void -qa_gr_fxpt_nco::t0 () +qa_fxpt_nco::t0() { - gr_nco<float,float> ref_nco; - gr_fxpt_nco new_nco; + gr::nco<float,float> ref_nco; + gr::fxpt_nco new_nco; double max_error = 0, max_phase_error = 0; - ref_nco.set_freq ((float)(2 * M_PI / SIN_COS_FREQ)); - new_nco.set_freq ((float)(2 * M_PI / SIN_COS_FREQ)); + ref_nco.set_freq((float)(2 * M_PI / SIN_COS_FREQ)); + new_nco.set_freq((float)(2 * M_PI / SIN_COS_FREQ)); - CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_nco.get_freq(), new_nco.get_freq(), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL(ref_nco.get_freq(), new_nco.get_freq(), SIN_COS_TOLERANCE); - for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){ - float ref_sin = ref_nco.sin (); - float new_sin = new_nco.sin (); + for(int i = 0; i < SIN_COS_BLOCK_SIZE; i++) { + float ref_sin = ref_nco.sin(); + float new_sin = new_nco.sin(); //printf ("i = %6d\n", i); - CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_sin, new_sin, SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL(ref_sin, new_sin, SIN_COS_TOLERANCE); - max_error = max_d (max_error, ref_sin-new_sin); + max_error = max_d(max_error, ref_sin-new_sin); - float ref_cos = ref_nco.cos (); - float new_cos = new_nco.cos (); - CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_cos, new_cos, SIN_COS_TOLERANCE); + float ref_cos = ref_nco.cos(); + float new_cos = new_nco.cos(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(ref_cos, new_cos, SIN_COS_TOLERANCE); - max_error = max_d (max_error, ref_cos-new_cos); + max_error = max_d(max_error, ref_cos-new_cos); - ref_nco.step (); - new_nco.step (); + ref_nco.step(); + new_nco.step(); - CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_nco.get_phase(), new_nco.get_phase(), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL(ref_nco.get_phase(), new_nco.get_phase(), SIN_COS_TOLERANCE); - max_phase_error = max_d (max_phase_error, ref_nco.get_phase()-new_nco.get_phase()); + max_phase_error = max_d(max_phase_error, ref_nco.get_phase()-new_nco.get_phase()); } // printf ("Fxpt max error %.9f, max phase error %.9f\n", max_error, max_phase_error); } void -qa_gr_fxpt_nco::t1 () +qa_fxpt_nco::t1() { - gr_nco<float,float> ref_nco; - gr_fxpt_nco new_nco; + gr::nco<float,float> ref_nco; + gr::fxpt_nco new_nco; gr_complex ref_block[SIN_COS_BLOCK_SIZE]; gr_complex new_block[SIN_COS_BLOCK_SIZE]; double max_error = 0; - ref_nco.set_freq ((float)(2 * M_PI / SIN_COS_FREQ)); - new_nco.set_freq ((float)(2 * M_PI / SIN_COS_FREQ)); + ref_nco.set_freq((float)(2 * M_PI / SIN_COS_FREQ)); + new_nco.set_freq((float)(2 * M_PI / SIN_COS_FREQ)); - CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_nco.get_freq(), new_nco.get_freq(), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL(ref_nco.get_freq(), new_nco.get_freq(), SIN_COS_TOLERANCE); - ref_nco.sincos ((gr_complex*)ref_block, SIN_COS_BLOCK_SIZE); - new_nco.sincos ((gr_complex*)new_block, SIN_COS_BLOCK_SIZE); + ref_nco.sincos((gr_complex*)ref_block, SIN_COS_BLOCK_SIZE); + new_nco.sincos((gr_complex*)new_block, SIN_COS_BLOCK_SIZE); - for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){ + for(int i = 0; i < SIN_COS_BLOCK_SIZE; i++) { CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_block[i].real(), new_block[i].real(), SIN_COS_TOLERANCE); max_error = max_d (max_error, ref_block[i].real()-new_block[i].real()); @@ -109,11 +110,11 @@ qa_gr_fxpt_nco::t1 () } void -qa_gr_fxpt_nco::t2 () +qa_fxpt_nco::t2() { } void -qa_gr_fxpt_nco::t3 () +qa_fxpt_nco::t3() { } diff --git a/gnuradio-runtime/lib/qa_gr_fxpt_nco.h b/gnuradio-runtime/lib/math/qa_fxpt_nco.h index 8998922bbb..1b2cdaede6 100644 --- a/gnuradio-runtime/lib/qa_gr_fxpt_nco.h +++ b/gnuradio-runtime/lib/math/qa_fxpt_nco.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -19,28 +19,27 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ + #ifndef INCLUDED_QA_GR_FXPT_NCO_H #define INCLUDED_QA_GR_FXPT_NCO_H - #include <cppunit/extensions/HelperMacros.h> #include <cppunit/TestCase.h> -class qa_gr_fxpt_nco : public CppUnit::TestCase { - - CPPUNIT_TEST_SUITE (qa_gr_fxpt_nco); - CPPUNIT_TEST (t0); - CPPUNIT_TEST (t1); - CPPUNIT_TEST (t2); - CPPUNIT_TEST (t3); - CPPUNIT_TEST_SUITE_END (); - - private: - void t0 (); - void t1 (); - void t2 (); - void t3 (); - +class qa_fxpt_nco : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(qa_fxpt_nco); + CPPUNIT_TEST(t0); + CPPUNIT_TEST(t1); + CPPUNIT_TEST(t2); + CPPUNIT_TEST(t3); + CPPUNIT_TEST_SUITE_END(); + +private: + void t0(); + void t1(); + void t2(); + void t3(); }; #endif /* INCLUDED_QA_GR_FXPT_NCO_H */ diff --git a/gnuradio-runtime/lib/qa_gr_fxpt_vco.cc b/gnuradio-runtime/lib/math/qa_fxpt_vco.cc index 5b6993a30c..ee9865e926 100644 --- a/gnuradio-runtime/lib/qa_gr_fxpt_vco.cc +++ b/gnuradio-runtime/lib/math/qa_fxpt_vco.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2005 Free Software Foundation, Inc. + * Copyright 2004,2005,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -23,9 +23,10 @@ #ifdef HAVE_CONFIG_H #include <config.h> #endif -#include <qa_gr_fxpt_vco.h> -#include <gr_fxpt_vco.h> -#include <gr_vco.h> + +#include <qa_fxpt_vco.h> +#include <gnuradio/fxpt_vco.h> +#include <vco.h> #include <cppunit/TestAssert.h> #include <iostream> #include <stdio.h> @@ -45,66 +46,65 @@ static double max_d(double a, double b) } void -qa_gr_fxpt_vco::t0 () +qa_fxpt_vco::t0() { - gr_vco<float,float> ref_vco; - gr_fxpt_vco new_vco; + gr::vco<float,float> ref_vco; + gr::fxpt_vco new_vco; double max_error = 0, max_phase_error = 0; float input[SIN_COS_BLOCK_SIZE]; - for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){ - input[i] = sin(double(i)); + for(int i = 0; i < SIN_COS_BLOCK_SIZE; i++) { + input[i] = sin(double(i)); } - for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){ - float ref_cos = ref_vco.cos (); - float new_cos = new_vco.cos (); - CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_cos, new_cos, SIN_COS_TOLERANCE); + for(int i = 0; i < SIN_COS_BLOCK_SIZE; i++) { + float ref_cos = ref_vco.cos(); + float new_cos = new_vco.cos(); + CPPUNIT_ASSERT_DOUBLES_EQUAL(ref_cos, new_cos, SIN_COS_TOLERANCE); - max_error = max_d (max_error, ref_cos-new_cos); + max_error = max_d(max_error, ref_cos-new_cos); - ref_vco.adjust_phase (input[i]); - new_vco.adjust_phase (input[i]); + ref_vco.adjust_phase(input[i]); + new_vco.adjust_phase(input[i]); - CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_vco.get_phase(), new_vco.get_phase(), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL(ref_vco.get_phase(), new_vco.get_phase(), SIN_COS_TOLERANCE); - max_phase_error = max_d (max_phase_error, ref_vco.get_phase()-new_vco.get_phase()); + max_phase_error = max_d(max_phase_error, ref_vco.get_phase()-new_vco.get_phase()); } // printf ("Fxpt max error %.9f, max phase error %.9f\n", max_error, max_phase_error); } - void -qa_gr_fxpt_vco::t1 () +qa_fxpt_vco::t1() { - gr_vco<float,float> ref_vco; - gr_fxpt_vco new_vco; + gr::vco<float,float> ref_vco; + gr::fxpt_vco new_vco; float ref_block[SIN_COS_BLOCK_SIZE]; float new_block[SIN_COS_BLOCK_SIZE]; float input[SIN_COS_BLOCK_SIZE]; double max_error = 0; - for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){ - input[i] = sin(double(i)); + for(int i = 0; i < SIN_COS_BLOCK_SIZE; i++) { + input[i] = sin(double(i)); } - ref_vco.cos (ref_block, input, SIN_COS_BLOCK_SIZE, SIN_COS_K, SIN_COS_AMPL); - new_vco.cos (new_block, input, SIN_COS_BLOCK_SIZE, SIN_COS_K, SIN_COS_AMPL); + ref_vco.cos(ref_block, input, SIN_COS_BLOCK_SIZE, SIN_COS_K, SIN_COS_AMPL); + new_vco.cos(new_block, input, SIN_COS_BLOCK_SIZE, SIN_COS_K, SIN_COS_AMPL); - for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){ - CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_block[i], new_block[i], SIN_COS_TOLERANCE); - max_error = max_d (max_error, ref_block[i]-new_block[i]); + for(int i = 0; i < SIN_COS_BLOCK_SIZE; i++) { + CPPUNIT_ASSERT_DOUBLES_EQUAL(ref_block[i], new_block[i], SIN_COS_TOLERANCE); + max_error = max_d(max_error, ref_block[i]-new_block[i]); } - CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_vco.get_phase(), new_vco.get_phase(), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL(ref_vco.get_phase(), new_vco.get_phase(), SIN_COS_TOLERANCE); // printf ("Fxpt max error %.9f, max phase error %.9f\n", max_error, ref_vco.get_phase()-new_vco.get_phase()); } void -qa_gr_fxpt_vco::t2 () +qa_fxpt_vco::t2() { } void -qa_gr_fxpt_vco::t3 () +qa_fxpt_vco::t3() { } diff --git a/gnuradio-runtime/lib/qa_gr_fxpt_vco.h b/gnuradio-runtime/lib/math/qa_fxpt_vco.h index fab8022e36..72693f32e2 100644 --- a/gnuradio-runtime/lib/qa_gr_fxpt_vco.h +++ b/gnuradio-runtime/lib/math/qa_fxpt_vco.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2005 Free Software Foundation, Inc. + * Copyright 2004,2005,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -19,28 +19,27 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ + #ifndef INCLUDED_QA_GR_FXPT_VCO_H #define INCLUDED_QA_GR_FXPT_VCO_H - #include <cppunit/extensions/HelperMacros.h> #include <cppunit/TestCase.h> -class qa_gr_fxpt_vco : public CppUnit::TestCase { - - CPPUNIT_TEST_SUITE (qa_gr_fxpt_vco); - CPPUNIT_TEST (t0); - CPPUNIT_TEST (t1); - CPPUNIT_TEST (t2); - CPPUNIT_TEST (t3); - CPPUNIT_TEST_SUITE_END (); - - private: - void t0 (); - void t1 (); - void t2 (); - void t3 (); - +class qa_fxpt_vco : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(qa_fxpt_vco); + CPPUNIT_TEST(t0); + CPPUNIT_TEST(t1); + CPPUNIT_TEST(t2); + CPPUNIT_TEST(t3); + CPPUNIT_TEST_SUITE_END(); + +private: + void t0(); + void t1(); + void t2(); + void t3(); }; #endif /* INCLUDED_QA_GR_FXPT_VCO_H */ diff --git a/gnuradio-runtime/lib/qa_gr_math.cc b/gnuradio-runtime/lib/math/qa_math.cc index 74d51b536e..1fb43cc67f 100644 --- a/gnuradio-runtime/lib/qa_gr_math.cc +++ b/gnuradio-runtime/lib/math/qa_math.cc @@ -19,21 +19,21 @@ * Boston, MA 02110-1301, USA. */ -#include <gr_math.h> -#include <qa_gr_math.h> +#include <gnuradio/math.h> +#include <qa_math.h> #include <cppunit/TestAssert.h> #include <stdio.h> void -qa_gr_math::test_binary_slicer1 () +qa_math::test_binary_slicer1() { float x[5] = {-1, -0.5, 0, 0.5, 1.0}; unsigned int z[5] = {0, 0, 1, 1, 1}; unsigned int y; //printf("\nBinary\n"); - for (unsigned int i = 0; i < 5; i++) { - y = gr_binary_slicer(x[i]); + for(unsigned int i = 0; i < 5; i++) { + y = gr::binary_slicer(x[i]); //printf("in: %f out: %d desired: %d\n", x[i], y, z[i]); CPPUNIT_ASSERT_DOUBLES_EQUAL(y, z[i], 1e-9); @@ -41,7 +41,7 @@ qa_gr_math::test_binary_slicer1 () //printf("\nBranchless Binary\n"); for (unsigned int i = 0; i < 5; i++) { - y = gr_branchless_binary_slicer(x[i]); + y = gr::branchless_binary_slicer(x[i]); //printf("in: %f out: %d desired: %d\n", x[i], y, z[i]); CPPUNIT_ASSERT_DOUBLES_EQUAL(y, z[i], 1e-9); @@ -49,7 +49,7 @@ qa_gr_math::test_binary_slicer1 () } void -qa_gr_math::test_quad_0deg_slicer1 () +qa_math::test_quad_0deg_slicer1() { gr_complex x[4] = {gr_complex(1, 0), gr_complex(0, 1), @@ -61,7 +61,7 @@ qa_gr_math::test_quad_0deg_slicer1 () //printf("\nQuad0\n"); for (unsigned int i = 0; i < 4; i++) { - y = gr_quad_0deg_slicer(x[i]); + y = gr::quad_0deg_slicer(x[i]); //printf("in: %.4f+j%.4f out: %d desired: %d\n", x[i].real(), x[i].imag(), y, z[i]); CPPUNIT_ASSERT_DOUBLES_EQUAL(y, z[i], 1e-9); @@ -69,7 +69,7 @@ qa_gr_math::test_quad_0deg_slicer1 () //printf("\nBranchless Quad0\n"); for (unsigned int i = 0; i < 4; i++) { - y = gr_branchless_quad_0deg_slicer(x[i]); + y = gr::branchless_quad_0deg_slicer(x[i]); //printf("in: %.4f+j%.4f out: %d desired: %d\n", x[i].real(), x[i].imag(), y, z[i]); CPPUNIT_ASSERT_DOUBLES_EQUAL(y, z[i], 1e-9); @@ -77,7 +77,7 @@ qa_gr_math::test_quad_0deg_slicer1 () } void -qa_gr_math::test_quad_45deg_slicer1 () +qa_math::test_quad_45deg_slicer1() { gr_complex x[4] = {gr_complex(0.707, 0.707), gr_complex(-0.707, 0.707), @@ -89,7 +89,7 @@ qa_gr_math::test_quad_45deg_slicer1 () //printf("\nQuad45\n"); for (unsigned int i = 0; i < 4; i++) { - y = gr_quad_45deg_slicer(x[i]); + y = gr::quad_45deg_slicer(x[i]); //printf("in: %.4f+j%.4f out: %d desired: %d\n", x[i].real(), x[i].imag(), y, z[i]); CPPUNIT_ASSERT_DOUBLES_EQUAL(y, z[i], 1e-9); @@ -97,7 +97,7 @@ qa_gr_math::test_quad_45deg_slicer1 () //printf("\nBranchless Quad45\n"); for (unsigned int i = 0; i < 4; i++) { - y = gr_branchless_quad_45deg_slicer(x[i]); + y = gr::branchless_quad_45deg_slicer(x[i]); //printf("in: %.4f+j%.4f out: %d desired: %d\n", x[i].real(), x[i].imag(), y, z[i]); CPPUNIT_ASSERT_DOUBLES_EQUAL(y, z[i], 1e-9); diff --git a/gnuradio-runtime/lib/qa_gr_math.h b/gnuradio-runtime/lib/math/qa_math.h index 86858c03d5..3621283b37 100644 --- a/gnuradio-runtime/lib/qa_gr_math.h +++ b/gnuradio-runtime/lib/math/qa_math.h @@ -25,9 +25,9 @@ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/TestCase.h> -class qa_gr_math : public CppUnit::TestCase { - - CPPUNIT_TEST_SUITE(qa_gr_math); +class qa_math : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(qa_math); CPPUNIT_TEST(test_binary_slicer1); CPPUNIT_TEST(test_quad_0deg_slicer1); CPPUNIT_TEST(test_quad_45deg_slicer1); diff --git a/gnuradio-runtime/lib/qa_sincos.cc b/gnuradio-runtime/lib/math/qa_sincos.cc index be163117de..7def8a9bb8 100644 --- a/gnuradio-runtime/lib/qa_sincos.cc +++ b/gnuradio-runtime/lib/math/qa_sincos.cc @@ -25,8 +25,7 @@ #endif #include <qa_sincos.h> -#include <gr_sincos.h> -#include <attributes.h> +#include <gnuradio/sincos.h> #include <cppunit/TestAssert.h> #include <cmath> @@ -42,7 +41,7 @@ qa_sincos::t1() c_sin = sin(x); c_cos = cos(x); - gr_sincos(x, &gr_sin, &gr_cos); + gr::sincos(x, &gr_sin, &gr_cos); CPPUNIT_ASSERT_DOUBLES_EQUAL(c_sin, gr_sin, 0.0001); CPPUNIT_ASSERT_DOUBLES_EQUAL(c_cos, gr_cos, 0.0001); @@ -61,7 +60,7 @@ qa_sincos::t2() c_sin = sinf(x); c_cos = cosf(x); - gr_sincosf(x, &gr_sin, &gr_cos); + gr::sincosf(x, &gr_sin, &gr_cos); CPPUNIT_ASSERT_DOUBLES_EQUAL(c_sin, gr_sin, 0.0001); CPPUNIT_ASSERT_DOUBLES_EQUAL(c_cos, gr_cos, 0.0001); diff --git a/gnuradio-runtime/lib/qa_sincos.h b/gnuradio-runtime/lib/math/qa_sincos.h index c54b75f97f..c54b75f97f 100644 --- a/gnuradio-runtime/lib/qa_sincos.h +++ b/gnuradio-runtime/lib/math/qa_sincos.h diff --git a/gnuradio-runtime/lib/math/random.cc b/gnuradio-runtime/lib/math/random.cc new file mode 100644 index 0000000000..7170f27edf --- /dev/null +++ b/gnuradio-runtime/lib/math/random.cc @@ -0,0 +1,188 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* + * Copyright 1997 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <math.h> +#include <gnuradio/random.h> + +namespace gr { + +#define IA 16807 +#define IM 2147483647 +#define AM (1.0/IM) +#define IQ 127773 +#define IR 2836 +#define NDIV (1+(IM-1)/NTAB) +#define EPS 1.2e-7 +#define RNMX (1.0-EPS) + + random::random(long seed) + { + reseed(seed); + } + + void + random::reseed(long seed) + { + d_seed = seed; + d_iy = 0; + for(int i = 0; i < NTAB; i++) + d_iv[i] = 0; + d_iset = 0; + d_gset = 0; + } + + /* + * This looks like it returns a uniform random deviate between 0.0 and 1.0 + * It looks similar to code from "Numerical Recipes in C". + */ + float + random::ran1() + { + int j; + long k; + float temp; + + if(d_seed <= 0 || !d_iy) { + if(-d_seed < 1) + d_seed=1; + else + d_seed = -d_seed; + for(j=NTAB+7;j>=0;j--) { + k=d_seed/IQ; + d_seed=IA*(d_seed-k*IQ)-IR*k; + if(d_seed < 0) + d_seed += IM; + if(j < NTAB) + d_iv[j] = d_seed; + } + d_iy=d_iv[0]; + } + k=(d_seed)/IQ; + d_seed=IA*(d_seed-k*IQ)-IR*k; + if(d_seed < 0) + d_seed += IM; + j=d_iy/NDIV; + d_iy=d_iv[j]; + d_iv[j] = d_seed; + temp=AM * d_iy; + if(temp > RNMX) + temp = RNMX; + return temp; + } + + /* + * Returns a normally distributed deviate with zero mean and variance 1. + * Also looks like it's from "Numerical Recipes in C". + */ + float + random::gasdev() + { + float fac,rsq,v1,v2; + d_iset = 1 - d_iset; + if(d_iset) { + do { + v1=2.0*ran1()-1.0; + v2=2.0*ran1()-1.0; + rsq=v1*v1+v2*v2; + } while(rsq >= 1.0 || rsq == 0.0); + fac= sqrt(-2.0*log(rsq)/rsq); + d_gset=v1*fac; + return v2*fac; + } + return d_gset; + } + + /* + * Copied from The KC7WW / OH2BNS Channel Simulator + * FIXME Need to check how good this is at some point + */ + float + random::laplacian() + { + float z = ran1(); + if(z < 0.5) + return log(2.0 * z) / M_SQRT2; + else + return -log(2.0 * (1.0 - z)) / M_SQRT2; + } + + /* + * Copied from The KC7WW / OH2BNS Channel Simulator + * FIXME Need to check how good this is at some point + */ + // 5 => scratchy, 8 => Geiger + float + random::impulse(float factor = 5) + { + float z = -M_SQRT2 * log(ran1()); + if(fabsf(z) <= factor) + return 0.0; + else + return z; + } + + /* + * Complex rayleigh is really gaussian I and gaussian Q + * It can also be generated by real rayleigh magnitude and + * uniform random angle + * Adapted from The KC7WW / OH2BNS Channel Simulator + * FIXME Need to check how good this is at some point + */ + gr_complex + random::rayleigh_complex() + { + return gr_complex(gasdev(),gasdev()); + } + + /* Other option + mag = rayleigh(); + ang = 2.0 * M_PI * RNG(); + *Rx = rxx * cos(z); + *Iy = rxx * sin(z); + */ + + float + random::rayleigh() + { + return sqrt(-2.0 * log(ran1())); + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/gr_sincos.c b/gnuradio-runtime/lib/math/sincos.cc index a8d01b0da4..49a90d2128 100644 --- a/gnuradio-runtime/lib/gr_sincos.c +++ b/gnuradio-runtime/lib/math/sincos.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2010 Free Software Foundation, Inc. + * Copyright 2004,2010,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -28,56 +28,58 @@ #define _GNU_SOURCE // ask for GNU extensions if available #endif -#include <gr_sincos.h> +#include <gnuradio/sincos.h> #include <math.h> -// ---------------------------------------------------------------- +namespace gr { #if defined (HAVE_SINCOS) -void -gr_sincos (double x, double *sinx, double *cosx) -{ - sincos (x, sinx, cosx); -} + void + sincos(double x, double *sinx, double *cosx) + { + ::sincos(x, sinx, cosx); + } #else -void -gr_sincos (double x, double *sinx, double *cosx) -{ - *sinx = sin (x); - *cosx = cos (x); -} + void + sincos(double x, double *sinx, double *cosx) + { + *sinx = ::sin(x); + *cosx = ::cos(x); + } #endif -// ---------------------------------------------------------------- + // ---------------------------------------------------------------- #if defined (HAVE_SINCOSF) -void -gr_sincosf (float x, float *sinx, float *cosx) -{ - sincosf (x, sinx, cosx); -} + void + sincosf(float x, float *sinx, float *cosx) + { + ::sincosf(x, sinx, cosx); + } #elif defined (HAVE_SINF) && defined (HAVE_COSF) -void -gr_sincosf (float x, float *sinx, float *cosx) -{ - *sinx = sinf (x); - *cosx = cosf (x); -} + void + sincosf(float x, float *sinx, float *cosx) + { + *sinx = ::sinf(x); + *cosx = ::cosf(x); + } #else -void -gr_sincosf (float x, float *sinx, float *cosx) -{ - *sinx = sin (x); - *cosx = cos (x); -} + void + sincosf(float x, float *sinx, float *cosx) + { + *sinx = ::sin(x); + *cosx = ::cos(x); + } #endif + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/sine_table.h b/gnuradio-runtime/lib/math/sine_table.h index 69834943bc..69834943bc 100644 --- a/gnuradio-runtime/lib/sine_table.h +++ b/gnuradio-runtime/lib/math/sine_table.h diff --git a/gnuradio-runtime/lib/math/vco.h b/gnuradio-runtime/lib/math/vco.h new file mode 100644 index 0000000000..fa11732c1f --- /dev/null +++ b/gnuradio-runtime/lib/math/vco.h @@ -0,0 +1,99 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef _GR_VCO_H_ +#define _GR_VCO_H_ + +#include <gnuradio/sincos.h> +#include <gnuradio/gr_complex.h> +#include <vector> +#include <cmath> + +namespace gr { + + /*! + * \brief base class template for Voltage Controlled Oscillator (VCO) + * \ingroup misc + */ + template<class o_type, class i_type> + class vco + { + public: + vco() : d_phase(0) {} + + virtual ~vco() {} + + // radians + void set_phase(double angle) { + d_phase = angle; + } + + void adjust_phase(double delta_phase) { + d_phase += delta_phase; + if(fabs (d_phase) > M_PI){ + + while(d_phase > M_PI) + d_phase -= 2*M_PI; + + while(d_phase < -M_PI) + d_phase += 2*M_PI; + } + } + + double get_phase() const { return d_phase; } + + // compute sin and cos for current phase angle + void sincos(float *sinx, float *cosx) const; + + // compute cos or sin for current phase angle + float cos() const { return std::cos(d_phase); } + float sin() const { return std::sin(d_phase); } + + // compute a block at a time + void cos(float *output, const float *input, + int noutput_items, double k, double ampl = 1.0); + + protected: + double d_phase; + }; + + template<class o_type, class i_type> + void + vco<o_type,i_type>::sincos(float *sinx, float *cosx) const + { + gr::sincosf(d_phase, sinx, cosx); + } + + template<class o_type, class i_type> + void + vco<o_type,i_type>::cos(float *output, const float *input, + int noutput_items, double k, double ampl) + { + for(int i = 0; i < noutput_items; i++) { + output[i] = cos() * ampl; + adjust_phase(input[i] * k); + } + } + +} /* namespace gr */ + +#endif /* _GR_VCO_H_ */ diff --git a/gnuradio-runtime/lib/message.cc b/gnuradio-runtime/lib/message.cc new file mode 100644 index 0000000000..ac066d668e --- /dev/null +++ b/gnuradio-runtime/lib/message.cc @@ -0,0 +1,82 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/message.h> +#include <assert.h> +#include <string.h> + +namespace gr { + + static long s_ncurrently_allocated = 0; + + message::sptr + message::make(long type, double arg1, double arg2, size_t length) + { + return message::sptr(new message(type, arg1, arg2, length)); + } + + message::sptr + message::make_from_string(const std::string s, long type, double arg1, double arg2) + { + message::sptr m = message::make(type, arg1, arg2, s.size()); + memcpy(m->msg(), s.data(), s.size()); + return m; + } + + message::message(long type, double arg1, double arg2, size_t length) + : d_type(type), d_arg1(arg1), d_arg2(arg2) + { + if(length == 0) + d_buf_start = d_msg_start = d_msg_end = d_buf_end = 0; + else { + d_buf_start = new unsigned char[length]; + d_msg_start = d_buf_start; + d_msg_end = d_buf_end = d_buf_start + length; + } + s_ncurrently_allocated++; + } + + message::~message() + { + assert (d_next == 0); + delete [] d_buf_start; + d_msg_start = d_msg_end = d_buf_end = 0; + s_ncurrently_allocated--; + } + + std::string + message::to_string() const + { + return std::string((char *)d_msg_start, length()); + } + + long + message_ncurrently_allocated() + { + return s_ncurrently_allocated; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/messages/msg_accepter.cc b/gnuradio-runtime/lib/messages/msg_accepter.cc index a0d2d840c6..cc86a6ff8a 100644 --- a/gnuradio-runtime/lib/messages/msg_accepter.cc +++ b/gnuradio-runtime/lib/messages/msg_accepter.cc @@ -24,7 +24,7 @@ #include "config.h" #endif -#include <messages/msg_accepter.h> +#include <gnuradio/messages/msg_accepter.h> namespace gr { namespace messages { diff --git a/gnuradio-runtime/lib/messages/msg_accepter_msgq.cc b/gnuradio-runtime/lib/messages/msg_accepter_msgq.cc index adbea5ebc6..7ee6ea02c1 100644 --- a/gnuradio-runtime/lib/messages/msg_accepter_msgq.cc +++ b/gnuradio-runtime/lib/messages/msg_accepter_msgq.cc @@ -23,9 +23,7 @@ #include <config.h> #endif -#include <messages/msg_accepter_msgq.h> - -using namespace pmt; +#include <gnuradio/messages/msg_accepter_msgq.h> namespace gr { namespace messages { @@ -41,7 +39,7 @@ namespace gr { } void - msg_accepter_msgq::post(pmt_t msg) + msg_accepter_msgq::post(pmt::pmt_t msg) { d_msg_queue->insert_tail(msg); } diff --git a/gnuradio-runtime/lib/messages/msg_producer.cc b/gnuradio-runtime/lib/messages/msg_producer.cc index c354422aa6..3f56bc6637 100644 --- a/gnuradio-runtime/lib/messages/msg_producer.cc +++ b/gnuradio-runtime/lib/messages/msg_producer.cc @@ -24,7 +24,7 @@ #include "config.h" #endif -#include <messages/msg_producer.h> +#include <gnuradio/messages/msg_producer.h> namespace gr { namespace messages { diff --git a/gnuradio-runtime/lib/messages/msg_queue.cc b/gnuradio-runtime/lib/messages/msg_queue.cc index 0d460dc05c..6db2d2daa2 100644 --- a/gnuradio-runtime/lib/messages/msg_queue.cc +++ b/gnuradio-runtime/lib/messages/msg_queue.cc @@ -24,11 +24,9 @@ #include "config.h" #endif -#include <messages/msg_queue.h> +#include <gnuradio/messages/msg_queue.h> #include <stdexcept> -using namespace pmt; - namespace gr { namespace messages { @@ -49,7 +47,7 @@ namespace gr { } void - msg_queue::insert_tail(pmt_t msg) + msg_queue::insert_tail(pmt::pmt_t msg) { gr::thread::scoped_lock guard(d_mutex); @@ -60,7 +58,7 @@ namespace gr { d_not_empty.notify_one(); } - pmt_t + pmt::pmt_t msg_queue::delete_head() { gr::thread::scoped_lock guard(d_mutex); @@ -68,7 +66,7 @@ namespace gr { while(empty_p()) d_not_empty.wait(guard); - pmt_t m(d_msgs.front()); + pmt::pmt_t m(d_msgs.front()); d_msgs.pop_front(); if(d_limit > 0) // Unlimited length queues never block on write @@ -77,15 +75,15 @@ namespace gr { return m; } - pmt_t + pmt::pmt_t msg_queue::delete_head_nowait() { gr::thread::scoped_lock guard(d_mutex); if(empty_p()) - return pmt_t(); + return pmt::pmt_t(); - pmt_t m(d_msgs.front()); + pmt::pmt_t m(d_msgs.front()); d_msgs.pop_front(); if(d_limit > 0) // Unlimited length queues never block on write @@ -97,7 +95,7 @@ namespace gr { void msg_queue::flush() { - while(delete_head_nowait() != pmt_t()) + while(delete_head_nowait() != pmt::pmt_t()) ; } diff --git a/gnuradio-runtime/lib/gr_reverse.cc b/gnuradio-runtime/lib/misc.cc index 08c588cb55..f9ad6ca89c 100644 --- a/gnuradio-runtime/lib/gr_reverse.cc +++ b/gnuradio-runtime/lib/misc.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2005,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -24,37 +24,47 @@ #include "config.h" #endif -#include <gr_reverse.h> +#include "misc.h" +namespace gr { -std::vector<float> -gr_reverse (const std::vector<float> &taps) -{ - int size = taps.size (); - std::vector<float> new_taps(size); + unsigned int + rounduppow2(unsigned int n) + { + int i; + for(i=0;((n-1)>>i) != 0;i++) + ; + return 1<<i; + } - if (size == 0) - return new_taps; + // ---------------------------------------------------------------- - for (int i = 0; i < size; i++) - new_taps[i] = taps[size - i - 1]; + void + zero_vector(std::vector<float> &v) + { + for(unsigned int i=0; i < v.size(); i++) + v[i] = 0; + } - return new_taps; -} + void + zero_vector(std::vector<double> &v) + { + for(unsigned int i=0; i < v.size(); i++) + v[i] = 0; + } + void + zero_vector(std::vector<int> &v) + { + for(unsigned int i=0; i < v.size(); i++) + v[i] = 0; + } -std::vector<gr_complex> -gr_reverse (const std::vector<gr_complex> &taps) -{ - int size = taps.size (); - std::vector<gr_complex> new_taps(size); - - if (size == 0) - return new_taps; - - for (int i = 0; i < size; i++) - new_taps[i] = taps[size - i - 1]; - - return new_taps; -} + void + zero_vector(std::vector<gr_complex> &v) + { + for(unsigned int i=0; i < v.size(); i++) + v[i] = 0; + } +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/gr_misc.h b/gnuradio-runtime/lib/misc.h index 182ae87de6..833b6470a5 100644 --- a/gnuradio-runtime/lib/gr_misc.h +++ b/gnuradio-runtime/lib/misc.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2005,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -23,17 +23,20 @@ #ifndef INCLUDED_GR_MISC_H #define INCLUDED_GR_MISC_H -#include <gr_runtime_api.h> -#include <gr_types.h> +#include <gnuradio/api.h> +#include <gnuradio/types.h> -GR_RUNTIME_API unsigned int -gr_rounduppow2(unsigned int n); +namespace gr { -// FIXME should be template -GR_RUNTIME_API void gr_zero_vector(std::vector<float> &v); -GR_RUNTIME_API void gr_zero_vector(std::vector<double> &v); -GR_RUNTIME_API void gr_zero_vector(std::vector<int> &v); -GR_RUNTIME_API void gr_zero_vector(std::vector<gr_complex> &v); + GR_RUNTIME_API unsigned int + rounduppow2(unsigned int n); + // FIXME should be template + GR_RUNTIME_API void zero_vector(std::vector<float> &v); + GR_RUNTIME_API void zero_vector(std::vector<double> &v); + GR_RUNTIME_API void zero_vector(std::vector<int> &v); + GR_RUNTIME_API void zero_vector(std::vector<gr_complex> &v); + +} /* namespace gr */ #endif /* INCLUDED_GR_MISC_H */ diff --git a/gnuradio-runtime/lib/gr_msg_accepter.cc b/gnuradio-runtime/lib/msg_accepter.cc index 93d5fb20e8..354fce0c3d 100644 --- a/gnuradio-runtime/lib/gr_msg_accepter.cc +++ b/gnuradio-runtime/lib/msg_accepter.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2009 Free Software Foundation, Inc. + * Copyright 2009,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -23,37 +23,40 @@ #include <config.h> #endif -#include <gr_msg_accepter.h> -#include <gr_block.h> -#include <gr_block_detail.h> -#include <gr_hier_block2.h> +#include <gnuradio/msg_accepter.h> +#include <gnuradio/block.h> +#include <gnuradio/block_detail.h> +#include <gnuradio/hier_block2.h> #include <stdexcept> -using namespace pmt; - -gr_msg_accepter::gr_msg_accepter() -{ -} - -gr_msg_accepter::~gr_msg_accepter() -{ - // NOP, required as virtual destructor -} - -void -gr_msg_accepter::post(pmt_t which_port, pmt_t msg) -{ - // Notify derived class, handled case by case - gr_block *p = dynamic_cast<gr_block *>(this); - if (p) { - p->_post(which_port,msg); - return; +namespace gr { + + msg_accepter::msg_accepter() + { + } + + msg_accepter::~msg_accepter() + { + // NOP, required as virtual destructor } - gr_hier_block2 *p2 = dynamic_cast<gr_hier_block2 *>(this); - if (p2){ - // FIXME do the right thing - return; + + void + msg_accepter::post(pmt::pmt_t which_port, pmt::pmt_t msg) + { + // Notify derived class, handled case by case + block *p = dynamic_cast<block *>(this); + if(p) { + p->_post(which_port, msg); + return; + } + + hier_block2 *p2 = dynamic_cast<hier_block2 *>(this); + if(p2) { + // FIXME do the right thing + return; + } + + throw std::runtime_error("unknown derived class"); } - throw std::runtime_error("unknown derived class"); -} +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/gr_msg_handler.cc b/gnuradio-runtime/lib/msg_handler.cc index 0f93497088..32d14eb715 100644 --- a/gnuradio-runtime/lib/gr_msg_handler.cc +++ b/gnuradio-runtime/lib/msg_handler.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2005,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -23,8 +23,13 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include <gr_msg_handler.h> -gr_msg_handler::~gr_msg_handler () -{ -} +#include <gnuradio/msg_handler.h> + +namespace gr { + + msg_handler::~msg_handler() + { + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/msg_queue.cc b/gnuradio-runtime/lib/msg_queue.cc new file mode 100644 index 0000000000..9961f76296 --- /dev/null +++ b/gnuradio-runtime/lib/msg_queue.cc @@ -0,0 +1,130 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2009,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/msg_queue.h> +#include <stdexcept> + +namespace gr { + + msg_queue::sptr + msg_queue::make(unsigned int limit) + { + return msg_queue::sptr(new msg_queue(limit)); + } + + msg_queue::msg_queue(unsigned int limit) + : d_not_empty(), d_not_full(), + /*d_head(0), d_tail(0),*/ d_count(0), d_limit(limit) + { + } + + msg_queue::~msg_queue() + { + flush (); + } + + void + msg_queue::insert_tail(message::sptr msg) + { + if(msg->d_next) + throw std::invalid_argument("gr::msg_queue::insert_tail: msg already in queue"); + + gr::thread::scoped_lock guard(d_mutex); + + while(full_p()) + d_not_full.wait(guard); + + if(d_tail == 0) { + d_tail = d_head = msg; + //msg->d_next = 0; + msg->d_next.reset(); + } + else { + d_tail->d_next = msg; + d_tail = msg; + //msg->d_next = 0; + msg->d_next.reset(); + } + d_count++; + d_not_empty.notify_one(); + } + + message::sptr + msg_queue::delete_head() + { + gr::thread::scoped_lock guard(d_mutex); + message::sptr m; + + while((m = d_head) == 0) + d_not_empty.wait(guard); + + d_head = m->d_next; + if(d_head == 0){ + //d_tail = 0; + d_tail.reset(); + } + + d_count--; + // m->d_next = 0; + m->d_next.reset(); + d_not_full.notify_one(); + return m; + } + + message::sptr + msg_queue::delete_head_nowait() + { + gr::thread::scoped_lock guard(d_mutex); + message::sptr m; + + if((m = d_head) == 0) { + //return 0; + return message::sptr(); + } + + d_head = m->d_next; + if(d_head == 0) { + //d_tail = 0; + d_tail.reset(); + } + + d_count--; + //m->d_next = 0; + m->d_next.reset(); + d_not_full.notify_one(); + return m; + } + + void + msg_queue::flush() + { + message::sptr m; + + while((m = delete_head_nowait ()) != 0) + ; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/gr_pagesize.cc b/gnuradio-runtime/lib/pagesize.cc index e31e05ca70..373c0b6654 100644 --- a/gnuradio-runtime/lib/gr_pagesize.cc +++ b/gnuradio-runtime/lib/pagesize.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2003 Free Software Foundation, Inc. + * Copyright 2003,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -24,33 +24,36 @@ #include "config.h" #endif -#include <gr_pagesize.h> +#include "pagesize.h" #include <unistd.h> #include <stdio.h> +namespace gr { + #if defined(_WIN32) && defined(HAVE_GETPAGESIZE) -extern "C" size_t getpagesize(void); + extern "C" size_t getpagesize(void); #endif -int -gr_pagesize () -{ - static int s_pagesize = -1; + int + pagesize() + { + static int s_pagesize = -1; - if (s_pagesize == -1){ + if(s_pagesize == -1) { #if defined(HAVE_GETPAGESIZE) - s_pagesize = getpagesize (); + s_pagesize = getpagesize(); #elif defined (HAVE_SYSCONF) - s_pagesize = sysconf (_SC_PAGESIZE); - if (s_pagesize == -1){ - perror ("_SC_PAGESIZE"); - s_pagesize = 4096; - } + s_pagesize = sysconf(_SC_PAGESIZE); + if(s_pagesize == -1) { + perror("_SC_PAGESIZE"); + s_pagesize = 4096; + } #else - fprintf (stderr, "gr_pagesize: no info; setting pagesize = 4096\n"); - s_pagesize = 4096; + fprintf(stderr, "gr::pagesize: no info; setting pagesize = 4096\n"); + s_pagesize = 4096; #endif + } + return s_pagesize; } - return s_pagesize; -} +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/gr_pagesize.h b/gnuradio-runtime/lib/pagesize.h index d14cb22b1b..6a16882002 100644 --- a/gnuradio-runtime/lib/gr_pagesize.h +++ b/gnuradio-runtime/lib/pagesize.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2003 Free Software Foundation, Inc. + * Copyright 2003,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -19,16 +19,19 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ -#ifndef _GR_PAGESIZE_H_ -#define _GR_PAGESIZE_H_ -#include <gr_runtime_api.h> +#ifndef GR_PAGESIZE_H_ +#define GR_PAGESIZE_H_ -/*! - * \brief return the page size in bytes - */ +#include <gnuradio/api.h> + +namespace gr { -GR_RUNTIME_API int gr_pagesize (); + /*! + * \brief return the page size in bytes + */ + GR_RUNTIME_API int pagesize(); +} /* namespace gr */ -#endif /* _GR_PAGESIZE_H_ */
\ No newline at end of file +#endif /* GR_PAGESIZE_H_ */ diff --git a/gnuradio-runtime/lib/pmt/pmt.cc b/gnuradio-runtime/lib/pmt/pmt.cc index b6b3004331..f3f7783839 100644 --- a/gnuradio-runtime/lib/pmt/pmt.cc +++ b/gnuradio-runtime/lib/pmt/pmt.cc @@ -27,7 +27,7 @@ #include <vector> #include <pmt/pmt.h> #include "pmt_int.h" -#include <messages/msg_accepter.h> +#include <gnuradio/messages/msg_accepter.h> #include <pmt/pmt_pool.h> #include <stdio.h> #include <string.h> diff --git a/gnuradio-runtime/lib/pmt/qa_pmt.h b/gnuradio-runtime/lib/pmt/qa_pmt.h index 3e0c91abac..9293a076a6 100644 --- a/gnuradio-runtime/lib/pmt/qa_pmt.h +++ b/gnuradio-runtime/lib/pmt/qa_pmt.h @@ -23,7 +23,7 @@ #ifndef INCLUDED_QA_PMT_H #define INCLUDED_QA_PMT_H -#include <attributes.h> +#include <gnuradio/attributes.h> #include <cppunit/TestSuite.h> //! collect all the tests for pmt diff --git a/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc b/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc index e9a897deac..bfe71fbe5a 100644 --- a/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc +++ b/gnuradio-runtime/lib/pmt/qa_pmt_prims.cc @@ -22,7 +22,7 @@ #include <qa_pmt_prims.h> #include <cppunit/TestAssert.h> -#include <messages/msg_passing.h> +#include <gnuradio/messages/msg_passing.h> #include <boost/format.hpp> #include <cstdio> #include <cstring> diff --git a/gnuradio-runtime/lib/pmt/qa_pmt_prims.h b/gnuradio-runtime/lib/pmt/qa_pmt_prims.h index 8c3f5c6220..f2f3dd77f7 100644 --- a/gnuradio-runtime/lib/pmt/qa_pmt_prims.h +++ b/gnuradio-runtime/lib/pmt/qa_pmt_prims.h @@ -22,13 +22,13 @@ #ifndef INCLUDED_QA_PMT_PRIMS_H #define INCLUDED_QA_PMT_PRIMS_H -#include <attributes.h> +#include <gnuradio/attributes.h> #include <pmt/api.h> //reason: suppress warnings #include <cppunit/extensions/HelperMacros.h> #include <cppunit/TestCase.h> -class __GR_ATTR_EXPORT qa_pmt_prims : public CppUnit::TestCase { - +class __GR_ATTR_EXPORT qa_pmt_prims : public CppUnit::TestCase +{ CPPUNIT_TEST_SUITE(qa_pmt_prims); CPPUNIT_TEST(test_symbols); CPPUNIT_TEST(test_booleans); diff --git a/gnuradio-runtime/lib/pmt/unv_qa_template.cc.t b/gnuradio-runtime/lib/pmt/unv_qa_template.cc.t index a04d532b4e..ea675cee16 100644 --- a/gnuradio-runtime/lib/pmt/unv_qa_template.cc.t +++ b/gnuradio-runtime/lib/pmt/unv_qa_template.cc.t @@ -2,7 +2,7 @@ void qa_pmt_unv::test_@TAG@vector() { static const size_t N = 3; - pmt_t v1 = pmt::make_@TAG@vector(N, 0); + pmt::pmt_t v1 = pmt::make_@TAG@vector(N, 0); CPPUNIT_ASSERT_EQUAL(N, pmt::length(v1)); @TYPE@ s0 = @TYPE@(10); @TYPE@ s1 = @TYPE@(20); diff --git a/gnuradio-runtime/lib/posix_memalign.cc b/gnuradio-runtime/lib/posix_memalign.cc index aaeff78042..a08e9e127a 100644 --- a/gnuradio-runtime/lib/posix_memalign.cc +++ b/gnuradio-runtime/lib/posix_memalign.cc @@ -36,7 +36,7 @@ /* emulate posix_memalign functionality, to some degree */ #include <errno.h> -#include "gr_pagesize.h" +#include "pagesize.h" int posix_memalign (void **memptr, size_t alignment, size_t size) @@ -86,7 +86,7 @@ int posix_memalign /* try valloc if it exists */ /* cheap and easy way to make sure alignment is met, so long as it * is <= pagesize () */ - if (alignment <= (size_t) gr_pagesize ()) { + if (alignment <= (size_t) gr::pagesize ()) { *memptr = valloc (size); } } diff --git a/gnuradio-runtime/lib/prefs.cc b/gnuradio-runtime/lib/prefs.cc new file mode 100644 index 0000000000..468532f33b --- /dev/null +++ b/gnuradio-runtime/lib/prefs.cc @@ -0,0 +1,401 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gnuradio/prefs.h> +#include <gnuradio/sys_paths.h> +#include <gnuradio/constants.h> +#include <algorithm> + +#include <boost/filesystem/operations.hpp> +#include <boost/filesystem/path.hpp> +#include <boost/filesystem/fstream.hpp> +namespace fs = boost::filesystem; + +namespace gr { + + /* + * Stub implementations + */ + static prefs s_default_singleton; + static prefs *s_singleton = &s_default_singleton; + + prefs * + prefs::singleton() + { + return s_singleton; + } + + void + prefs::set_singleton(prefs *p) + { + s_singleton = p; + } + + prefs::prefs() + { + _read_files(); + } + + prefs::~prefs() + { + // nop + } + + std::vector<std::string> + prefs::_sys_prefs_filenames() + { + std::vector<std::string> fnames; + + fs::path dir = prefsdir(); + if(!fs::is_directory(dir)) + return fnames; + + fs::directory_iterator diritr(dir); + while(diritr != fs::directory_iterator()) { + fs::path p = *diritr++; + if(p.extension() != ".swp") + fnames.push_back(p.string()); + } + std::sort(fnames.begin(), fnames.end()); + + // Find if there is a ~/.gnuradio/config.conf file and add this to + // the end of the file list to override any preferences in the + // installed path config files. + fs::path homedir = fs::path(gr::appdata_path()); + homedir = homedir/".gnuradio/config.conf"; + if(fs::exists(homedir)) { + fnames.push_back(homedir.string()); + } + + return fnames; + } + + void + prefs::_read_files() + { + std::string config; + + std::vector<std::string> filenames = _sys_prefs_filenames(); + std::vector<std::string>::iterator sitr; + char tmp[1024]; + for(sitr = filenames.begin(); sitr != filenames.end(); sitr++) { + fs::ifstream fin(*sitr); + while(!fin.eof()) { + fin.getline(tmp, 1024); + std::string t(tmp); + // ignore empty lines or lines of just comments + if((t.size() > 0) && (t[0] != '#')) { + // remove any comments in the line + size_t hash = t.find("#"); + + // Use hash marks at the end of each segment as a delimiter + config += t.substr(0, hash) + '#'; + } + } + fin.close(); + } + + // Remove all whitespace. + config.erase(std::remove_if(config.begin(), config.end(), + ::isspace), config.end()); + + // Convert the string into a map + _convert_to_map(config); + } + + void + prefs::_convert_to_map(const std::string &conf) + { + // Convert the string into an map of maps + // Map is structured as {section name: map of options} + // And options map is simply: {option name: option value} + std::string sub = conf; + size_t sec_start = sub.find("["); + while(sec_start != std::string::npos) { + sub = sub.substr(sec_start); + + size_t sec_end = sub.find("]"); + if(sec_end == std::string::npos) + throw std::runtime_error("Config file error: Mismatched section label.\n"); + + std::string sec = sub.substr(1, sec_end-1); + size_t next_sec_start = sub.find("[", sec_end); + std::string subsec = sub.substr(sec_end+1, next_sec_start-sec_end-2); + + std::transform(sec.begin(), sec.end(), sec.begin(), ::tolower); + + std::map<std::string, std::string> options_map = d_config_map[sec]; + size_t next_opt = 0; + size_t next_val = 0; + next_opt = subsec.find("#"); + while(next_opt < subsec.size()-1) { + next_val = subsec.find("=", next_opt); + std::string option = subsec.substr(next_opt+1, next_val-next_opt-1); + + next_opt = subsec.find("#", next_val); + std::string value = subsec.substr(next_val+1, next_opt-next_val-1); + + std::transform(option.begin(), option.end(), option.begin(), ::tolower); + options_map[option] = value; + } + + d_config_map[sec] = options_map; + + sec_start = sub.find("[", sec_end); + } + } + + std::string + prefs::to_string() + { + config_map_itr sections; + config_map_elem_itr options; + std::stringstream s; + + for(sections = d_config_map.begin(); sections != d_config_map.end(); sections++) { + s << "[" << sections->first << "]" << std::endl; + for(options = sections->second.begin(); options != sections->second.end(); options++) { + s << options->first << " = " << options->second << std::endl; + } + s << std::endl; + } + + return s.str(); + } + + void + prefs::save() + { + std::string conf = to_string(); + + fs::path homedir = fs::path(gr::appdata_path()); + homedir = homedir/".gnuradio/config.conf"; + fs::ofstream fout(homedir); + fout << conf; + fout.close(); + } + + char * + prefs::option_to_env(std::string section, std::string option) + { + std::stringstream envname; + std::string secname=section, optname=option; + + std::transform(section.begin(), section.end(), secname.begin(), ::toupper); + std::transform(option.begin(), option.end(), optname.begin(), ::toupper); + envname << "GR_CONF_" << secname << "_" << optname; + + return getenv(envname.str().c_str()); + } + + bool + prefs::has_section(const std::string §ion) + { + std::string s = section; + std::transform(section.begin(), section.end(), s.begin(), ::tolower); + return d_config_map.count(s) > 0; + } + + bool + prefs::has_option(const std::string §ion, const std::string &option) + { + if(option_to_env(section, option)) + return true; + + if(has_section(section)) { + std::string s = section; + std::transform(section.begin(), section.end(), s.begin(), ::tolower); + + std::string o = option; + std::transform(option.begin(), option.end(), o.begin(), ::tolower); + + config_map_itr sec = d_config_map.find(s); + return sec->second.count(o) > 0; + } + else { + return false; + } + } + + const std::string + prefs::get_string(const std::string §ion, const std::string &option, + const std::string &default_val) + { + char *env = option_to_env(section, option); + if(env) + return std::string(env); + + if(has_option(section, option)) { + std::string s = section; + std::transform(section.begin(), section.end(), s.begin(), ::tolower); + + std::string o = option; + std::transform(option.begin(), option.end(), o.begin(), ::tolower); + + config_map_itr sec = d_config_map.find(s); + config_map_elem_itr opt = sec->second.find(o); + return opt->second; + } + else { + return default_val; + } + } + + void + prefs::set_string(const std::string §ion, const std::string &option, + const std::string &val) + { + std::string s = section; + std::transform(section.begin(), section.end(), s.begin(), ::tolower); + + std::string o = option; + std::transform(option.begin(), option.end(), o.begin(), ::tolower); + + std::map<std::string, std::string> opt_map = d_config_map[s]; + + opt_map[o] = val; + + d_config_map[s] = opt_map; + } + + bool + prefs::get_bool(const std::string §ion, const std::string &option, + bool default_val) + { + if(has_option(section, option)) { + std::string str = get_string(section, option, ""); + if(str == "") { + return default_val; + } + std::transform(str.begin(), str.end(), str.begin(), ::tolower); + if((str == "true") || (str == "on") || (str == "1")) + return true; + else if((str == "false") || (str == "off") || (str == "0")) + return false; + else + return default_val; + } + else { + return default_val; + } + } + + void + prefs::set_bool(const std::string §ion, const std::string &option, + bool val) + { + std::string s = section; + std::transform(section.begin(), section.end(), s.begin(), ::tolower); + + std::string o = option; + std::transform(option.begin(), option.end(), o.begin(), ::tolower); + + std::map<std::string, std::string> opt_map = d_config_map[s]; + + std::stringstream sstr; + sstr << (val == true); + opt_map[o] = sstr.str(); + + d_config_map[s] = opt_map; + } + + long + prefs::get_long(const std::string §ion, const std::string &option, + long default_val) + { + if(has_option(section, option)) { + std::string str = get_string(section, option, ""); + if(str == "") { + return default_val; + } + std::stringstream sstr(str); + long n; + sstr >> n; + return n; + } + else { + return default_val; + } + } + + void + prefs::set_long(const std::string §ion, const std::string &option, + long val) + { + std::string s = section; + std::transform(section.begin(), section.end(), s.begin(), ::tolower); + + std::string o = option; + std::transform(option.begin(), option.end(), o.begin(), ::tolower); + + std::map<std::string, std::string> opt_map = d_config_map[s]; + + std::stringstream sstr; + sstr << val; + opt_map[o] = sstr.str(); + + d_config_map[s] = opt_map; + } + + double + prefs::get_double(const std::string §ion, const std::string &option, + double default_val) + { + if(has_option(section, option)) { + std::string str = get_string(section, option, ""); + if(str == "") { + return default_val; + } + std::stringstream sstr(str); + double n; + sstr >> n; + return n; + } + else { + return default_val; + } + } + + void + prefs::set_double(const std::string §ion, const std::string &option, + double val) + { + std::string s = section; + std::transform(section.begin(), section.end(), s.begin(), ::tolower); + + std::string o = option; + std::transform(option.begin(), option.end(), o.begin(), ::tolower); + + std::map<std::string, std::string> opt_map = d_config_map[s]; + + std::stringstream sstr; + sstr << val; + opt_map[o] = sstr.str(); + + d_config_map[s] = opt_map; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/qa_buffer.cc b/gnuradio-runtime/lib/qa_buffer.cc new file mode 100644 index 0000000000..5f1dece0ad --- /dev/null +++ b/gnuradio-runtime/lib/qa_buffer.cc @@ -0,0 +1,304 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qa_buffer.h> +#include <gnuradio/buffer.h> +#include <cppunit/TestAssert.h> +#include <stdlib.h> +#include <gnuradio/random.h> + +static void +leak_check(void f()) +{ + long buffer_count = gr::buffer_ncurrently_allocated(); + long buffer_reader_count = gr::buffer_reader_ncurrently_allocated(); + + f(); + + CPPUNIT_ASSERT_EQUAL(buffer_reader_count, gr::buffer_reader_ncurrently_allocated()); + CPPUNIT_ASSERT_EQUAL(buffer_count, gr::buffer_ncurrently_allocated()); +} + + +// ---------------------------------------------------------------------------- +// test single writer, no readers... +// + +static void +t0_body() +{ + int nitems = 4000 / sizeof(int); + int counter = 0; + + gr::buffer_sptr buf(gr::make_buffer(nitems, sizeof(int), gr::block_sptr())); + + int last_sa; + int sa; + + sa = buf->space_available(); + CPPUNIT_ASSERT(sa > 0); + last_sa = sa; + + for(int i = 0; i < 5; i++) { + sa = buf->space_available(); + CPPUNIT_ASSERT_EQUAL(last_sa, sa); + last_sa = sa; + + int *p = (int*)buf->write_pointer(); + CPPUNIT_ASSERT(p != 0); + + for(int j = 0; j < sa; j++) + *p++ = counter++; + + buf->update_write_pointer(sa); + } +} + +// ---------------------------------------------------------------------------- +// test single writer, single reader +// + +static void +t1_body() +{ + int nitems = 4000 / sizeof(int); + int write_counter = 0; + int read_counter = 0; + + gr::buffer_sptr buf(gr::make_buffer(nitems, sizeof(int), gr::block_sptr())); + gr::buffer_reader_sptr r1(gr::buffer_add_reader(buf, 0, gr::block_sptr())); + + int sa; + + // write 1/3 of buffer + + sa = buf->space_available(); + CPPUNIT_ASSERT(sa > 0); + + int *p = (int*)buf->write_pointer(); + CPPUNIT_ASSERT(p != 0); + + for(int j = 0; j < sa/3; j++) { + *p++ = write_counter++; + } + buf->update_write_pointer(sa/3); + + // write the next 1/3 (1/2 of what's left) + + sa = buf->space_available(); + CPPUNIT_ASSERT(sa > 0); + + p = (int*)buf->write_pointer(); + CPPUNIT_ASSERT(p != 0); + + for(int j = 0; j < sa/2; j++) { + *p++ = write_counter++; + } + buf->update_write_pointer(sa/2); + + // check that we can read it OK + + int ia = r1->items_available(); + CPPUNIT_ASSERT_EQUAL(write_counter, ia); + + int *rp = (int*)r1->read_pointer(); + CPPUNIT_ASSERT(rp != 0); + + for(int i = 0; i < ia/2; i++) { + CPPUNIT_ASSERT_EQUAL(read_counter, *rp); + read_counter++; + rp++; + } + r1->update_read_pointer(ia/2); + + // read the rest + + ia = r1->items_available(); + rp = (int *) r1->read_pointer(); + CPPUNIT_ASSERT(rp != 0); + + for(int i = 0; i < ia; i++) { + CPPUNIT_ASSERT_EQUAL(read_counter, *rp); + read_counter++; + rp++; + } + r1->update_read_pointer(ia); +} + +// ---------------------------------------------------------------------------- +// single writer, single reader: check wrap-around +// + +static void +t2_body() +{ + // 64K is the largest granularity we've seen so far (MS windows file mapping). + // This allows a bit of "white box testing" + + int nitems = (64 * (1L << 10)) / sizeof(int); // 64K worth of ints + + gr::buffer_sptr buf(gr::make_buffer(nitems, sizeof(int), gr::block_sptr())); + gr::buffer_reader_sptr r1(gr::buffer_add_reader(buf, 0, gr::block_sptr())); + + int read_counter = 0; + int write_counter = 0; + int n; + int *wp = 0; + int *rp = 0; + + // Write 3/4 of buffer + + n = (int)(buf->space_available() * 0.75); + wp = (int*)buf->write_pointer(); + + for(int i = 0; i < n; i++) + *wp++ = write_counter++; + buf->update_write_pointer(n); + + // Now read it all + + int m = r1->items_available(); + CPPUNIT_ASSERT_EQUAL(n, m); + rp = (int*)r1->read_pointer(); + + for(int i = 0; i < m; i++) { + CPPUNIT_ASSERT_EQUAL(read_counter, *rp); + read_counter++; + rp++; + } + r1->update_read_pointer(m); + + // Now write as much as we can. + // This will wrap around the buffer + + n = buf->space_available(); + CPPUNIT_ASSERT_EQUAL(nitems - 1, n); // white box test + wp = (int*)buf->write_pointer(); + + for(int i = 0; i < n; i++) + *wp++ = write_counter++; + buf->update_write_pointer(n); + + // now read it all + + m = r1->items_available(); + CPPUNIT_ASSERT_EQUAL(n, m); + rp = (int*)r1->read_pointer(); + + for(int i = 0; i < m; i++) { + CPPUNIT_ASSERT_EQUAL(read_counter, *rp); + read_counter++; + rp++; + } + r1->update_read_pointer(m); +} + +// ---------------------------------------------------------------------------- +// single writer, N readers, randomized order and lengths +// ---------------------------------------------------------------------------- + +static void +t3_body() +{ + int nitems = (64 * (1L << 10)) / sizeof(int); + + static const int N = 5; + gr::buffer_sptr buf(gr::make_buffer(nitems, sizeof(int), gr::block_sptr())); + gr::buffer_reader_sptr reader[N]; + int read_counter[N]; + int write_counter = 0; + gr::random random; + + for(int i = 0; i < N; i++) { + read_counter[i] = 0; + reader[i] = buffer_add_reader(buf, 0, gr::block_sptr()); + } + + for(int lc = 0; lc < 1000; lc++) { + + // write some + + int n = (int)(buf->space_available() * random.ran1()); + int *wp = (int*)buf->write_pointer(); + + for(int i = 0; i < n; i++) + *wp++ = write_counter++; + + buf->update_write_pointer(n); + + // pick a random reader and read some + + int r = (int)(N * random.ran1()); + CPPUNIT_ASSERT(0 <= r && r < N); + + int m = reader[r]->items_available(); + int *rp = (int*)reader[r]->read_pointer(); + + for(int i = 0; i < m; i++) { + CPPUNIT_ASSERT_EQUAL(read_counter[r], *rp); + read_counter[r]++; + rp++; + } + reader[r]->update_read_pointer (m); + } +} + + +// ---------------------------------------------------------------------------- + +void +qa_buffer::t0() +{ + leak_check(t0_body); +} + +void +qa_buffer::t1() +{ + leak_check(t1_body); +} + +void +qa_buffer::t2() +{ + leak_check(t2_body); +} + +void +qa_buffer::t3() +{ + leak_check(t3_body); +} + +void +qa_buffer::t4() +{ +} + +void +qa_buffer::t5() +{ +} diff --git a/gnuradio-runtime/lib/qa_gr_buffer.h b/gnuradio-runtime/lib/qa_buffer.h index 2937c24b68..a41e69dd48 100644 --- a/gnuradio-runtime/lib/qa_gr_buffer.h +++ b/gnuradio-runtime/lib/qa_buffer.h @@ -26,28 +26,24 @@ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/TestCase.h> -class qa_gr_buffer : public CppUnit::TestCase { - - CPPUNIT_TEST_SUITE (qa_gr_buffer); - CPPUNIT_TEST (t0); - CPPUNIT_TEST (t1); - CPPUNIT_TEST (t2); - CPPUNIT_TEST (t3); - CPPUNIT_TEST (t4); - CPPUNIT_TEST (t5); - CPPUNIT_TEST_SUITE_END (); - +class qa_buffer : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(qa_buffer); + CPPUNIT_TEST(t0); + CPPUNIT_TEST(t1); + CPPUNIT_TEST(t2); + CPPUNIT_TEST(t3); + CPPUNIT_TEST(t4); + CPPUNIT_TEST(t5); + CPPUNIT_TEST_SUITE_END(); private: - - void t0 (); - void t1 (); - void t2 (); - void t3 (); - void t4 (); - void t5 (); + void t0(); + void t1(); + void t2(); + void t3(); + void t4(); + void t5(); }; - - #endif /* INCLUDED_QA_GR_BUFFER_H */ diff --git a/gnuradio-runtime/lib/qa_gr_circular_file.cc b/gnuradio-runtime/lib/qa_circular_file.cc index 243e44784b..d80831b4b9 100644 --- a/gnuradio-runtime/lib/qa_gr_circular_file.cc +++ b/gnuradio-runtime/lib/qa_circular_file.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2002 Free Software Foundation, Inc. + * Copyright 2002,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -23,8 +23,9 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include <qa_gr_circular_file.h> -#include <gr_circular_file.h> + +#include "qa_circular_file.h" +#include "circular_file.h" #include <cppunit/TestAssert.h> #include <iostream> #include <stdio.h> @@ -35,38 +36,37 @@ static const int BUFFER_SIZE = 8192; static const int NWRITE = 8192 * 9 / 8; void -qa_gr_circular_file::t1 () +qa_circular_file::t1() { #ifdef HAVE_MMAP - gr_circular_file *cf_writer; - gr_circular_file *cf_reader; + gr::circular_file *cf_writer; + gr::circular_file *cf_reader; // write the data... - - cf_writer = new gr_circular_file (test_file, true, BUFFER_SIZE * sizeof (short)); + cf_writer = new gr::circular_file(test_file, true, + BUFFER_SIZE * sizeof(short)); short sd; - for (int i = 0; i < NWRITE; i++){ + for(int i = 0; i < NWRITE; i++) { sd = i; - cf_writer->write (&sd, sizeof (sd)); + cf_writer->write(&sd, sizeof (sd)); } delete cf_writer; // now read it back... - - cf_reader = new gr_circular_file (test_file); - for (int i = 0; i < BUFFER_SIZE; i++){ - int n = cf_reader->read (&sd, sizeof (sd)); - CPPUNIT_ASSERT_EQUAL ((int) sizeof (sd), n); - CPPUNIT_ASSERT_EQUAL (NWRITE - BUFFER_SIZE + i, (int) sd); + cf_reader = new gr::circular_file(test_file); + for(int i = 0; i < BUFFER_SIZE; i++) { + int n = cf_reader->read (&sd, sizeof(sd)); + CPPUNIT_ASSERT_EQUAL((int) sizeof (sd), n); + CPPUNIT_ASSERT_EQUAL(NWRITE - BUFFER_SIZE + i, (int)sd); } - int n = cf_reader->read (&sd, sizeof (sd)); - CPPUNIT_ASSERT_EQUAL (0, n); + int n = cf_reader->read(&sd, sizeof(sd)); + CPPUNIT_ASSERT_EQUAL(0, n); delete cf_reader; - unlink (test_file); + unlink(test_file); #endif // HAVE_MMAP } diff --git a/gnuradio-runtime/lib/qa_gr_vmcircbuf.h b/gnuradio-runtime/lib/qa_circular_file.h index 3576660d5a..fd5c156b56 100644 --- a/gnuradio-runtime/lib/qa_gr_vmcircbuf.h +++ b/gnuradio-runtime/lib/qa_circular_file.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2002,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -19,21 +19,21 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ -#ifndef _QA_GR_VMCIRCBUF_H_ -#define _QA_GR_VMCIRCBUF_H_ + +#ifndef QA_GR_CIRCULAR_FILE_H +#define QA_GR_CIRCULAR_FILE_H #include <cppunit/extensions/HelperMacros.h> #include <cppunit/TestCase.h> -class qa_gr_vmcircbuf : public CppUnit::TestCase { - - CPPUNIT_TEST_SUITE (qa_gr_vmcircbuf); - CPPUNIT_TEST (test_all); - CPPUNIT_TEST_SUITE_END (); +class qa_circular_file : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(qa_circular_file); + CPPUNIT_TEST(t1); + CPPUNIT_TEST_SUITE_END(); - private: - void test_all (); +private: + void t1(); }; - -#endif /* _QA_GR_VMCIRCBUF_H_ */ +#endif /* QA_GR_CIRCULAR_FILE_H */ diff --git a/gnuradio-runtime/lib/qa_gr_buffer.cc b/gnuradio-runtime/lib/qa_gr_buffer.cc deleted file mode 100644 index c74baf398e..0000000000 --- a/gnuradio-runtime/lib/qa_gr_buffer.cc +++ /dev/null @@ -1,307 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <qa_gr_buffer.h> -#include <gr_buffer.h> -#include <cppunit/TestAssert.h> -#include <stdlib.h> -#include <gr_random.h> - -static void -leak_check (void f ()) -{ - long buffer_count = gr_buffer_ncurrently_allocated (); - long buffer_reader_count = gr_buffer_reader_ncurrently_allocated (); - - f (); - - CPPUNIT_ASSERT_EQUAL (buffer_reader_count, gr_buffer_reader_ncurrently_allocated ()); - CPPUNIT_ASSERT_EQUAL (buffer_count, gr_buffer_ncurrently_allocated ()); -} - - -// ---------------------------------------------------------------------------- -// test single writer, no readers... -// - -static void -t0_body () -{ - int nitems = 4000 / sizeof (int); - int counter = 0; - - gr_buffer_sptr buf(gr_make_buffer(nitems, sizeof (int), gr_block_sptr())); - - int last_sa; - int sa; - - sa = buf->space_available (); - CPPUNIT_ASSERT (sa > 0); - last_sa = sa; - - for (int i = 0; i < 5; i++){ - sa = buf->space_available (); - CPPUNIT_ASSERT_EQUAL (last_sa, sa); - last_sa = sa; - - int *p = (int *) buf->write_pointer (); - CPPUNIT_ASSERT (p != 0); - - for (int j = 0; j < sa; j++) - *p++ = counter++; - - buf->update_write_pointer (sa); - } -} - -// ---------------------------------------------------------------------------- -// test single writer, single reader -// - -static void -t1_body () - { - int nitems = 4000 / sizeof (int); - int write_counter = 0; - int read_counter = 0; - - gr_buffer_sptr buf(gr_make_buffer(nitems, sizeof (int), gr_block_sptr())); - gr_buffer_reader_sptr r1 (gr_buffer_add_reader (buf, 0, gr_block_sptr())); - - - int sa; - - // write 1/3 of buffer - - sa = buf->space_available (); - CPPUNIT_ASSERT (sa > 0); - - int *p = (int *) buf->write_pointer (); - CPPUNIT_ASSERT (p != 0); - - for (int j = 0; j < sa/3; j++){ - *p++ = write_counter++; - } - buf->update_write_pointer (sa/3); - - - // write the next 1/3 (1/2 of what's left) - - sa = buf->space_available (); - CPPUNIT_ASSERT (sa > 0); - - p = (int *) buf->write_pointer (); - CPPUNIT_ASSERT (p != 0); - - for (int j = 0; j < sa/2; j++){ - *p++ = write_counter++; - } - buf->update_write_pointer (sa/2); - - - // check that we can read it OK - - int ia = r1->items_available (); - CPPUNIT_ASSERT_EQUAL (write_counter, ia); - - int *rp = (int *) r1->read_pointer (); - CPPUNIT_ASSERT (rp != 0); - - for (int i = 0; i < ia/2; i++){ - CPPUNIT_ASSERT_EQUAL (read_counter, *rp); - read_counter++; - rp++; - } - r1->update_read_pointer (ia/2); - - // read the rest - - ia = r1->items_available (); - rp = (int *) r1->read_pointer (); - CPPUNIT_ASSERT (rp != 0); - - for (int i = 0; i < ia; i++){ - CPPUNIT_ASSERT_EQUAL (read_counter, *rp); - read_counter++; - rp++; - } - r1->update_read_pointer (ia); -} - -// ---------------------------------------------------------------------------- -// single writer, single reader: check wrap-around -// - -static void -t2_body () -{ - // 64K is the largest granularity we've seen so far (MS windows file mapping). - // This allows a bit of "white box testing" - - int nitems = (64 * (1L << 10)) / sizeof (int); // 64K worth of ints - - gr_buffer_sptr buf(gr_make_buffer (nitems, sizeof (int), gr_block_sptr())); - gr_buffer_reader_sptr r1 (gr_buffer_add_reader (buf, 0, gr_block_sptr())); - - int read_counter = 0; - int write_counter = 0; - int n; - int *wp = 0; - int *rp = 0; - - // Write 3/4 of buffer - - n = (int) (buf->space_available () * 0.75); - wp = (int *) buf->write_pointer (); - - for (int i = 0; i < n; i++) - *wp++ = write_counter++; - buf->update_write_pointer (n); - - // Now read it all - - int m = r1->items_available (); - CPPUNIT_ASSERT_EQUAL (n, m); - rp = (int *) r1->read_pointer (); - - for (int i = 0; i < m; i++){ - CPPUNIT_ASSERT_EQUAL (read_counter, *rp); - read_counter++; - rp++; - } - r1->update_read_pointer (m); - - // Now write as much as we can. - // This will wrap around the buffer - - n = buf->space_available (); - CPPUNIT_ASSERT_EQUAL (nitems - 1, n); // white box test - wp = (int *) buf->write_pointer (); - - for (int i = 0; i < n; i++) - *wp++ = write_counter++; - buf->update_write_pointer (n); - - // now read it all - - m = r1->items_available (); - CPPUNIT_ASSERT_EQUAL (n, m); - rp = (int *) r1->read_pointer (); - - for (int i = 0; i < m; i++){ - CPPUNIT_ASSERT_EQUAL (read_counter, *rp); - read_counter++; - rp++; - } - r1->update_read_pointer (m); - -} - -// ---------------------------------------------------------------------------- -// single writer, N readers, randomized order and lengths -// ---------------------------------------------------------------------------- - -static void -t3_body () -{ - int nitems = (64 * (1L << 10)) / sizeof (int); - - static const int N = 5; - gr_buffer_sptr buf(gr_make_buffer(nitems, sizeof (int), gr_block_sptr())); - gr_buffer_reader_sptr reader[N]; - int read_counter[N]; - int write_counter = 0; - gr_random random; - - for (int i = 0; i < N; i++){ - read_counter[i] = 0; - reader[i] = gr_buffer_add_reader (buf, 0, gr_block_sptr()); - } - - for (int lc = 0; lc < 1000; lc++){ - - // write some - - int n = (int) (buf->space_available () * random.ran1 ()); - int *wp = (int *) buf->write_pointer (); - - for (int i = 0; i < n; i++) - *wp++ = write_counter++; - - buf->update_write_pointer (n); - - // pick a random reader and read some - - int r = (int) (N * random.ran1 ()); - CPPUNIT_ASSERT (0 <= r && r < N); - - int m = reader[r]->items_available (); - int *rp = (int *) reader[r]->read_pointer (); - - for (int i = 0; i < m; i++){ - CPPUNIT_ASSERT_EQUAL (read_counter[r], *rp); - read_counter[r]++; - rp++; - } - reader[r]->update_read_pointer (m); - } -} - - -// ---------------------------------------------------------------------------- - -void -qa_gr_buffer::t0 () -{ - leak_check (t0_body); -} - -void -qa_gr_buffer::t1 () -{ - leak_check (t1_body); -} - -void -qa_gr_buffer::t2 () -{ - leak_check (t2_body); -} - -void -qa_gr_buffer::t3 () -{ - leak_check (t3_body); -} - -void -qa_gr_buffer::t4 () -{ -} - -void -qa_gr_buffer::t5 () -{ -} diff --git a/gnuradio-runtime/lib/qa_gr_fxpt.cc b/gnuradio-runtime/lib/qa_gr_fxpt.cc deleted file mode 100644 index 7eac0d8964..0000000000 --- a/gnuradio-runtime/lib/qa_gr_fxpt.cc +++ /dev/null @@ -1,103 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <qa_gr_fxpt.h> -#include <gr_fxpt.h> -#include <cppunit/TestAssert.h> -#include <iostream> -#include <stdio.h> -#include <unistd.h> -#include <math.h> - -static const float SIN_COS_TOLERANCE = 1e-5; - -void -qa_gr_fxpt::t0 () -{ - CPPUNIT_ASSERT_DOUBLES_EQUAL (M_PI/2, gr_fxpt::fixed_to_float (0x40000000), SIN_COS_TOLERANCE); - CPPUNIT_ASSERT_DOUBLES_EQUAL (0.0, gr_fxpt::fixed_to_float (0x00000000), SIN_COS_TOLERANCE); - CPPUNIT_ASSERT_DOUBLES_EQUAL (-M_PI, gr_fxpt::fixed_to_float (0x80000000), SIN_COS_TOLERANCE); - - if (0){ - /* - * These are disabled because of some precision issues. - * - * Different compilers seem to have different opinions on whether - * the calulations are done single or double (or extended) - * precision. Any of the answers are fine for our real purpose, but - * sometimes the answer is off by a few bits at the bottom. - * Hence, the disabled check. - */ - CPPUNIT_ASSERT_EQUAL ((gr_int32) 0x40000000, gr_fxpt::float_to_fixed (M_PI/2)); - CPPUNIT_ASSERT_EQUAL ((gr_int32) 0, gr_fxpt::float_to_fixed (0)); - CPPUNIT_ASSERT_EQUAL ((gr_int32) 0x80000000, gr_fxpt::float_to_fixed (-M_PI)); - } -} - -void -qa_gr_fxpt::t1 () -{ - - CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0, gr_fxpt::sin (0x00000000), SIN_COS_TOLERANCE); - CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0.707106781, gr_fxpt::sin (0x20000000), SIN_COS_TOLERANCE); - CPPUNIT_ASSERT_DOUBLES_EQUAL ( 1, gr_fxpt::sin (0x40000000), SIN_COS_TOLERANCE); - CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0.707106781, gr_fxpt::sin (0x60000000), SIN_COS_TOLERANCE); - CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0, gr_fxpt::sin (0x7fffffff), SIN_COS_TOLERANCE); - CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0, gr_fxpt::sin (0x80000000), SIN_COS_TOLERANCE); - CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0, gr_fxpt::sin (0x80000001), SIN_COS_TOLERANCE); - CPPUNIT_ASSERT_DOUBLES_EQUAL (-1, gr_fxpt::sin (-0x40000000), SIN_COS_TOLERANCE); - CPPUNIT_ASSERT_DOUBLES_EQUAL (-0.707106781, gr_fxpt::sin (-0x20000000), SIN_COS_TOLERANCE); - - - for (float p = -M_PI; p < M_PI; p += 2 * M_PI / 3600){ - float expected = sin (p); - float actual = gr_fxpt::sin (gr_fxpt::float_to_fixed (p)); - CPPUNIT_ASSERT_DOUBLES_EQUAL (expected, actual, SIN_COS_TOLERANCE); - } -} - -void -qa_gr_fxpt::t2 () -{ - for (float p = -M_PI; p < M_PI; p += 2 * M_PI / 3600){ - float expected = cos (p); - float actual = gr_fxpt::cos (gr_fxpt::float_to_fixed (p)); - CPPUNIT_ASSERT_DOUBLES_EQUAL (expected, actual, SIN_COS_TOLERANCE); - } -} - -void -qa_gr_fxpt::t3 () -{ - for (float p = -M_PI; p < M_PI; p += 2 * M_PI / 3600){ - float expected_sin = sin (p); - float expected_cos = cos (p); - float actual_sin; - float actual_cos; - gr_fxpt::sincos (gr_fxpt::float_to_fixed (p), &actual_sin, &actual_cos); - CPPUNIT_ASSERT_DOUBLES_EQUAL (expected_sin, actual_sin, SIN_COS_TOLERANCE); - CPPUNIT_ASSERT_DOUBLES_EQUAL (expected_cos, actual_cos, SIN_COS_TOLERANCE); - } -} diff --git a/gnuradio-runtime/lib/qa_gr_io_signature.cc b/gnuradio-runtime/lib/qa_gr_io_signature.cc deleted file mode 100644 index c1737ffb8e..0000000000 --- a/gnuradio-runtime/lib/qa_gr_io_signature.cc +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#include <qa_gr_io_signature.h> -#include <gr_io_signature.h> - -void -qa_gr_io_signature::t0 () -{ - gr_make_io_signature (1, 1, sizeof (int)); -} - -void -qa_gr_io_signature::t1 () -{ - gr_make_io_signature (3, 1, sizeof (int)); // throws std::invalid_argument -} - -void -qa_gr_io_signature::t2 () -{ - gr_io_signature_sptr p = - gr_make_io_signature (3, gr_io_signature::IO_INFINITE, sizeof (int)); - - CPPUNIT_ASSERT_EQUAL (p->min_streams (), 3); - CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item (0), (int) sizeof (int)); -} - -void -qa_gr_io_signature::t3 () -{ - gr_io_signature_sptr p = - gr_make_io_signature3 (0, 5, 1, 2, 3); - - CPPUNIT_ASSERT_EQUAL (p->min_streams (), 0); - CPPUNIT_ASSERT_EQUAL (p->max_streams (), 5); - CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item(0), 1); - CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item(1), 2); - CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item(2), 3); - CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item(3), 3); - CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item(4), 3); -} diff --git a/gnuradio-runtime/lib/qa_io_signature.cc b/gnuradio-runtime/lib/qa_io_signature.cc new file mode 100644 index 0000000000..bc3509a260 --- /dev/null +++ b/gnuradio-runtime/lib/qa_io_signature.cc @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qa_io_signature.h> +#include <gnuradio/io_signature.h> + +void +qa_io_signature::t0() +{ + gr::io_signature::make(1, 1, sizeof(int)); +} + +void +qa_io_signature::t1() +{ + gr::io_signature::make(3, 1, sizeof(int)); // throws std::invalid_argument +} + +void +qa_io_signature::t2() +{ + gr::io_signature::sptr p = + gr::io_signature::make(3, gr::io_signature::IO_INFINITE, sizeof(int)); + + CPPUNIT_ASSERT_EQUAL(p->min_streams(), 3); + CPPUNIT_ASSERT_EQUAL(p->sizeof_stream_item(0), (int)sizeof(int)); +} + +void +qa_io_signature::t3() +{ + gr::io_signature::sptr p = + gr::io_signature::make3(0, 5, 1, 2, 3); + + CPPUNIT_ASSERT_EQUAL(p->min_streams(), 0); + CPPUNIT_ASSERT_EQUAL(p->max_streams(), 5); + CPPUNIT_ASSERT_EQUAL(p->sizeof_stream_item(0), 1); + CPPUNIT_ASSERT_EQUAL(p->sizeof_stream_item(1), 2); + CPPUNIT_ASSERT_EQUAL(p->sizeof_stream_item(2), 3); + CPPUNIT_ASSERT_EQUAL(p->sizeof_stream_item(3), 3); + CPPUNIT_ASSERT_EQUAL(p->sizeof_stream_item(4), 3); +} diff --git a/gnuradio-runtime/lib/qa_gr_io_signature.h b/gnuradio-runtime/lib/qa_io_signature.h index 9cd6bb5247..981ad03b59 100644 --- a/gnuradio-runtime/lib/qa_gr_io_signature.h +++ b/gnuradio-runtime/lib/qa_io_signature.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -27,20 +27,20 @@ #include <cppunit/TestCase.h> #include <stdexcept> -class qa_gr_io_signature : public CppUnit::TestCase { - - CPPUNIT_TEST_SUITE (qa_gr_io_signature); - CPPUNIT_TEST (t0); - CPPUNIT_TEST_EXCEPTION (t1, std::invalid_argument); - CPPUNIT_TEST (t2); - CPPUNIT_TEST (t3); - CPPUNIT_TEST_SUITE_END (); +class qa_io_signature : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(qa_io_signature); + CPPUNIT_TEST(t0); + CPPUNIT_TEST_EXCEPTION(t1, std::invalid_argument); + CPPUNIT_TEST(t2); + CPPUNIT_TEST(t3); + CPPUNIT_TEST_SUITE_END(); private: - void t0 (); - void t1 (); - void t2 (); - void t3 (); + void t0(); + void t1(); + void t2(); + void t3(); }; #endif /* INCLUDED_QA_GR_IO_SIGNATURE_H */ diff --git a/gnuradio-runtime/lib/qa_gr_logger.cc b/gnuradio-runtime/lib/qa_logger.cc index a8e4a1d766..b147b36da1 100644 --- a/gnuradio-runtime/lib/qa_gr_logger.cc +++ b/gnuradio-runtime/lib/qa_logger.cc @@ -29,11 +29,11 @@ #include <config.h> #endif -#include <qa_gr_logger.h> -#include <gr_logger.h> +#include <qa_logger.h> +#include <gnuradio/logger.h> void -qa_gr_logger::t1() +qa_logger::t1() { #ifdef ENABLE_GR_LOG // This doesn't really test anything, more just diff --git a/gnuradio-runtime/lib/qa_gr_logger.h b/gnuradio-runtime/lib/qa_logger.h index b0d3711523..35f7f1f6c4 100644 --- a/gnuradio-runtime/lib/qa_gr_logger.h +++ b/gnuradio-runtime/lib/qa_logger.h @@ -28,15 +28,15 @@ //! collect all the tests for the example directory -class qa_gr_logger : public CppUnit::TestCase { - public: - CPPUNIT_TEST_SUITE(qa_gr_logger); +class qa_logger : public CppUnit::TestCase +{ +public: + CPPUNIT_TEST_SUITE(qa_logger); CPPUNIT_TEST(t1); CPPUNIT_TEST_SUITE_END(); private: void t1(); - }; #endif /* INCLUDED_QA_GR_LOG_H */ diff --git a/gnuradio-runtime/lib/qa_runtime.cc b/gnuradio-runtime/lib/qa_runtime.cc index b15051c2ad..dbf7e5bb9a 100644 --- a/gnuradio-runtime/lib/qa_runtime.cc +++ b/gnuradio-runtime/lib/qa_runtime.cc @@ -30,32 +30,32 @@ #endif #include <qa_runtime.h> -#include <qa_gr_buffer.h> -#include <qa_gr_circular_file.h> -#include <qa_gr_fxpt.h> -#include <qa_gr_fxpt_nco.h> -#include <qa_gr_fxpt_vco.h> -#include <qa_gr_io_signature.h> -#include <qa_gr_logger.h> -#include <qa_gr_math.h> -#include <qa_gr_vmcircbuf.h> +#include <qa_buffer.h> +#include <qa_io_signature.h> +#include <qa_circular_file.h> +#include <qa_fxpt.h> +#include <qa_fxpt_nco.h> +#include <qa_fxpt_vco.h> +#include <qa_logger.h> +#include <qa_math.h> +#include <qa_vmcircbuf.h> #include <qa_sincos.h> CppUnit::TestSuite * -qa_runtime::suite () +qa_runtime::suite() { - CppUnit::TestSuite *s = new CppUnit::TestSuite ("runtime"); + CppUnit::TestSuite *s = new CppUnit::TestSuite("runtime"); - s->addTest (qa_gr_buffer::suite ()); - s->addTest (qa_gr_circular_file::suite ()); - s->addTest (qa_gr_fxpt::suite ()); - s->addTest (qa_gr_fxpt_nco::suite ()); - s->addTest (qa_gr_fxpt_vco::suite ()); - s->addTest (qa_gr_io_signature::suite ()); - s->addTest (qa_gr_logger::suite ()); - s->addTest (qa_gr_math::suite ()); - s->addTest (qa_gr_vmcircbuf::suite ()); - s->addTest (qa_sincos::suite ()); + s->addTest(qa_buffer::suite()); + s->addTest(qa_io_signature::suite()); + s->addTest(qa_circular_file::suite()); + s->addTest(qa_fxpt::suite()); + s->addTest(qa_fxpt_nco::suite()); + s->addTest(qa_fxpt_vco::suite()); + s->addTest(qa_logger::suite()); + s->addTest(qa_math::suite()); + s->addTest(qa_vmcircbuf::suite()); + s->addTest(qa_sincos::suite()); return s; } diff --git a/gnuradio-runtime/lib/qa_runtime.h b/gnuradio-runtime/lib/qa_runtime.h index b03e3db721..a1e58190d6 100644 --- a/gnuradio-runtime/lib/qa_runtime.h +++ b/gnuradio-runtime/lib/qa_runtime.h @@ -23,7 +23,7 @@ #ifndef _QA_RUNTIME_H_ #define _QA_RUNTIME_H_ -#include <attributes.h> +#include <gnuradio/attributes.h> #include <cppunit/TestSuite.h> //! collect all the tests for the runtime directory diff --git a/gnuradio-runtime/lib/qa_gr_vmcircbuf.cc b/gnuradio-runtime/lib/qa_vmcircbuf.cc index e3b36d8829..7301b4cf17 100644 --- a/gnuradio-runtime/lib/qa_gr_vmcircbuf.cc +++ b/gnuradio-runtime/lib/qa_vmcircbuf.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2002 Free Software Foundation, Inc. + * Copyright 2002,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -24,17 +24,17 @@ #include <config.h> #endif -#include <qa_gr_vmcircbuf.h> +#include <qa_vmcircbuf.h> #include <cppunit/TestAssert.h> -#include <gr_vmcircbuf.h> +#include "vmcircbuf.h" #include <stdio.h> void -qa_gr_vmcircbuf::test_all () +qa_vmcircbuf::test_all() { - int verbose = 1; // summary + int verbose = 1; // summary - bool ok = gr_vmcircbuf_sysconfig::test_all_factories (verbose); + bool ok = gr::vmcircbuf_sysconfig::test_all_factories(verbose); - CPPUNIT_ASSERT_EQUAL (true, ok); + CPPUNIT_ASSERT_EQUAL(true, ok); } diff --git a/gnuradio-runtime/lib/qa_gr_circular_file.h b/gnuradio-runtime/lib/qa_vmcircbuf.h index df35ab077b..93f46cf4a8 100644 --- a/gnuradio-runtime/lib/qa_gr_circular_file.h +++ b/gnuradio-runtime/lib/qa_vmcircbuf.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2002 Free Software Foundation, Inc. + * Copyright 2004,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -19,22 +19,21 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ -#ifndef _QA_GR_CIRCULAR_FILE_H_ -#define _QA_GR_CIRCULAR_FILE_H_ + +#ifndef QA_GR_VMCIRCBUF_H +#define QA_GR_VMCIRCBUF_H #include <cppunit/extensions/HelperMacros.h> #include <cppunit/TestCase.h> -class qa_gr_circular_file : public CppUnit::TestCase { - - CPPUNIT_TEST_SUITE (qa_gr_circular_file); - CPPUNIT_TEST (t1); - CPPUNIT_TEST_SUITE_END (); - - private: - void t1 (); +class qa_vmcircbuf : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(qa_vmcircbuf); + CPPUNIT_TEST(test_all); + CPPUNIT_TEST_SUITE_END(); +private: + void test_all(); }; - -#endif /* _QA_GR_CIRCULAR_FILE_H_ */ +#endif /* QA_GR_VMCIRCBUF_H */ diff --git a/gnuradio-runtime/lib/random.h b/gnuradio-runtime/lib/random.h deleted file mode 100644 index c643c3e422..0000000000 --- a/gnuradio-runtime/lib/random.h +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2003, 2008 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef _RANDOM_H_ -#define _RANDOM_H_ - -// While rand(3) specifies RAND_MAX, random(3) says that the output -// ranges from 0 to 2^31-1 but does not specify a macro to denote -// this. We define RANDOM_MAX for cleanliness. We must omit the -// definition for systems that have made the same choice. (Note that -// random(3) is from 4.2BSD, and not specified by POSIX.) - -#ifndef RANDOM_MAX -static const int RANDOM_MAX = 2147483647; // 2^31-1 -#endif /* RANDOM_MAX */ - -#include <stdlib.h> - -#endif // _RANDOM_H_ diff --git a/gnuradio-runtime/lib/realtime.cc b/gnuradio-runtime/lib/realtime.cc index 5dadc26bbd..81f92ae488 100644 --- a/gnuradio-runtime/lib/realtime.cc +++ b/gnuradio-runtime/lib/realtime.cc @@ -24,155 +24,14 @@ #include <config.h> #endif -#include <realtime.h> - -#ifdef HAVE_SCHED_H -#include <sched.h> -#endif - -#include <algorithm> -#include <math.h> -#include <string.h> -#include <errno.h> -#include <stdio.h> - -#if defined(HAVE_PTHREAD_SETSCHEDPARAM) || defined(HAVE_SCHED_SETSCHEDULER) -#include <pthread.h> - -namespace gr { - - /*! - * Rescale our virtual priority so that it maps to the middle 1/2 of - * the priorities given by min_real_pri and max_real_pri. - */ - static int - rescale_virtual_pri(int virtual_pri, int min_real_pri, int max_real_pri) - { - float rmin = min_real_pri + (0.25 * (max_real_pri - min_real_pri)); - float rmax = min_real_pri + (0.75 * (max_real_pri - min_real_pri)); - float m = (rmax - rmin) / (rt_priority_max() - rt_priority_min()); - float y = m * (virtual_pri - rt_priority_min()) + rmin; - int y_int = static_cast<int>(rint(y)); - return std::max(min_real_pri, std::min(max_real_pri, y_int)); - } - -} // namespace gr - -#endif - - -#if defined(HAVE_PTHREAD_SETSCHEDPARAM) - -namespace gr { - - rt_status_t - enable_realtime_scheduling(rt_sched_param p) - { - int policy = p.policy == RT_SCHED_FIFO ? SCHED_FIFO : SCHED_RR; - int min_real_pri = sched_get_priority_min(policy); - int max_real_pri = sched_get_priority_max(policy); - int pri = rescale_virtual_pri(p.priority, min_real_pri, max_real_pri); - - // FIXME check hard and soft limits with getrlimit, and limit the value we ask for. - // fprintf(stderr, "pthread_setschedparam: policy = %d, pri = %d\n", policy, pri); - - struct sched_param param; - memset (¶m, 0, sizeof (param)); - param.sched_priority = pri; - int result = pthread_setschedparam (pthread_self(), policy, ¶m); - if (result != 0) { - if (result == EPERM) // N.B., return value, not errno - return RT_NO_PRIVS; - else { - fprintf(stderr, - "pthread_setschedparam: failed to set real time priority: %s\n", - strerror(result)); - return RT_OTHER_ERROR; - } - } - - //printf("SCHED_FIFO enabled with priority = %d\n", pri); - return RT_OK; - } -} // namespace gr - - -#elif defined(HAVE_SCHED_SETSCHEDULER) - -namespace gr { - - rt_status_t - enable_realtime_scheduling(rt_sched_param p) - { - int policy = p.policy == RT_SCHED_FIFO ? SCHED_FIFO : SCHED_RR; - int min_real_pri = sched_get_priority_min(policy); - int max_real_pri = sched_get_priority_max(policy); - int pri = rescale_virtual_pri(p.priority, min_real_pri, max_real_pri); - - // FIXME check hard and soft limits with getrlimit, and limit the value we ask for. - // fprintf(stderr, "sched_setscheduler: policy = %d, pri = %d\n", policy, pri); - - int pid = 0; // this process - struct sched_param param; - memset(¶m, 0, sizeof(param)); - param.sched_priority = pri; - int result = sched_setscheduler(pid, policy, ¶m); - if (result != 0){ - if (errno == EPERM) - return RT_NO_PRIVS; - else { - perror ("sched_setscheduler: failed to set real time priority"); - return RT_OTHER_ERROR; - } - } - - //printf("SCHED_FIFO enabled with priority = %d\n", pri); - return RT_OK; - } - -} // namespace gr - -#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) - -#include <windows.h> - -namespace gr { - - rt_status_t enable_realtime_scheduling(rt_sched_param p){ - - //set the priority class on the process - int pri_class = (true)? REALTIME_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS; - if (SetPriorityClass(GetCurrentProcess(), pri_class) == 0) - return RT_OTHER_ERROR; - - //scale the priority value to the constants - int priorities[] = { - THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL, - THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL - }; - const double priority = double(p.priority)/(rt_priority_max() - rt_priority_min()); - size_t pri_index = size_t((priority+1.0)*6/2.0); // -1 -> 0, +1 -> 6 - pri_index %= sizeof(priorities)/sizeof(*priorities); //range check - - //set the thread priority on the thread - if (SetThreadPriority(GetCurrentThread(), priorities[pri_index]) == 0) - return RT_OTHER_ERROR; - - //printf("SetPriorityClass + SetThreadPriority\n"); - return RT_OK; - } - -} // namespace gr - -#else +#include <gnuradio/realtime.h> namespace gr { - + rt_status_t - enable_realtime_scheduling(rt_sched_param p) + enable_realtime_scheduling() { - return RT_NOT_IMPLEMENTED; + return enable_realtime_scheduling(); } -} // namespace gr -#endif +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/realtime_impl.cc b/gnuradio-runtime/lib/realtime_impl.cc new file mode 100644 index 0000000000..5dadc26bbd --- /dev/null +++ b/gnuradio-runtime/lib/realtime_impl.cc @@ -0,0 +1,178 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2007,2008 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <realtime.h> + +#ifdef HAVE_SCHED_H +#include <sched.h> +#endif + +#include <algorithm> +#include <math.h> +#include <string.h> +#include <errno.h> +#include <stdio.h> + +#if defined(HAVE_PTHREAD_SETSCHEDPARAM) || defined(HAVE_SCHED_SETSCHEDULER) +#include <pthread.h> + +namespace gr { + + /*! + * Rescale our virtual priority so that it maps to the middle 1/2 of + * the priorities given by min_real_pri and max_real_pri. + */ + static int + rescale_virtual_pri(int virtual_pri, int min_real_pri, int max_real_pri) + { + float rmin = min_real_pri + (0.25 * (max_real_pri - min_real_pri)); + float rmax = min_real_pri + (0.75 * (max_real_pri - min_real_pri)); + float m = (rmax - rmin) / (rt_priority_max() - rt_priority_min()); + float y = m * (virtual_pri - rt_priority_min()) + rmin; + int y_int = static_cast<int>(rint(y)); + return std::max(min_real_pri, std::min(max_real_pri, y_int)); + } + +} // namespace gr + +#endif + + +#if defined(HAVE_PTHREAD_SETSCHEDPARAM) + +namespace gr { + + rt_status_t + enable_realtime_scheduling(rt_sched_param p) + { + int policy = p.policy == RT_SCHED_FIFO ? SCHED_FIFO : SCHED_RR; + int min_real_pri = sched_get_priority_min(policy); + int max_real_pri = sched_get_priority_max(policy); + int pri = rescale_virtual_pri(p.priority, min_real_pri, max_real_pri); + + // FIXME check hard and soft limits with getrlimit, and limit the value we ask for. + // fprintf(stderr, "pthread_setschedparam: policy = %d, pri = %d\n", policy, pri); + + struct sched_param param; + memset (¶m, 0, sizeof (param)); + param.sched_priority = pri; + int result = pthread_setschedparam (pthread_self(), policy, ¶m); + if (result != 0) { + if (result == EPERM) // N.B., return value, not errno + return RT_NO_PRIVS; + else { + fprintf(stderr, + "pthread_setschedparam: failed to set real time priority: %s\n", + strerror(result)); + return RT_OTHER_ERROR; + } + } + + //printf("SCHED_FIFO enabled with priority = %d\n", pri); + return RT_OK; + } +} // namespace gr + + +#elif defined(HAVE_SCHED_SETSCHEDULER) + +namespace gr { + + rt_status_t + enable_realtime_scheduling(rt_sched_param p) + { + int policy = p.policy == RT_SCHED_FIFO ? SCHED_FIFO : SCHED_RR; + int min_real_pri = sched_get_priority_min(policy); + int max_real_pri = sched_get_priority_max(policy); + int pri = rescale_virtual_pri(p.priority, min_real_pri, max_real_pri); + + // FIXME check hard and soft limits with getrlimit, and limit the value we ask for. + // fprintf(stderr, "sched_setscheduler: policy = %d, pri = %d\n", policy, pri); + + int pid = 0; // this process + struct sched_param param; + memset(¶m, 0, sizeof(param)); + param.sched_priority = pri; + int result = sched_setscheduler(pid, policy, ¶m); + if (result != 0){ + if (errno == EPERM) + return RT_NO_PRIVS; + else { + perror ("sched_setscheduler: failed to set real time priority"); + return RT_OTHER_ERROR; + } + } + + //printf("SCHED_FIFO enabled with priority = %d\n", pri); + return RT_OK; + } + +} // namespace gr + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + +#include <windows.h> + +namespace gr { + + rt_status_t enable_realtime_scheduling(rt_sched_param p){ + + //set the priority class on the process + int pri_class = (true)? REALTIME_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS; + if (SetPriorityClass(GetCurrentProcess(), pri_class) == 0) + return RT_OTHER_ERROR; + + //scale the priority value to the constants + int priorities[] = { + THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL, + THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL + }; + const double priority = double(p.priority)/(rt_priority_max() - rt_priority_min()); + size_t pri_index = size_t((priority+1.0)*6/2.0); // -1 -> 0, +1 -> 6 + pri_index %= sizeof(priorities)/sizeof(*priorities); //range check + + //set the thread priority on the thread + if (SetThreadPriority(GetCurrentThread(), priorities[pri_index]) == 0) + return RT_OTHER_ERROR; + + //printf("SetPriorityClass + SetThreadPriority\n"); + return RT_OK; + } + +} // namespace gr + +#else + +namespace gr { + + rt_status_t + enable_realtime_scheduling(rt_sched_param p) + { + return RT_NOT_IMPLEMENTED; + } +} // namespace gr + +#endif diff --git a/gnuradio-runtime/lib/runtime_block_gateway.cc b/gnuradio-runtime/lib/runtime_block_gateway.cc deleted file mode 100644 index 11d16af41e..0000000000 --- a/gnuradio-runtime/lib/runtime_block_gateway.cc +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright 2011-2012 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include <runtime_block_gateway.h> -#include <gr_io_signature.h> -#include <iostream> -#include <boost/bind.hpp> - -/*********************************************************************** - * Helper routines - **********************************************************************/ -template <typename OutType, typename InType> -void copy_pointers(OutType &out, const InType &in){ - out.resize(in.size()); - for (size_t i = 0; i < in.size(); i++){ - out[i] = (void *)(in[i]); - } -} - -/*********************************************************************** - * The gr_block gateway implementation class - **********************************************************************/ -class runtime_block_gateway_impl : public runtime_block_gateway{ -public: - runtime_block_gateway_impl( - gr_feval_ll *handler, - const std::string &name, - gr_io_signature_sptr in_sig, - gr_io_signature_sptr out_sig, - const gr_block_gw_work_type work_type, - const unsigned factor - ): - gr_block(name, in_sig, out_sig), - _handler(handler), - _work_type(work_type) - { - switch(_work_type){ - case GR_BLOCK_GW_WORK_GENERAL: - _decim = 1; //not relevant, but set anyway - _interp = 1; //not relevant, but set anyway - break; - - case GR_BLOCK_GW_WORK_SYNC: - _decim = 1; - _interp = 1; - this->set_fixed_rate(true); - break; - - case GR_BLOCK_GW_WORK_DECIM: - _decim = factor; - _interp = 1; - break; - - case GR_BLOCK_GW_WORK_INTERP: - _decim = 1; - _interp = factor; - this->set_output_multiple(_interp); - break; - } - } - - /******************************************************************* - * Overloads for various scheduler-called functions - ******************************************************************/ - void forecast( - int noutput_items, - gr_vector_int &ninput_items_required - ){ - switch(_work_type){ - case GR_BLOCK_GW_WORK_GENERAL: - _message.action = gr_block_gw_message_type::ACTION_FORECAST; - _message.forecast_args_noutput_items = noutput_items; - _message.forecast_args_ninput_items_required = ninput_items_required; - _handler->calleval(0); - ninput_items_required = _message.forecast_args_ninput_items_required; - return; - - default: - unsigned ninputs = ninput_items_required.size(); - for (unsigned i = 0; i < ninputs; i++) - ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items); - return; - } - } - - int general_work( - int noutput_items, - gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items - ){ - switch(_work_type){ - case GR_BLOCK_GW_WORK_GENERAL: - _message.action = gr_block_gw_message_type::ACTION_GENERAL_WORK; - _message.general_work_args_noutput_items = noutput_items; - _message.general_work_args_ninput_items = ninput_items; - copy_pointers(_message.general_work_args_input_items, input_items); - _message.general_work_args_output_items = output_items; - _handler->calleval(0); - return _message.general_work_args_return_value; - - default: - int r = work (noutput_items, input_items, output_items); - if (r > 0) consume_each(r*_decim/_interp); - return r; - } - } - - int work( - int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items - ){ - _message.action = gr_block_gw_message_type::ACTION_WORK; - _message.work_args_ninput_items = fixed_rate_noutput_to_ninput(noutput_items); - if (_message.work_args_ninput_items == 0) return -1; - _message.work_args_noutput_items = noutput_items; - copy_pointers(_message.work_args_input_items, input_items); - _message.work_args_output_items = output_items; - _handler->calleval(0); - return _message.work_args_return_value; - } - - int fixed_rate_noutput_to_ninput(int noutput_items){ - return (noutput_items*_decim/_interp) + history() - 1; - } - - int fixed_rate_ninput_to_noutput(int ninput_items){ - return std::max(0, ninput_items - (int)history() + 1)*_interp/_decim; - } - - bool start(void){ - _message.action = gr_block_gw_message_type::ACTION_START; - _handler->calleval(0); - return _message.start_args_return_value; - } - - bool stop(void){ - _message.action = gr_block_gw_message_type::ACTION_STOP; - _handler->calleval(0); - return _message.stop_args_return_value; - } - - gr_block_gw_message_type &gr_block_message(void){ - return _message; - } - -private: - gr_feval_ll *_handler; - gr_block_gw_message_type _message; - const gr_block_gw_work_type _work_type; - unsigned _decim, _interp; -}; - -boost::shared_ptr<runtime_block_gateway> runtime_make_block_gateway( - gr_feval_ll *handler, - const std::string &name, - gr_io_signature_sptr in_sig, - gr_io_signature_sptr out_sig, - const gr_block_gw_work_type work_type, - const unsigned factor -){ - return boost::shared_ptr<runtime_block_gateway>( - new runtime_block_gateway_impl(handler, name, in_sig, out_sig, - work_type, factor) - ); -} diff --git a/gnuradio-runtime/lib/gr_scheduler.cc b/gnuradio-runtime/lib/scheduler.cc index c691f5d99f..38d95e6fb2 100644 --- a/gnuradio-runtime/lib/gr_scheduler.cc +++ b/gnuradio-runtime/lib/scheduler.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008 Free Software Foundation, Inc. + * Copyright 2008,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -22,12 +22,18 @@ #ifdef HAVE_CONFIG_H #include <config.h> #endif -#include <gr_scheduler.h> -gr_scheduler::gr_scheduler(gr_flat_flowgraph_sptr ffg, int max_noutput_items) -{ -} +#include "scheduler.h" -gr_scheduler::~gr_scheduler() -{ -} +namespace gr { + + scheduler::scheduler(flat_flowgraph_sptr ffg, + int max_noutput_items) + { + } + + scheduler::~scheduler() + { + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/scheduler.h b/gnuradio-runtime/lib/scheduler.h new file mode 100644 index 0000000000..575862b27d --- /dev/null +++ b/gnuradio-runtime/lib/scheduler.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2013 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 3, 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_GR_SCHEDULER_H +#define INCLUDED_GR_SCHEDULER_H + +#include <gnuradio/api.h> +#include <boost/utility.hpp> +#include <gnuradio/block.h> +#include "flat_flowgraph.h" + +namespace gr { + + class scheduler; + typedef boost::shared_ptr<scheduler> scheduler_sptr; + + /*! + * \brief Abstract scheduler that takes a flattened flow graph and + * runs it. + * + * Preconditions: details, buffers and buffer readers have been + * assigned. + */ + class GR_RUNTIME_API scheduler : boost::noncopyable + { + public: + /*! + * \brief Construct a scheduler and begin evaluating the graph. + * + * The scheduler will continue running until all blocks until they + * report that they are done or the stop method is called. + */ + scheduler(flat_flowgraph_sptr ffg, int max_noutput_items); + + virtual ~scheduler(); + + /*! + * \brief Tell the scheduler to stop executing. + */ + virtual void stop() = 0; + + /*! + * \brief Block until the graph is done. + */ + virtual void wait() = 0; + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_SCHEDULER_H */ diff --git a/gnuradio-runtime/lib/scheduler_sts.cc b/gnuradio-runtime/lib/scheduler_sts.cc new file mode 100644 index 0000000000..cc60b55f02 --- /dev/null +++ b/gnuradio-runtime/lib/scheduler_sts.cc @@ -0,0 +1,90 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2013 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 3, 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 <config.h> +#endif + +#include "scheduler_sts.h" +#include <gnuradio/single_threaded_scheduler.h> +#include <gnuradio/thread/thread_body_wrapper.h> + +namespace gr { + + class sts_container + { + block_vector_t d_blocks; + + public: + sts_container(block_vector_t blocks) + : d_blocks(blocks) {} + + void operator()() + { + make_single_threaded_scheduler(d_blocks)->run(); + } + }; + + scheduler_sptr + scheduler_sts::make(flat_flowgraph_sptr ffg, int max_noutput_items) + { + return scheduler_sptr(new scheduler_sts(ffg, max_noutput_items)); + } + + scheduler_sts::scheduler_sts(flat_flowgraph_sptr ffg, int max_noutput_items) + : scheduler(ffg, max_noutput_items) + { + // Split the flattened flow graph into discrete partitions, each + // of which is topologically sorted. + + std::vector<basic_block_vector_t> graphs = ffg->partition(); + + // For each partition, create a thread to evaluate it using + // an instance of the gr_single_threaded_scheduler + + for(std::vector<basic_block_vector_t>::iterator p = graphs.begin(); + p != graphs.end(); p++) { + + block_vector_t blocks = flat_flowgraph::make_block_vector(*p); + d_threads.create_thread( + gr::thread::thread_body_wrapper<sts_container>(sts_container(blocks), + "single-threaded-scheduler")); + } + } + + scheduler_sts::~scheduler_sts() + { + stop(); + } + + void + scheduler_sts::stop() + { + d_threads.interrupt_all(); + } + + void + scheduler_sts::wait() + { + d_threads.join_all(); + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/scheduler_sts.h b/gnuradio-runtime/lib/scheduler_sts.h new file mode 100644 index 0000000000..b4cddb4614 --- /dev/null +++ b/gnuradio-runtime/lib/scheduler_sts.h @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2013 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 3, 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_GR_SCHEDULER_STS_H +#define INCLUDED_GR_SCHEDULER_STS_H + +#include <gnuradio/api.h> +#include <gnuradio/thread/thread_group.h> +#include "scheduler.h" + +namespace gr { + + /*! + * \brief Concrete scheduler that uses the single_threaded_scheduler + */ + class GR_RUNTIME_API scheduler_sts : public scheduler + { + gr::thread::thread_group d_threads; + + protected: + /*! + * \brief Construct a scheduler and begin evaluating the graph. + * + * The scheduler will continue running until all blocks until they + * report that they are done or the stop method is called. + */ + scheduler_sts(flat_flowgraph_sptr ffg, int max_noutput_items); + + public: + static scheduler_sptr make(flat_flowgraph_sptr ffg, + int max_noutput_items); + + ~scheduler_sts(); + + /*! + * \brief Tell the scheduler to stop executing. + */ + void stop(); + + /*! + * \brief Block until the graph is done. + */ + void wait(); + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_SCHEDULER_STS_H */ diff --git a/gnuradio-runtime/lib/scheduler_tpb.cc b/gnuradio-runtime/lib/scheduler_tpb.cc new file mode 100644 index 0000000000..d35c37fb34 --- /dev/null +++ b/gnuradio-runtime/lib/scheduler_tpb.cc @@ -0,0 +1,106 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2013 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 3, 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 <config.h> +#endif + +#include "scheduler_tpb.h" +#include "tpb_thread_body.h" +#include <gnuradio/thread/thread_body_wrapper.h> +#include <sstream> + +namespace gr { + + class tpb_container + { + block_sptr d_block; + int d_max_noutput_items; + + public: + tpb_container(block_sptr block, int max_noutput_items) + : d_block(block), d_max_noutput_items(max_noutput_items) {} + + void operator()() + { + tpb_thread_body body(d_block, d_max_noutput_items); + } + }; + + scheduler_sptr + scheduler_tpb::make(flat_flowgraph_sptr ffg, int max_noutput_items) + { + return scheduler_sptr(new scheduler_tpb(ffg, max_noutput_items)); + } + + scheduler_tpb::scheduler_tpb(flat_flowgraph_sptr ffg, + int max_noutput_items) + : scheduler(ffg, max_noutput_items) + { + // Get a topologically sorted vector of all the blocks in use. + // Being topologically sorted probably isn't going to matter, but + // there's a non-zero chance it might help... + + basic_block_vector_t used_blocks = ffg->calc_used_blocks(); + used_blocks = ffg->topological_sort(used_blocks); + block_vector_t blocks = flat_flowgraph::make_block_vector(used_blocks); + + // Ensure that the done flag is clear on all blocks + + for(size_t i = 0; i < blocks.size(); i++) { + blocks[i]->detail()->set_done(false); + } + + // Fire off a thead for each block + + for(size_t i = 0; i < blocks.size(); i++) { + std::stringstream name; + name << "thread-per-block[" << i << "]: " << blocks[i]; + + // If set, use internal value instead of global value + if(blocks[i]->is_set_max_noutput_items()) + max_noutput_items = blocks[i]->max_noutput_items(); + + d_threads.create_thread( + gr::thread::thread_body_wrapper<tpb_container> + (tpb_container(blocks[i], max_noutput_items), + name.str())); + } + } + + scheduler_tpb::~scheduler_tpb() + { + stop(); + } + + void + scheduler_tpb::stop() + { + d_threads.interrupt_all(); + } + + void + scheduler_tpb::wait() + { + d_threads.join_all(); + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/scheduler_tpb.h b/gnuradio-runtime/lib/scheduler_tpb.h new file mode 100644 index 0000000000..f5ab21f269 --- /dev/null +++ b/gnuradio-runtime/lib/scheduler_tpb.h @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2013 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 3, 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_GR_SCHEDULER_TPB_H +#define INCLUDED_GR_SCHEDULER_TPB_H + +#include <gnuradio/api.h> +#include <gnuradio/thread/thread_group.h> +#include "scheduler.h" + +namespace gr { + + /*! + * \brief Concrete scheduler that uses a kernel thread-per-block + */ + class GR_RUNTIME_API scheduler_tpb : public scheduler + { + gr::thread::thread_group d_threads; + + protected: + /*! + * \brief Construct a scheduler and begin evaluating the graph. + * + * The scheduler will continue running until all blocks until they + * report that they are done or the stop method is called. + */ + scheduler_tpb(flat_flowgraph_sptr ffg, int max_noutput_items); + + public: + static scheduler_sptr make(flat_flowgraph_sptr ffg, + int max_noutput_items=100000); + + ~scheduler_tpb(); + + /*! + * \brief Tell the scheduler to stop executing. + */ + void stop(); + + /*! + * \brief Block until the graph is done. + */ + void wait(); + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_SCHEDULER_TPB_H */ diff --git a/gnuradio-runtime/lib/gr_select_handler.cc b/gnuradio-runtime/lib/select_handler.cc index 0fc86354a6..ca99ce6ce8 100644 --- a/gnuradio-runtime/lib/gr_select_handler.cc +++ b/gnuradio-runtime/lib/select_handler.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2005,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -24,13 +24,17 @@ #include "config.h" #endif -#include <gr_select_handler.h> +#include <gnuradio/select_handler.h> -gr_select_handler::gr_select_handler(int fd) - : d_fd(fd) -{ -} +namespace gr { -gr_select_handler::~gr_select_handler() -{ -} + select_handler::select_handler(int fd) + : d_fd(fd) + { + } + + select_handler::~select_handler() + { + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/single_threaded_scheduler.cc b/gnuradio-runtime/lib/single_threaded_scheduler.cc new file mode 100644 index 0000000000..0d7f91670b --- /dev/null +++ b/gnuradio-runtime/lib/single_threaded_scheduler.cc @@ -0,0 +1,363 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/single_threaded_scheduler.h> +#include <gnuradio/block.h> +#include <gnuradio/block_detail.h> +#include <gnuradio/buffer.h> +#include <boost/thread.hpp> +#include <boost/format.hpp> +#include <iostream> +#include <limits> +#include <assert.h> +#include <stdio.h> + +namespace gr { + + // must be defined to either 0 or 1 +#define ENABLE_LOGGING 0 + +#if (ENABLE_LOGGING) +#define LOG(x) do { x; } while(0) +#else +#define LOG(x) do {;} while(0) +#endif + + static int which_scheduler = 0; + + single_threaded_scheduler_sptr + make_single_threaded_scheduler(const std::vector<block_sptr> &blocks) + { + return single_threaded_scheduler_sptr + (new single_threaded_scheduler(blocks)); + } + + single_threaded_scheduler::single_threaded_scheduler(const std::vector<block_sptr> &blocks) + : d_blocks(blocks), d_enabled(true), d_log(0) + { + if(ENABLE_LOGGING) { + std::string name = str(boost::format("sst-%d.log") % which_scheduler++); + d_log = new std::ofstream(name.c_str()); + *d_log << "single_threaded_scheduler: " + << d_blocks.size () + << " blocks\n"; + } + } + + single_threaded_scheduler::~single_threaded_scheduler() + { + if(ENABLE_LOGGING) + delete d_log; + } + + void + single_threaded_scheduler::run() + { + // d_enabled = true; // KLUDGE + main_loop (); + } + + void + single_threaded_scheduler::stop() + { + if(0) + std::cout << "gr_singled_threaded_scheduler::stop() " + << this << std::endl; + d_enabled = false; + } + + inline static unsigned int + round_up(unsigned int n, unsigned int multiple) + { + return ((n + multiple - 1) / multiple) * multiple; + } + + inline static unsigned int + round_down(unsigned int n, unsigned int multiple) + { + return (n / multiple) * multiple; + } + + // + // Return minimum available write space in all our downstream + // buffers or -1 if we're output blocked and the output we're + // blocked on is done. + // + static int + min_available_space(block_detail *d, int output_multiple) + { + int min_space = std::numeric_limits<int>::max(); + + for(int i = 0; i < d->noutputs (); i++) { + int n = round_down (d->output(i)->space_available (), output_multiple); + if(n == 0) { // We're blocked on output. + if(d->output(i)->done()) { // Downstream is done, therefore we're done. + return -1; + } + return 0; + } + min_space = std::min (min_space, n); + } + return min_space; + } + + void + single_threaded_scheduler::main_loop() + { + static const int DEFAULT_CAPACITY = 16; + + int noutput_items; + gr_vector_int ninput_items_required(DEFAULT_CAPACITY); + gr_vector_int ninput_items(DEFAULT_CAPACITY); + gr_vector_const_void_star input_items(DEFAULT_CAPACITY); + gr_vector_void_star output_items(DEFAULT_CAPACITY); + unsigned int bi; + unsigned int nalive; + int max_items_avail; + bool made_progress_last_pass; + bool making_progress; + + for(unsigned i = 0; i < d_blocks.size (); i++) + d_blocks[i]->detail()->set_done (false); // reset any done flags + + for(unsigned i = 0; i < d_blocks.size (); i++) // enable any drivers, etc. + d_blocks[i]->start(); + + bi = 0; + made_progress_last_pass = true; + making_progress = false; + + // Loop while there are still blocks alive + + nalive = d_blocks.size (); + while(d_enabled && nalive > 0) { + if(boost::this_thread::interruption_requested()) + break; + + block *m = d_blocks[bi].get (); + block_detail *d = m->detail().get (); + + LOG(*d_log << std::endl << m); + + if(d->done ()) + goto next_block; + + if(d->source_p ()) { + // Invoke sources as a last resort. As long as the previous + // pass made progress, don't call a source. + if(made_progress_last_pass) { + LOG(*d_log << " Skipping source\n"); + goto next_block; + } + + ninput_items_required.resize (0); + ninput_items.resize (0); + input_items.resize (0); + output_items.resize (d->noutputs ()); + + // determine the minimum available output space + noutput_items = min_available_space (d, m->output_multiple ()); + LOG(*d_log << " source\n noutput_items = " << noutput_items << std::endl); + if(noutput_items == -1) // we're done + goto were_done; + + if(noutput_items == 0) { // we're output blocked + LOG(*d_log << " BLKD_OUT\n"); + goto next_block; + } + + goto setup_call_to_work; // jump to common code + } + + else if(d->sink_p ()) { + ninput_items_required.resize (d->ninputs ()); + ninput_items.resize (d->ninputs ()); + input_items.resize (d->ninputs ()); + output_items.resize (0); + LOG(*d_log << " sink\n"); + + max_items_avail = 0; + for(int i = 0; i < d->ninputs (); i++) { + ninput_items[i] = d->input(i)->items_available(); + //if (ninput_items[i] == 0 && d->input(i)->done()) + if(ninput_items[i] < m->output_multiple() && d->input(i)->done()) + goto were_done; + + max_items_avail = std::max (max_items_avail, ninput_items[i]); + } + + // take a swag at how much output we can sink + noutput_items = (int) (max_items_avail * m->relative_rate ()); + noutput_items = round_down (noutput_items, m->output_multiple ()); + LOG(*d_log << " max_items_avail = " << max_items_avail << std::endl); + LOG(*d_log << " noutput_items = " << noutput_items << std::endl); + + if(noutput_items == 0) { // we're blocked on input + LOG(*d_log << " BLKD_IN\n"); + goto next_block; + } + + goto try_again; // Jump to code shared with regular case. + } + + else { + // do the regular thing + ninput_items_required.resize(d->ninputs ()); + ninput_items.resize(d->ninputs ()); + input_items.resize(d->ninputs ()); + output_items.resize(d->noutputs ()); + + max_items_avail = 0; + for(int i = 0; i < d->ninputs (); i++) { + ninput_items[i] = d->input(i)->items_available (); + max_items_avail = std::max(max_items_avail, ninput_items[i]); + } + + // determine the minimum available output space + noutput_items = min_available_space(d, m->output_multiple ()); + if(ENABLE_LOGGING){ + *d_log << " regular "; + if(m->relative_rate() >= 1.0) + *d_log << "1:" << m->relative_rate() << std::endl; + else + *d_log << 1.0/m->relative_rate() << ":1\n"; + *d_log << " max_items_avail = " << max_items_avail << std::endl; + *d_log << " noutput_items = " << noutput_items << std::endl; + } + if(noutput_items == -1) // we're done + goto were_done; + + if(noutput_items == 0) { // we're output blocked + LOG(*d_log << " BLKD_OUT\n"); + goto next_block; + } + +#if 0 + // Compute best estimate of noutput_items that we can really use. + noutput_items = + std::min((unsigned)noutput_items, + std::max((unsigned)m->output_multiple(), + round_up((unsigned)(max_items_avail * m->relative_rate()), + m->output_multiple()))); + + LOG(*d_log << " revised noutput_items = " << noutput_items << std::endl); +#endif + + try_again: + if(m->fixed_rate()) { + // try to work it forward starting with max_items_avail. + // We want to try to consume all the input we've got. + int reqd_noutput_items = m->fixed_rate_ninput_to_noutput(max_items_avail); + reqd_noutput_items = round_up(reqd_noutput_items, m->output_multiple()); + if(reqd_noutput_items > 0 && reqd_noutput_items <= noutput_items) + noutput_items = reqd_noutput_items; + } + + // ask the block how much input they need to produce noutput_items + m->forecast(noutput_items, ninput_items_required); + + // See if we've got sufficient input available + int i; + for(i = 0; i < d->ninputs (); i++) + if(ninput_items_required[i] > ninput_items[i]) // not enough + break; + + if(i < d->ninputs()) { // not enough input on input[i] + // if we can, try reducing the size of our output request + if(noutput_items > m->output_multiple ()){ + noutput_items /= 2; + noutput_items = round_up (noutput_items, m->output_multiple ()); + goto try_again; + } + + // We're blocked on input + LOG(*d_log << " BLKD_IN\n"); + if(d->input(i)->done()) // If the upstream block is done, we're done + goto were_done; + + // Is it possible to ever fulfill this request? + if(ninput_items_required[i] > d->input(i)->max_possible_items_available ()) { + // Nope, never going to happen... + std::cerr << "\nsched: <block " << m->name() + << " (" << m->unique_id() << ")>" + << " is requesting more input data\n" + << " than we can provide.\n" + << " ninput_items_required = " + << ninput_items_required[i] << "\n" + << " max_possible_items_available = " + << d->input(i)->max_possible_items_available() << "\n" + << " If this is a filter, consider reducing the number of taps.\n"; + goto were_done; + } + + goto next_block; + } + + // We've got enough data on each input to produce noutput_items. + // Finish setting up the call to work. + for(int i = 0; i < d->ninputs (); i++) + input_items[i] = d->input(i)->read_pointer(); + + setup_call_to_work: + + for(int i = 0; i < d->noutputs (); i++) + output_items[i] = d->output(i)->write_pointer(); + + // Do the actual work of the block + int n = m->general_work(noutput_items, ninput_items, + input_items, output_items); + LOG(*d_log << " general_work: noutput_items = " << noutput_items + << " result = " << n << std::endl); + + if(n == -1) // block is done + goto were_done; + + d->produce_each(n); // advance write pointers + if(n > 0) + making_progress = true; + + goto next_block; + } + assert(0); + + were_done: + LOG(*d_log << " were_done\n"); + d->set_done (true); + nalive--; + + next_block: + if(++bi >= d_blocks.size ()) { + bi = 0; + made_progress_last_pass = making_progress; + making_progress = false; + } + } + + for(unsigned i = 0; i < d_blocks.size(); i++) // disable any drivers, etc. + d_blocks[i]->stop(); + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/gr_sptr_magic.cc b/gnuradio-runtime/lib/sptr_magic.cc index 2073701422..70596abb05 100644 --- a/gnuradio-runtime/lib/gr_sptr_magic.cc +++ b/gnuradio-runtime/lib/sptr_magic.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008,2009 Free Software Foundation, Inc. + * Copyright 2008,2009,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -18,54 +18,54 @@ * 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 <config.h> #endif -#include <gr_sptr_magic.h> -#include <gr_hier_block2.h> + +#include <gnuradio/sptr_magic.h> +#include <gnuradio/hier_block2.h> #include <map> #include <stdexcept> - -#include <thread/thread.h> +#include <gnuradio/thread/thread.h> namespace gnuradio { - static gr::thread::mutex s_mutex; - typedef std::map<gr_basic_block*, gr_basic_block_sptr> sptr_map; - static sptr_map s_map; + static gr::thread::mutex s_mutex; + typedef std::map<gr::basic_block*, gr::basic_block_sptr> sptr_map; + static sptr_map s_map; void - detail::sptr_magic::create_and_stash_initial_sptr(gr_hier_block2 *p) + detail::sptr_magic::create_and_stash_initial_sptr(gr::hier_block2 *p) { - gr_basic_block_sptr sptr(p); + gr::basic_block_sptr sptr(p); gr::thread::scoped_lock guard(s_mutex); - s_map.insert(sptr_map::value_type(static_cast<gr_basic_block *>(p), sptr)); + s_map.insert(sptr_map::value_type(static_cast<gr::basic_block *>(p), sptr)); } - - gr_basic_block_sptr - detail::sptr_magic::fetch_initial_sptr(gr_basic_block *p) + gr::basic_block_sptr + detail::sptr_magic::fetch_initial_sptr(gr::basic_block *p) { /* - * If p isn't a subclass of gr_hier_block2, just create the + * If p isn't a subclass of gr::hier_block2, just create the * shared ptr and return it. */ - gr_hier_block2 *hb2 = dynamic_cast<gr_hier_block2 *>(p); - if (!hb2){ - return gr_basic_block_sptr(p); + gr::hier_block2 *hb2 = dynamic_cast<gr::hier_block2 *>(p); + if(!hb2) { + return gr::basic_block_sptr(p); } /* - * p is a subclass of gr_hier_block2, thus we've already created the shared pointer + * p is a subclass of gr::hier_block2, thus we've already created the shared pointer * and stashed it away. Fish it out and return it. */ gr::thread::scoped_lock guard(s_mutex); - sptr_map::iterator pos = s_map.find(static_cast<gr_basic_block *>(p)); - if (pos == s_map.end()) - throw std::invalid_argument("gr_sptr_magic: invalid pointer!"); + sptr_map::iterator pos = s_map.find(static_cast<gr::basic_block *>(p)); + if(pos == s_map.end()) + throw std::invalid_argument("sptr_magic: invalid pointer!"); - gr_basic_block_sptr sptr = pos->second; + gr::basic_block_sptr sptr = pos->second; s_map.erase(pos); return sptr; } diff --git a/gnuradio-runtime/lib/sync_block.cc b/gnuradio-runtime/lib/sync_block.cc new file mode 100644 index 0000000000..e00b80c79e --- /dev/null +++ b/gnuradio-runtime/lib/sync_block.cc @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/sync_block.h> + +namespace gr { + + sync_block::sync_block(const std::string &name, + io_signature::sptr input_signature, + io_signature::sptr output_signature) + : block(name, input_signature, output_signature) + { + set_fixed_rate(true); + } + + void + sync_block::forecast(int noutput_items, + gr_vector_int &ninput_items_required) + { + unsigned ninputs = ninput_items_required.size(); + for(unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items); + } + + int + sync_block::fixed_rate_noutput_to_ninput(int noutput_items) + { + return noutput_items + history() - 1; + } + + int + sync_block::fixed_rate_ninput_to_noutput(int ninput_items) + { + return std::max(0, ninput_items - (int)history() + 1); + } + + int + sync_block::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int r = work(noutput_items, input_items, output_items); + if(r > 0) + consume_each(r); + return r; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/sync_decimator.cc b/gnuradio-runtime/lib/sync_decimator.cc new file mode 100644 index 0000000000..a9c2d1eeff --- /dev/null +++ b/gnuradio-runtime/lib/sync_decimator.cc @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/sync_decimator.h> + +namespace gr { + + sync_decimator::sync_decimator(const std::string &name, + io_signature::sptr input_signature, + io_signature::sptr output_signature, + unsigned decimation) + : sync_block(name, input_signature, output_signature) + { + set_decimation(decimation); + } + + void + sync_decimator::forecast(int noutput_items, gr_vector_int &ninput_items_required) + { + unsigned ninputs = ninput_items_required.size(); + for(unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items); + } + + int + sync_decimator::fixed_rate_noutput_to_ninput(int noutput_items) + { + return noutput_items * decimation() + history() - 1; + } + + int + sync_decimator::fixed_rate_ninput_to_noutput(int ninput_items) + { + return std::max(0, ninput_items - (int)history() + 1) / decimation(); + } + + int + sync_decimator::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int r = work(noutput_items, input_items, output_items); + if(r > 0) + consume_each(r * decimation ()); + return r; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/sync_interpolator.cc b/gnuradio-runtime/lib/sync_interpolator.cc new file mode 100644 index 0000000000..5721f24f0f --- /dev/null +++ b/gnuradio-runtime/lib/sync_interpolator.cc @@ -0,0 +1,73 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2008,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gnuradio/sync_interpolator.h> + +namespace gr { + + sync_interpolator::sync_interpolator(const std::string &name, + io_signature::sptr input_signature, + io_signature::sptr output_signature, + unsigned interpolation) + : sync_block(name, input_signature, output_signature) + { + set_interpolation(interpolation); + } + + void + sync_interpolator::forecast(int noutput_items, + gr_vector_int &ninput_items_required) + { + unsigned ninputs = ninput_items_required.size(); + for(unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items); + } + + int + sync_interpolator::fixed_rate_noutput_to_ninput(int noutput_items) + { + return noutput_items / interpolation() + history() - 1; + } + + int + sync_interpolator::fixed_rate_ninput_to_noutput(int ninput_items) + { + return std::max(0, ninput_items - (int)history() + 1) * interpolation(); + } + + int + sync_interpolator::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int r = work(noutput_items, input_items, output_items); + if(r > 0) + consume_each(r / interpolation()); + return r; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/gr_sys_paths.cc b/gnuradio-runtime/lib/sys_paths.cc index b4918af33d..64853c68b2 100644 --- a/gnuradio-runtime/lib/gr_sys_paths.cc +++ b/gnuradio-runtime/lib/sys_paths.cc @@ -1,5 +1,5 @@ /* - * Copyright 2011 Free Software Foundation, Inc. + * Copyright 2011,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -19,37 +19,47 @@ * Boston, MA 02110-1301, USA. */ -#include <gr_sys_paths.h> +#include <gnuradio/sys_paths.h> #include <cstdlib> //getenv #include <cstdio> //P_tmpdir (maybe) -const char *gr_tmp_path(){ +namespace gr { + + const char *tmp_path() + { const char *path; //first case, try TMP environment variable path = getenv("TMP"); - if (path) return path; + if(path) + return path; //second case, try P_tmpdir when its defined #ifdef P_tmpdir - if (P_tmpdir) return P_tmpdir; + if(P_tmpdir) + return P_tmpdir; #endif /*P_tmpdir*/ //fall-through case, nothing worked return "/tmp"; -} + } -const char *gr_appdata_path(){ + const char *appdata_path() + { const char *path; //first case, try HOME environment variable (unix) path = getenv("HOME"); - if (path) return path; + if(path) + return path; //second case, try APPDATA environment variable (windows) path = getenv("APPDATA"); - if (path) return path; + if(path) + return path; //fall-through case, nothing worked - return gr_tmp_path(); -} + return tmp_path(); + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/tagged_stream_block.cc b/gnuradio-runtime/lib/tagged_stream_block.cc new file mode 100644 index 0000000000..40febfdeca --- /dev/null +++ b/gnuradio-runtime/lib/tagged_stream_block.cc @@ -0,0 +1,144 @@ +/* -*- c++ -*- */ +/* + * Copyright 2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <boost/format.hpp> +#include <gnuradio/tagged_stream_block.h> + +namespace gr { + + tagged_stream_block::tagged_stream_block(const std::string &name, + io_signature::sptr input_signature, + io_signature::sptr output_signature, + const std::string &length_tag_key) + : block(name, input_signature, output_signature), + d_length_tag_key(pmt::string_to_symbol(length_tag_key)), + d_n_input_items_reqd(input_signature->min_streams(), 0), + d_length_tag_key_str(length_tag_key) + { + } + + // This is evil hackery: We trick the scheduler into creating the right number of input items + void + tagged_stream_block::forecast(int noutput_items, + gr_vector_int &ninput_items_required) + { + unsigned ninputs = ninput_items_required.size(); + for(unsigned i = 0; i < ninputs; i++) { + if (i < d_n_input_items_reqd.size() && d_n_input_items_reqd[i] != 0) { + ninput_items_required[i] = d_n_input_items_reqd[i]; + } + else { + // If there's no item, there's no tag--so there must at least be one! + ninput_items_required[i] = std::max(1, (int)std::floor((double) noutput_items / relative_rate() + 0.5)); + } + } + } + + void + tagged_stream_block::parse_length_tags(const std::vector<std::vector<tag_t> > &tags, + gr_vector_int &n_input_items_reqd) + { + for(unsigned i = 0; i < tags.size(); i++) { + for(unsigned k = 0; k < tags[i].size(); k++) { + if(tags[i][k].key == d_length_tag_key) { + n_input_items_reqd[i] = pmt::to_long(tags[i][k].value); + remove_item_tag(i, tags[i][k]); + } + } + } + } + + int + tagged_stream_block::calculate_output_stream_length(const gr_vector_int &ninput_items) + { + int noutput_items = *std::max_element(ninput_items.begin(), ninput_items.end()); + return (int)std::floor(relative_rate() * noutput_items + 0.5); + } + + void + tagged_stream_block::update_length_tags(int n_produced, int n_ports) + { + for(int i = 0; i < n_ports; i++) { + add_item_tag(i, nitems_written(i), + d_length_tag_key, + pmt::from_long(n_produced)); + } + return; + } + + int + tagged_stream_block::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + if(d_length_tag_key_str.empty()) { + return work(noutput_items, ninput_items, input_items, output_items); + } + + if(d_n_input_items_reqd[0] == 0) { // Otherwise, it's already set from a previous call + std::vector<std::vector<tag_t> > tags(input_items.size(), std::vector<tag_t>()); + for(unsigned i = 0; i < input_items.size(); i++) { + get_tags_in_range(tags[i], i, nitems_read(i), nitems_read(i)+1); + } + d_n_input_items_reqd.assign(input_items.size(), -1); + parse_length_tags(tags, d_n_input_items_reqd); + } + for(unsigned i = 0; i < input_items.size(); i++) { + if(d_n_input_items_reqd[i] == -1) { + GR_LOG_FATAL(d_logger, boost::format("Missing a required length tag on port %1% at item #%2%") % i % nitems_read(i)); + throw std::runtime_error("Missing length tag."); + } + if(d_n_input_items_reqd[i] > ninput_items[i]) { + return 0; + } + } + + int min_output_size = calculate_output_stream_length(d_n_input_items_reqd); + if(noutput_items < min_output_size) { + set_min_noutput_items(min_output_size); + return 0; + } + set_min_noutput_items(1); + + // WORK CALLED HERE // + int n_produced = work(noutput_items, d_n_input_items_reqd, input_items, output_items); + ////////////////////// + + if(n_produced == WORK_DONE) { + return n_produced; + } + for(int i = 0; i < (int) d_n_input_items_reqd.size(); i++) { + consume(i, d_n_input_items_reqd[i]); + } + update_length_tags(n_produced, output_items.size()); + + d_n_input_items_reqd.assign(input_items.size(), 0); + + return n_produced; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/test.cc b/gnuradio-runtime/lib/test.cc new file mode 100644 index 0000000000..775dc2bde4 --- /dev/null +++ b/gnuradio-runtime/lib/test.cc @@ -0,0 +1,181 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2008,2010,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "test.h" +#include <gnuradio/io_signature.h> +#include <stdexcept> +#include <iostream> +#include <string.h> + +namespace gr { + + test_sptr + make_test(const std::string &name, + int min_inputs, int max_inputs, unsigned int sizeof_input_item, + int min_outputs, int max_outputs, unsigned int sizeof_output_item, + unsigned int history, unsigned int output_multiple, double relative_rate, + bool fixed_rate, consume_type_t cons_type, produce_type_t prod_type) + { + return gnuradio::get_initial_sptr + (new test(name, min_inputs, max_inputs, sizeof_input_item, + min_outputs, max_outputs, sizeof_output_item, + history, output_multiple, relative_rate, + fixed_rate,cons_type, prod_type)); + } + + test::test(const std::string &name, + int min_inputs, int max_inputs, + unsigned int sizeof_input_item, + int min_outputs, int max_outputs, + unsigned int sizeof_output_item, + unsigned int history, + unsigned int output_multiple, + double relative_rate, + bool fixed_rate, + consume_type_t cons_type, produce_type_t prod_type) + : block (name, + io_signature::make(min_inputs, max_inputs, sizeof_input_item), + io_signature::make(min_outputs, max_outputs, sizeof_output_item)), + d_sizeof_input_item(sizeof_input_item), + d_sizeof_output_item(sizeof_output_item), + d_check_topology(true), + d_consume_type(cons_type), + d_min_consume(0), + d_max_consume(0), + d_produce_type(prod_type), + d_min_produce(0), + d_max_produce(0) + { + set_history(history); + set_output_multiple(output_multiple); + set_relative_rate(relative_rate); + set_fixed_rate(fixed_rate); + } + + int + test::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + //touch all inputs and outputs to detect segfaults + unsigned ninputs = input_items.size (); + unsigned noutputs= output_items.size(); + for(unsigned i = 0; i < ninputs; i++) { + char * in=(char *)input_items[i]; + if(ninput_items[i]< (int)(noutput_items+history())) { + std::cerr << "ERROR: ninput_items[" << i << "] < noutput_items+history()" << std::endl; + std::cerr << "ninput_items[" << i << "] = " << ninput_items[i] << std::endl; + std::cerr << "noutput_items+history() = " << noutput_items+history() << std::endl; + std::cerr << "noutput_items = " << noutput_items << std::endl; + std::cerr << "history() = " << history() << std::endl; + throw std::runtime_error ("test"); + } + else { + for (int j = 0; j < ninput_items[i]; j++) { + //Touch every available input_item + //We use a class variable to avoid the compiler to optimize this away + for(unsigned int k = 0; k < d_sizeof_input_item; k++) + d_temp= in[j*d_sizeof_input_item+k]; + } + switch(d_consume_type){ + case CONSUME_NOUTPUT_ITEMS: + consume(i,noutput_items); + break; + case CONSUME_NOUTPUT_ITEMS_LIMIT_MAX: + consume(i,std::min(noutput_items,d_max_consume)); + break; + case CONSUME_NOUTPUT_ITEMS_LIMIT_MIN: + consume(i,std::min(std::max(noutput_items,d_min_consume),ninput_items[i])); + break; + case CONSUME_ALL_AVAILABLE: + consume(i,ninput_items[i]); + break; + case CONSUME_ALL_AVAILABLE_LIMIT_MAX: + consume(i,std::min(ninput_items[i],d_max_consume)); + break; +/* //This could result in segfault, uncomment if you want to test this + case CONSUME_ALL_AVAILABLE_LIMIT_MIN: + consume(i,std::max(ninput_items[i],d_max_consume)); + break;*/ + case CONSUME_ZERO: + consume(i,0); + break; + case CONSUME_ONE: + consume(i,1); + break; + case CONSUME_MINUS_ONE: + consume(i,-1); + break; + default: + consume(i,noutput_items); + } + } + } + for(unsigned i = 0; i < noutputs; i++) { + char * out=(char *)output_items[i]; + { + for(int j=0;j<noutput_items;j++) { + //Touch every available output_item + for(unsigned int k=0;k<d_sizeof_output_item;k++) + out[j*d_sizeof_input_item+k]=0; + } + } + } + //Now copy input to output until max ninputs or max noutputs is reached + int common_nports=std::min(ninputs,noutputs); + if(d_sizeof_output_item==d_sizeof_input_item) + for(int i = 0; i < common_nports; i++) { + memcpy(output_items[i],input_items[i],noutput_items*d_sizeof_input_item); + } + int noutput_items_produced=0; + switch(d_produce_type) { + case PRODUCE_NOUTPUT_ITEMS: + noutput_items_produced=noutput_items; + break; + case PRODUCE_NOUTPUT_ITEMS_LIMIT_MAX: + noutput_items_produced=std::min(noutput_items,d_max_produce); + break; +/* //This could result in segfault, uncomment if you want to test this + case PRODUCE_NOUTPUT_ITEMS_LIMIT_MIN: + noutput_items_produced=std::max(noutput_items,d_min_produce); + break;*/ + case PRODUCE_ZERO: + noutput_items_produced=0; + break; + case PRODUCE_ONE: + noutput_items_produced=1; + break; + case PRODUCE_MINUS_ONE: + noutput_items_produced=-1; + break; + default: + noutput_items_produced=noutput_items; + } + return noutput_items_produced; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/test.h b/gnuradio-runtime/lib/test.h new file mode 100644 index 0000000000..cbe42f94e8 --- /dev/null +++ b/gnuradio-runtime/lib/test.h @@ -0,0 +1,225 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_TEST_H +#define INCLUDED_GR_TEST_H + +#include <gnuradio/api.h> +#include <gnuradio/block.h> +#include <string> +#include "test_types.h" + +namespace gr { + + class test; + typedef boost::shared_ptr<test> test_sptr; + + // public constructor + GR_RUNTIME_API test_sptr + make_test(const std::string &name=std::string("test"), + int min_inputs=1, int max_inputs=1, unsigned int sizeof_input_item=1, + int min_outputs=1, int max_outputs=1, unsigned int sizeof_output_item=1, + unsigned int history=1,unsigned int output_multiple=1,double relative_rate=1.0, + bool fixed_rate=true,consume_type_t cons_type=CONSUME_NOUTPUT_ITEMS, + produce_type_t prod_type=PRODUCE_NOUTPUT_ITEMS); + + /*! + * \brief Test class for testing runtime system (setting up buffers and such.) + * \ingroup misc + * + * This block does not do any usefull actual data processing. It + * just exposes setting all standard block parameters using the + * contructor or public methods. + * + * This block can be usefull when testing the runtime system. + * You can force this block to have a large history, decimation + * factor and/or large output_multiple. + * The runtime system should detect this and create large enough buffers + * all through the signal chain. + */ + class GR_RUNTIME_API test : public block + { + public: + ~test() {} + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + // ---------------------------------------------------------------- + // override these to define your behavior + // ---------------------------------------------------------------- + + /*! + * \brief Estimate input requirements given output request + * + * \param noutput_items number of output items to produce + * \param ninput_items_required number of input items required on each input stream + * + * Given a request to product \p noutput_items, estimate the + * number of data items required on each input stream. The + * estimate doesn't have to be exact, but should be close. + */ + void forecast(int noutput_items, + gr_vector_int &ninput_items_required) + { + unsigned ninputs = ninput_items_required.size(); + for(unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = (int)((double)noutput_items / relative_rate()) + (int)history(); + } + + /*! + * \brief Force check topology to return true or false. + * + * \param check_topology value to return when check_topology is + * called (true or false) default check_topology returns true + */ + void set_check_topology(bool check_topology) { + d_check_topology=check_topology; + } + + /*! + * \brief Confirm that ninputs and noutputs is an acceptable combination. + * + * \param ninputs number of input streams connected + * \param noutputs number of output streams connected + * + * \returns true if this is a valid configuration for this block. + * + * This function is called by the runtime system whenever the + * topology changes. Most classes do not need to override this. + * This check is in addition to the constraints specified by the + * input and output gr::io_signatures. + */ + bool check_topology(int ninputs, int noutputs) { + return d_check_topology; + } + + // ---------------------------------------------------------------- + /* + * The following two methods provide special case info to the + * scheduler in the event that a block has a fixed input to output + * ratio. gr::sync_block, gr::sync_decimator and + * gr::sync_interpolator override these. If you're fixed rate, + * subclass one of those. + */ + /*! + * \brief Given ninput samples, return number of output samples + * that will be produced. N.B. this is only defined if fixed_rate + * returns true. Generally speaking, you don't need to override + * this. + */ + int fixed_rate_ninput_to_noutput(int ninput) { + return (int)((double)ninput/relative_rate()); + } + + /*! + * \brief Given noutput samples, return number of input samples + * required to produce noutput. N.B. this is only defined if + * fixed_rate returns true. + */ + int fixed_rate_noutput_to_ninput(int noutput) { + return (int)((double)noutput*relative_rate()); + } + + /*! + * \brief Set if fixed rate should return true. + * N.B. This is normally a private method but we make it available here as public. + */ + void set_fixed_rate_public(bool fixed_rate) { + set_fixed_rate(fixed_rate); + } + + /*! + * \brief Set the consume pattern. + * + * \param cons_type which consume pattern to use + */ + void set_consume_type(consume_type_t cons_type) { + d_consume_type=cons_type; + } + + /*! + * \brief Set the consume limit. + * + * \param limit min or maximum items to consume (depending on + * consume_type) + */ + void set_consume_limit(unsigned int limit) { + d_min_consume=limit; d_max_consume=limit; + } + + /*! + * \brief Set the produce pattern. + * + * \param prod_type which produce pattern to use + */ + void set_produce_type(produce_type_t prod_type) { + d_produce_type=prod_type; + } + + /*! + * \brief Set the produce limit. + * + * \param limit min or maximum items to produce (depending on + * produce_type) + */ + void set_produce_limit(unsigned int limit) { + d_min_produce=limit; d_max_produce=limit; + } + + // ---------------------------------------------------------------------------- + + protected: + unsigned int d_sizeof_input_item; + unsigned int d_sizeof_output_item; + bool d_check_topology; + char d_temp; + consume_type_t d_consume_type; + int d_min_consume; + int d_max_consume; + produce_type_t d_produce_type; + int d_min_produce; + int d_max_produce; + test(const std::string &name,int min_inputs, int max_inputs, + unsigned int sizeof_input_item, + int min_outputs, int max_outputs, unsigned int sizeof_output_item, + unsigned int history, unsigned int output_multiple, double relative_rate, + bool fixed_rate, consume_type_t cons_type, produce_type_t prod_type); + + friend GR_RUNTIME_API test_sptr make_test(const std::string &name, + int min_inputs, int max_inputs, + unsigned int sizeof_input_item, + int min_outputs, int max_outputs, + unsigned int sizeof_output_item, + unsigned int history, + unsigned int output_multiple, + double relative_rate, + bool fixed_rate, + consume_type_t cons_type, + produce_type_t prod_type); + }; + +} /* namespace gr */ + +#endif /* INCLUDED_TEST_H */ diff --git a/gnuradio-runtime/lib/test_runtime.cc b/gnuradio-runtime/lib/test_runtime.cc index 7dc7b17ea0..c85d325174 100644 --- a/gnuradio-runtime/lib/test_runtime.cc +++ b/gnuradio-runtime/lib/test_runtime.cc @@ -27,7 +27,7 @@ #include <cppunit/TextTestRunner.h> #include <cppunit/XmlOutputter.h> -#include <gr_unittests.h> +#include <gnuradio/unittests.h> #include <qa_runtime.h> #include <pmt/qa_pmt.h> diff --git a/gnuradio-runtime/lib/gr_test_types.h b/gnuradio-runtime/lib/test_types.h index 04f38f7b26..868a9e62a3 100644 --- a/gnuradio-runtime/lib/gr_test_types.h +++ b/gnuradio-runtime/lib/test_types.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2006,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -19,28 +19,33 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ + #ifndef INCLUDED_GR_TEST_TYPES_H #define INCLUDED_GR_TEST_TYPES_H -typedef enum { - CONSUME_NOUTPUT_ITEMS=0, - CONSUME_NOUTPUT_ITEMS_LIMIT_MAX=1, - CONSUME_NOUTPUT_ITEMS_LIMIT_MIN=2, - CONSUME_ALL_AVAILABLE=3, - CONSUME_ALL_AVAILABLE_LIMIT_MAX=4, - /*CONSUME_ALL_AVAILABLE_LIMIT_MIN=5,*/ - CONSUME_ZERO=6, - CONSUME_ONE=7, - CONSUME_MINUS_ONE=8 - } gr_consume_type_t; +namespace gr { + + typedef enum { + CONSUME_NOUTPUT_ITEMS=0, + CONSUME_NOUTPUT_ITEMS_LIMIT_MAX=1, + CONSUME_NOUTPUT_ITEMS_LIMIT_MIN=2, + CONSUME_ALL_AVAILABLE=3, + CONSUME_ALL_AVAILABLE_LIMIT_MAX=4, + /*CONSUME_ALL_AVAILABLE_LIMIT_MIN=5,*/ + CONSUME_ZERO=6, + CONSUME_ONE=7, + CONSUME_MINUS_ONE=8 + } consume_type_t; + + typedef enum { + PRODUCE_NOUTPUT_ITEMS=0, + PRODUCE_NOUTPUT_ITEMS_LIMIT_MAX=1, + /*PRODUCE_NOUTPUT_ITEMS_LIMIT_MIN=2,*/ + PRODUCE_ZERO=6, + PRODUCE_ONE=7, + PRODUCE_MINUS_ONE=8 + } produce_type_t; -typedef enum { - PRODUCE_NOUTPUT_ITEMS=0, - PRODUCE_NOUTPUT_ITEMS_LIMIT_MAX=1, - /*PRODUCE_NOUTPUT_ITEMS_LIMIT_MIN=2,*/ - PRODUCE_ZERO=6, - PRODUCE_ONE=7, - PRODUCE_MINUS_ONE=8 - } gr_produce_type_t; +} /* namespace gr */ #endif /* INCLUDED_GR_TEST_TYPES_H */ diff --git a/gnuradio-runtime/lib/thread/thread.cc b/gnuradio-runtime/lib/thread/thread.cc index af0822445d..1727dc6621 100644 --- a/gnuradio-runtime/lib/thread/thread.cc +++ b/gnuradio-runtime/lib/thread/thread.cc @@ -23,7 +23,7 @@ #include <config.h> #endif -#include <thread/thread.h> +#include <gnuradio/thread/thread.h> #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) diff --git a/gnuradio-runtime/lib/thread/thread_body_wrapper.cc b/gnuradio-runtime/lib/thread/thread_body_wrapper.cc index 47feafdd42..e23b7d15d0 100644 --- a/gnuradio-runtime/lib/thread/thread_body_wrapper.cc +++ b/gnuradio-runtime/lib/thread/thread_body_wrapper.cc @@ -23,7 +23,7 @@ #include <config.h> #endif -#include <thread/thread_body_wrapper.h> +#include <gnuradio/thread/thread_body_wrapper.h> #ifdef HAVE_SIGNAL_H #include <signal.h> diff --git a/gnuradio-runtime/lib/thread/thread_group.cc b/gnuradio-runtime/lib/thread/thread_group.cc index 034fe82e75..e467dfda5a 100644 --- a/gnuradio-runtime/lib/thread/thread_group.cc +++ b/gnuradio-runtime/lib/thread/thread_group.cc @@ -12,7 +12,7 @@ * This was extracted from Boost 1.35.0 and fixed. */ -#include <thread/thread_group.h> +#include <gnuradio/thread/thread_group.h> namespace gr { namespace thread { diff --git a/gnuradio-runtime/lib/top_block.cc b/gnuradio-runtime/lib/top_block.cc new file mode 100644 index 0000000000..8d2e42bb12 --- /dev/null +++ b/gnuradio-runtime/lib/top_block.cc @@ -0,0 +1,167 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "top_block_impl.h" +#include <gnuradio/top_block.h> +#include <gnuradio/io_signature.h> +#include <gnuradio/prefs.h> +#include <unistd.h> +#include <iostream> + +namespace gr { + top_block_sptr + make_top_block(const std::string &name) + { + return gnuradio::get_initial_sptr + (new top_block(name)); + } + + top_block::top_block(const std::string &name) + : hier_block2(name, + io_signature::make(0,0,0), + io_signature::make(0,0,0)) + { + d_impl = new top_block_impl(this); + } + + top_block::~top_block() + { + stop(); + wait(); + + delete d_impl; + } + + void + top_block::start(int max_noutput_items) + { + d_impl->start(max_noutput_items); + + if(prefs::singleton()->get_bool("ControlPort", "on", false)) { + setup_rpc(); + } + } + + void + top_block::stop() + { + d_impl->stop(); + } + + void + top_block::wait() + { + d_impl->wait(); + } + + void + top_block::run(int max_noutput_items) + { + start(max_noutput_items); + wait(); + } + + void + top_block::lock() + { + d_impl->lock(); + } + + void + top_block::unlock() + { + d_impl->unlock(); + } + + std::string + top_block::edge_list() + { + return d_impl->edge_list(); + } + + void + top_block::dump() + { + d_impl->dump(); + } + + int + top_block::max_noutput_items() + { + return d_impl->max_noutput_items(); + } + + void + top_block::set_max_noutput_items(int nmax) + { + d_impl->set_max_noutput_items(nmax); + } + + top_block_sptr + top_block::to_top_block() + { + return cast_to_top_block_sptr(shared_from_this()); + } + + void + top_block::setup_rpc() + { +#ifdef GR_CTRLPORT + if(is_rpc_set()) + return; + + // Getters + add_rpc_variable( + rpcbasic_sptr(new rpcbasic_register_get<top_block, int>( + alias(), "max noutput_items", + &top_block::max_noutput_items, + pmt::mp(0), pmt::mp(8192), pmt::mp(8192), + "items", "Max number of output items", + RPC_PRIVLVL_MIN, DISPNULL))); + + if(prefs::singleton()->get_bool("ControlPort", "edges_list", false)) { + add_rpc_variable( + rpcbasic_sptr(new rpcbasic_register_get<top_block, std::string>( + alias(), "edge list", + &top_block::edge_list, + pmt::mp(""), pmt::mp(""), pmt::mp(""), + "edges", "List of edges in the graph", + RPC_PRIVLVL_MIN, DISPNULL))); + } + + // Setters + add_rpc_variable( + rpcbasic_sptr(new rpcbasic_register_set<top_block, int>( + alias(), "max noutput_items", + &top_block::set_max_noutput_items, + pmt::mp(0), pmt::mp(8192), pmt::mp(8192), + "items", "Max number of output items", + RPC_PRIVLVL_MIN, DISPNULL))); + rpc_set(); +#endif /* GR_CTRLPORT */ + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/top_block_impl.cc b/gnuradio-runtime/lib/top_block_impl.cc new file mode 100644 index 0000000000..9d377f469f --- /dev/null +++ b/gnuradio-runtime/lib/top_block_impl.cc @@ -0,0 +1,212 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2008,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "top_block_impl.h" +#include "flat_flowgraph.h" +#include "scheduler_sts.h" +#include "scheduler_tpb.h" +#include <gnuradio/top_block.h> +#include <gnuradio/prefs.h> + +#include <stdexcept> +#include <iostream> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> + +namespace gr { + +#define GR_TOP_BLOCK_IMPL_DEBUG 0 + + typedef scheduler_sptr(*scheduler_maker)(flat_flowgraph_sptr ffg, + int max_noutput_items); + + static struct scheduler_table { + const char *name; + scheduler_maker f; + } scheduler_table[] = { + { "TPB", scheduler_tpb::make }, // first entry is default + { "STS", scheduler_sts::make } + }; + + static scheduler_sptr + make_scheduler(flat_flowgraph_sptr ffg, int max_noutput_items) + { + static scheduler_maker factory = 0; + + if(factory == 0) { + char *v = getenv("GR_SCHEDULER"); + if(!v) + factory = scheduler_table[0].f; // use default + else { + for(size_t i = 0; i < sizeof(scheduler_table)/sizeof(scheduler_table[0]); i++) { + if(strcmp(v, scheduler_table[i].name) == 0) { + factory = scheduler_table[i].f; + break; + } + } + if(factory == 0) { + std::cerr << "warning: Invalid GR_SCHEDULER environment variable value \"" + << v << "\". Using \"" << scheduler_table[0].name << "\"\n"; + factory = scheduler_table[0].f; + } + } + } + return factory(ffg, max_noutput_items); + } + + top_block_impl::top_block_impl(top_block *owner) + : d_owner(owner), d_ffg(), + d_state(IDLE), d_lock_count(0) + { + } + + top_block_impl::~top_block_impl() + { + d_owner = 0; + } + + void + top_block_impl::start(int max_noutput_items) + { + gr::thread::scoped_lock l(d_mutex); + + d_max_noutput_items = max_noutput_items; + + if(d_state != IDLE) + throw std::runtime_error("top_block::start: top block already running or wait() not called after previous stop()"); + + if(d_lock_count > 0) + throw std::runtime_error("top_block::start: can't start with flow graph locked"); + + // Create new flat flow graph by flattening hierarchy + d_ffg = d_owner->flatten(); + + // Validate new simple flow graph and wire it up + d_ffg->validate(); + d_ffg->setup_connections(); + + // Only export perf. counters if ControlPort config param is + // enabled and if the PerfCounter option 'export' is turned on. + prefs *p = prefs::singleton(); + if(p->get_bool("ControlPort", "on", false) && p->get_bool("PerfCounters", "export", false)) + d_ffg->enable_pc_rpc(); + + d_scheduler = make_scheduler(d_ffg, d_max_noutput_items); + d_state = RUNNING; + } + + void + top_block_impl::stop() + { + if(d_scheduler) + d_scheduler->stop(); + } + + void + top_block_impl::wait() + { + if(d_scheduler) + d_scheduler->wait(); + + d_state = IDLE; + } + + // N.B. lock() and unlock() cannot be called from a flow graph + // thread or deadlock will occur when reconfiguration happens + void + top_block_impl::lock() + { + gr::thread::scoped_lock lock(d_mutex); + d_lock_count++; + } + + void + top_block_impl::unlock() + { + gr::thread::scoped_lock lock(d_mutex); + + if(d_lock_count <= 0) { + d_lock_count = 0; // fix it, then complain + throw std::runtime_error("unpaired unlock() call"); + } + + d_lock_count--; + if(d_lock_count > 0 || d_state == IDLE) // nothing to do + return; + + restart(); + } + + /* + * restart is called with d_mutex held + */ + void + top_block_impl::restart() + { + stop(); // Stop scheduler and wait for completion + wait(); + + // Create new simple flow graph + flat_flowgraph_sptr new_ffg = d_owner->flatten(); + new_ffg->validate(); // check consistency, sanity, etc + new_ffg->merge_connections(d_ffg); // reuse buffers, etc + d_ffg = new_ffg; + + // Create a new scheduler to execute it + d_scheduler = make_scheduler(d_ffg, d_max_noutput_items); + d_state = RUNNING; + } + + std::string + top_block_impl::edge_list() + { + if(d_ffg) + return d_ffg->edge_list(); + else + return ""; + } + + void + top_block_impl::dump() + { + if(d_ffg) + d_ffg->dump(); + } + + int + top_block_impl::max_noutput_items() + { + return d_max_noutput_items; + } + + void + top_block_impl::set_max_noutput_items(int nmax) + { + d_max_noutput_items = nmax; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/top_block_impl.h b/gnuradio-runtime/lib/top_block_impl.h new file mode 100644 index 0000000000..9e0e661a02 --- /dev/null +++ b/gnuradio-runtime/lib/top_block_impl.h @@ -0,0 +1,90 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2008,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_TOP_BLOCK_IMPL_H +#define INCLUDED_GR_TOP_BLOCK_IMPL_H + +#include <gnuradio/api.h> +#include "scheduler.h" +#include <gnuradio/thread/thread.h> + +namespace gr { + + /*! + *\brief Abstract implementation details of top_block + * \ingroup internal + * + * The actual implementation of top_block. Separate class allows + * decoupling of changes from dependent classes. + */ + class GR_RUNTIME_API top_block_impl + { + public: + top_block_impl(top_block *owner); + ~top_block_impl(); + + // Create and start scheduler threads + void start(int max_noutput_items=100000000); + + // Signal scheduler threads to stop + void stop(); + + // Wait for scheduler threads to exit + void wait(); + + // Lock the top block to allow reconfiguration + void lock(); + + // Unlock the top block at end of reconfiguration + void unlock(); + + // Return a string list of edges + std::string edge_list(); + + // Dump the flowgraph to stdout + void dump(); + + // Get the number of max noutput_items in the flowgraph + int max_noutput_items(); + + // Set the maximum number of noutput_items in the flowgraph + void set_max_noutput_items(int nmax); + + protected: + enum tb_state { IDLE, RUNNING }; + + top_block *d_owner; + flat_flowgraph_sptr d_ffg; + scheduler_sptr d_scheduler; + + gr::thread::mutex d_mutex; // protects d_state and d_lock_count + tb_state d_state; + int d_lock_count; + int d_max_noutput_items; + + private: + void restart(); + }; + +} /* namespace gr */ + +#endif /* INCLUDED_GR_TOP_BLOCK_IMPL_H */ diff --git a/gnuradio-runtime/lib/tpb_detail.cc b/gnuradio-runtime/lib/tpb_detail.cc new file mode 100644 index 0000000000..cf05c2b102 --- /dev/null +++ b/gnuradio-runtime/lib/tpb_detail.cc @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2013 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 3, 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 <config.h> +#endif + +#include <gnuradio/tpb_detail.h> +#include <gnuradio/block.h> +#include <gnuradio/block_detail.h> +#include <gnuradio/buffer.h> + +namespace gr { + + /* + * We assume that no worker threads are ever running when the graph + * structure is being manipulated, thus it's safe for us to poke + * around in our neighbors w/o holding any locks. + */ + void + tpb_detail::notify_upstream(block_detail *d) + { + // For each of our inputs, tell the guy upstream that we've + // consumed some input, and that he most likely has more output + // buffer space available. + + for(size_t i = 0; i < d->d_input.size(); i++) { + // Can you say, "pointer chasing?" + d->d_input[i]->buffer()->link()->detail()->d_tpb.set_output_changed(); + } + } + + void + tpb_detail::notify_downstream(block_detail *d) + { + // For each of our outputs, tell the guys downstream that they + // have new input available. + + for(size_t i = 0; i < d->d_output.size(); i++) { + buffer_sptr buf = d->d_output[i]; + for(size_t j = 0, k = buf->nreaders(); j < k; j++) + buf->reader(j)->link()->detail()->d_tpb.set_input_changed(); + } + } + + void + tpb_detail::notify_neighbors(block_detail *d) + { + notify_downstream(d); + notify_upstream(d); + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/tpb_thread_body.cc b/gnuradio-runtime/lib/tpb_thread_body.cc new file mode 100644 index 0000000000..ceb94fbb2a --- /dev/null +++ b/gnuradio-runtime/lib/tpb_thread_body.cc @@ -0,0 +1,151 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009,2011,2013 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 3, 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 <config.h> +#endif + +#include "tpb_thread_body.h" +#include <gnuradio/prefs.h> +#include <boost/thread.hpp> +#include <boost/foreach.hpp> +#include <pmt/pmt.h> +#include <iostream> + +namespace gr { + + tpb_thread_body::tpb_thread_body(block_sptr block, int max_noutput_items) + : d_exec(block, max_noutput_items) + { + //std::cerr << "tpb_thread_body: " << block << std::endl; + + block_detail *d = block->detail().get(); + block_executor::state s; + pmt::pmt_t msg; + + d->threaded = true; + d->thread = gr::thread::get_current_thread_id(); + + prefs *p = prefs::singleton(); + size_t max_nmsgs = static_cast<size_t>(p->get_long("DEFAULT", "max_messages", 100)); + + // Set thread affinity if it was set before fg was started. + if(block->processor_affinity().size() > 0) { + gr::thread::thread_bind_to_processor(d->thread, block->processor_affinity()); + } + + while(1) { + boost::this_thread::interruption_point(); + + // handle any queued up messages + //BOOST_FOREACH( pmt::pmt_t port, block->msg_queue.keys() ) + + BOOST_FOREACH(basic_block::msg_queue_map_t::value_type &i, block->msg_queue) { + // Check if we have a message handler attached before getting + // any messages. This is mostly a protection for the unknown + // startup sequence of the threads. + if(block->has_msg_handler(i.first)) { + while((msg = block->delete_head_nowait(i.first))) { + block->dispatch_msg(i.first,msg); + } + } + else { + // If we don't have a handler but are building up messages, + // prune the queue from the front to keep memory in check. + if(block->nmsgs(i.first) > max_nmsgs) + msg = block->delete_head_nowait(i.first); + } + } + + d->d_tpb.clear_changed(); + // run one iteration if we are a connected stream block + if(d->noutputs() >0 || d->ninputs()>0){ + s = d_exec.run_one_iteration(); + } + else { + s = block_executor::BLKD_IN; + } + + switch(s){ + case block_executor::READY: // Tell neighbors we made progress. + d->d_tpb.notify_neighbors(d); + break; + + case block_executor::READY_NO_OUTPUT: // Notify upstream only + d->d_tpb.notify_upstream(d); + break; + + case block_executor::DONE: // Game over. + d->d_tpb.notify_neighbors(d); + return; + + case block_executor::BLKD_IN: // Wait for input. + { + gr::thread::scoped_lock guard(d->d_tpb.mutex); + while(!d->d_tpb.input_changed) { + + // wait for input or message + while(!d->d_tpb.input_changed && block->empty_p()) + d->d_tpb.input_cond.wait(guard); + + // handle all pending messages + BOOST_FOREACH(basic_block::msg_queue_map_t::value_type &i, block->msg_queue) { + while((msg = block->delete_head_nowait(i.first))) { + guard.unlock(); // release lock while processing msg + block->dispatch_msg(i.first, msg); + guard.lock(); + } + } + } + } + break; + + case block_executor::BLKD_OUT: // Wait for output buffer space. + { + gr::thread::scoped_lock guard(d->d_tpb.mutex); + while(!d->d_tpb.output_changed) { + // wait for output room or message + while(!d->d_tpb.output_changed && block->empty_p()) + d->d_tpb.output_cond.wait(guard); + + // handle all pending messages + BOOST_FOREACH(basic_block::msg_queue_map_t::value_type &i, block->msg_queue) { + while((msg = block->delete_head_nowait(i.first))) { + guard.unlock(); // release lock while processing msg + block->dispatch_msg(i.first,msg); + guard.lock(); + } + } + } + } + break; + + default: + assert(0); + } + } + } + + tpb_thread_body::~tpb_thread_body() + { + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/gr_tpb_thread_body.h b/gnuradio-runtime/lib/tpb_thread_body.h index 6ecb022f69..9859b125dd 100644 --- a/gnuradio-runtime/lib/gr_tpb_thread_body.h +++ b/gnuradio-runtime/lib/tpb_thread_body.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008 Free Software Foundation, Inc. + * Copyright 2008,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -21,26 +21,29 @@ #ifndef INCLUDED_GR_TPB_THREAD_BODY_H #define INCLUDED_GR_TPB_THREAD_BODY_H -#include <gr_runtime_api.h> -#include <gr_block_executor.h> -#include <gr_block.h> -#include <gr_block_detail.h> +#include <gnuradio/api.h> +#include <gnuradio/block.h> +#include <gnuradio/block_detail.h> +#include "block_executor.h" -/*! - * \brief The body of each thread-per-block thread. - * - * One of these is instantiated in its own thread for each block. The - * constructor turns into the main loop which returns when the block is - * done or is interrupted. - */ +namespace gr { -class GR_RUNTIME_API gr_tpb_thread_body { - gr_block_executor d_exec; + /*! + * \brief The body of each thread-per-block thread. + * + * One of these is instantiated in its own thread for each block. + * The constructor turns into the main loop which returns when the + * block is done or is interrupted. + */ + class GR_RUNTIME_API tpb_thread_body + { + block_executor d_exec; -public: - gr_tpb_thread_body(gr_block_sptr block, int max_noutput_items=100000); - ~gr_tpb_thread_body(); -}; + public: + tpb_thread_body(block_sptr block, int max_noutput_items=100000); + ~tpb_thread_body(); + }; +} /* namespace gr */ #endif /* INCLUDED_GR_TPB_THREAD_BODY_H */ diff --git a/gnuradio-runtime/lib/vmcircbuf.cc b/gnuradio-runtime/lib/vmcircbuf.cc new file mode 100644 index 0000000000..0fccb3d914 --- /dev/null +++ b/gnuradio-runtime/lib/vmcircbuf.cc @@ -0,0 +1,299 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <assert.h> +#include <stdexcept> +#include <stdio.h> +#include <string.h> +#include <vector> +#include <boost/format.hpp> +#include "vmcircbuf.h" +#include "vmcircbuf_prefs.h" +#include "local_sighandler.h" + +// all the factories we know about +#include "vmcircbuf_createfilemapping.h" +#include "vmcircbuf_sysv_shm.h" +#include "vmcircbuf_mmap_shm_open.h" +#include "vmcircbuf_mmap_tmpfile.h" + +namespace gr { + + static const char *FACTORY_PREF_KEY = "vmcircbuf_default_factory"; + + vmcircbuf::~vmcircbuf() + { + } + + vmcircbuf_factory::~vmcircbuf_factory() + { + } + + // ---------------------------------------------------------------- + + static vmcircbuf_factory *s_default_factory = 0; + + vmcircbuf_factory * + vmcircbuf_sysconfig::get_default_factory() + { + if(s_default_factory) + return s_default_factory; + + bool verbose = false; + + std::vector<gr::vmcircbuf_factory *> all = all_factories (); + + const char *name = gr::vmcircbuf_prefs::get(FACTORY_PREF_KEY); + + if(name) { + for(unsigned int i = 0; i < all.size (); i++) { + if(strcmp(name, all[i]->name ()) == 0) { + s_default_factory = all[i]; + if(verbose) + fprintf(stderr, "gr::vmcircbuf_sysconfig: using %s\n", + s_default_factory->name()); + return s_default_factory; + } + } + } + + // either we don't have a default, or the default named is not in our + // list of factories. Find the first factory that works. + + if(verbose) + fprintf(stderr, "gr::vmcircbuf_sysconfig: finding a working factory...\n"); + + for(unsigned int i = 0; i < all.size (); i++) { + if(test_factory(all[i], verbose)) { + set_default_factory(all[i]); + return s_default_factory; + } + } + + // We're screwed! + fprintf(stderr, "gr::vmcircbuf_sysconfig: unable to find a working factory!\n"); + throw std::runtime_error("gr::vmcircbuf_sysconfig"); + } + + std::vector<vmcircbuf_factory *> + vmcircbuf_sysconfig::all_factories() + { + std::vector<vmcircbuf_factory*> result; + + result.push_back(gr::vmcircbuf_createfilemapping_factory::singleton()); +#ifdef TRY_SHM_VMCIRCBUF + result.push_back(gr::vmcircbuf_sysv_shm_factory::singleton()); + result.push_back(gr::vmcircbuf_mmap_shm_open_factory::singleton()); +#endif + result.push_back (gr::vmcircbuf_mmap_tmpfile_factory::singleton()); + + return result; + } + + void + vmcircbuf_sysconfig::set_default_factory(vmcircbuf_factory *f) + { + gr::vmcircbuf_prefs::set(FACTORY_PREF_KEY, f->name()); + s_default_factory = f; + } + + + // ------------------------------------------------------------------------ + // test code for vmcircbuf factories + // ------------------------------------------------------------------------ + + static void + init_buffer(vmcircbuf *c, int counter, int size) + { + unsigned int *p = (unsigned int*)c->pointer_to_first_copy(); + for(unsigned int i = 0; i < size / sizeof(int); i++) + p[i] = counter + i; + } + + static bool + check_mapping(vmcircbuf *c, int counter, int size, const char *msg, bool verbose) + { + bool ok = true; + + if(verbose) + fprintf(stderr, "... %s", msg); + + unsigned int *p1 = (unsigned int *)c->pointer_to_first_copy(); + unsigned int *p2 = (unsigned int *)c->pointer_to_second_copy(); + + // fprintf(stderr, "p1 = %p, p2 = %p\n", p1, p2); + + for(unsigned int i = 0; i < size / sizeof (int); i++) { + if(p1[i] != counter + i) { + ok = false; + if(verbose) + fprintf(stderr, " p1[%d] == %u, expected %u\n", i, p1[i], counter + i); + break; + } + if(p2[i] != counter + i) { + if(verbose) + fprintf(stderr, " p2[%d] == %u, expected %u\n", i, p2[i], counter + i); + ok = false; + break; + } + } + + if(ok && verbose) { + fprintf(stderr, " OK\n"); + } + return ok; + } + + static const char * + memsize(int size) + { + static std::string buf; + if(size >= (1 << 20)) { + buf = str(boost::format("%dMB") % (size / (1 << 20))); + } + else if(size >= (1 << 10)){ + buf = str(boost::format("%dKB") % (size / (1 << 10))); + } + else { + buf = str(boost::format("%d") % size); + } + return buf.c_str(); + } + + static bool + test_a_bunch(vmcircbuf_factory *factory, int n, int size, int *start_ptr, bool verbose) + { + bool ok = true; + std::vector<int> counter(n); + std::vector<vmcircbuf*> c(n); + int cum_size = 0; + + for(int i = 0; i < n; i++) { + counter[i] = *start_ptr; + *start_ptr += size; + if((c[i] = factory->make (size)) == 0) { + if(verbose) + fprintf(stderr, + "Failed to allocate gr::vmcircbuf number %d of size %d (cum = %s)\n", + i + 1, size, memsize(cum_size)); + return false; + } + init_buffer(c[i], counter[i], size); + cum_size += size; + } + + for(int i = 0; i < n; i++) { + std::string msg = str(boost::format("test_a_bunch_%dx%s[%d]") % n % memsize(size) % i); + ok &= check_mapping(c[i], counter[i], size, msg.c_str(), verbose); + } + + for(int i = 0; i < n; i++) { + delete c[i]; + c[i] = 0; + } + + return ok; + } + + static bool + standard_tests(vmcircbuf_factory *f, int verbose) + { + if(verbose >= 1) + fprintf(stderr, "Testing %s...\n", f->name()); + + bool v = verbose >= 2; + int granularity = f->granularity(); + int start = 0; + bool ok = true; + + ok &= test_a_bunch(f, 1, 1 * granularity, &start, v); // 1 x 4KB = 4KB + + if(ok) { + ok &= test_a_bunch(f, 64, 4 * granularity, &start, v); // 64 x 16KB = 1MB + ok &= test_a_bunch(f, 4, 4 * (1L << 20), &start, v); // 4 x 4MB = 16MB + // ok &= test_a_bunch(f, 256, 256 * (1L << 10), &start, v); // 256 x 256KB = 64MB + } + + if(verbose >= 1) + fprintf(stderr, "....... %s: %s", f->name(), ok ? "OK\n" : "Doesn't work\n"); + + return ok; + } + + bool + vmcircbuf_sysconfig::test_factory(vmcircbuf_factory *f, int verbose) + { + // Install local signal handlers for SIGSEGV and SIGBUS. + // If something goes wrong, these signals may be invoked. + +#ifdef SIGSEGV + gr::local_sighandler sigsegv (SIGSEGV, gr::local_sighandler::throw_signal); +#endif +#ifdef SIGBUS + gr::local_sighandler sigbus (SIGBUS, gr::local_sighandler::throw_signal); +#endif +#ifdef SIGSYS + gr::local_sighandler sigsys (SIGSYS, gr::local_sighandler::throw_signal); +#endif + + try { + return standard_tests (f, verbose); + } + catch(gr::signal &sig) { + if(verbose) { + fprintf(stderr, "....... %s: %s", f->name(), "Doesn't work\n"); + fprintf(stderr, + "gr::vmcircbuf_factory::test_factory (%s): caught %s\n", + f->name(), sig.name().c_str()); + return false; + } + } + catch (...) { + if(verbose) { + fprintf(stderr, "....... %s: %s", f->name(), "Doesn't work\n"); + fprintf(stderr, + "gr::vmcircbuf_factory::test_factory (%s): some kind of uncaught exception\n", + f->name()); + } + return false; + } + return false; // never gets here. shut compiler up. + } + + bool + vmcircbuf_sysconfig::test_all_factories(int verbose) + { + bool ok = false; + + std::vector<vmcircbuf_factory *> all = all_factories(); + + for(unsigned int i = 0; i < all.size (); i++) + ok |= test_factory(all[i], verbose); + + return ok; + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/vmcircbuf.h b/gnuradio-runtime/lib/vmcircbuf.h new file mode 100644 index 0000000000..c3ddfe0043 --- /dev/null +++ b/gnuradio-runtime/lib/vmcircbuf.h @@ -0,0 +1,125 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef GR_VMCIRCBUF_H +#define GR_VMCIRCBUF_H + +#include <gnuradio/api.h> +#include <vector> + +namespace gr { + + /*! + * \brief abstract class to implement doubly mapped virtual memory circular buffers + * \ingroup internal + */ + class GR_RUNTIME_API vmcircbuf + { + protected: + int d_size; + char *d_base; + + // CREATORS + vmcircbuf(int size) : d_size(size), d_base(0) {}; + + public: + virtual ~vmcircbuf(); + + // ACCESSORS + void *pointer_to_first_copy() const{ return d_base; } + void *pointer_to_second_copy() const{ return d_base + d_size; } + }; + + /*! + * \brief abstract factory for creating circular buffers + */ + class GR_RUNTIME_API vmcircbuf_factory + { + protected: + vmcircbuf_factory() {}; + virtual ~vmcircbuf_factory(); + + public: + + /*! + * \brief return name of this factory + */ + virtual const char *name() const = 0; + + /*! + * \brief return granularity of mapping, typically equal to page size + */ + virtual int granularity() = 0; + + /*! + * \brief return a gr::vmcircbuf, or 0 if unable. + * + * Call this to create a doubly mapped circular buffer. + */ + virtual vmcircbuf *make(int size) = 0; + }; + + /* + * \brief pulls together all implementations of gr::vmcircbuf + */ + class GR_RUNTIME_API vmcircbuf_sysconfig + { + public: + /* + * \brief return the single instance of the default factory. + * + * returns the default factory to use if it's already defined, + * else find the first working factory and use it. + */ + static vmcircbuf_factory *get_default_factory(); + + static int granularity() { return get_default_factory()->granularity(); } + static vmcircbuf *make(int size) { return get_default_factory()->make(size); } + + // N.B. not all factories are guaranteed to work. + // It's too hard to check everything at config time, so we check at runtime + static std::vector<vmcircbuf_factory*> all_factories(); + + // make this factory the default + static void set_default_factory(vmcircbuf_factory *f); + + /*! + * \brief Does this factory really work? + * + * verbose = 0: silent + * verbose = 1: names of factories tested and results + * verbose = 2: all intermediate results + */ + static bool test_factory(vmcircbuf_factory *f, int verbose); + + /*! + * \brief Test all factories, return true if at least one of them works + * verbose = 0: silent + * verbose = 1: names of factories tested and results + * verbose = 2: all intermediate results + */ + static bool test_all_factories(int verbose); + }; + +} /* namespace gr */ + +#endif /* GR_VMCIRCBUF_H */ diff --git a/gnuradio-runtime/lib/vmcircbuf_createfilemapping.cc b/gnuradio-runtime/lib/vmcircbuf_createfilemapping.cc new file mode 100644 index 0000000000..2d345a29b1 --- /dev/null +++ b/gnuradio-runtime/lib/vmcircbuf_createfilemapping.cc @@ -0,0 +1,204 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2005,2011,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdexcept> +#include <assert.h> +#include <unistd.h> +#include <fcntl.h> +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif +#include <errno.h> +#include <stdio.h> +#include "pagesize.h" +#include "vmcircbuf_createfilemapping.h" +#include <boost/format.hpp> + +namespace gr { + +#ifdef HAVE_CREATEFILEMAPPING + // Print Windows error (could/should be global?) + static void + werror(char *where, DWORD last_error) + { + char buf[1024]; + + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + last_error, + 0, // default language + buf, + sizeof(buf)/sizeof(TCHAR), // buffer size + NULL); + fprintf(stderr, "%s: Error %d: %s", where, last_error, buf); + return; + } +#endif + + + vmcircbuf_createfilemapping::vmcircbuf_createfilemapping(int size) + : gr::vmcircbuf(size) + { +#if !defined(HAVE_CREATEFILEMAPPING) + fprintf(stderr, "%s: createfilemapping is not available\n", __FUNCTION__); + throw std::runtime_error("gr::vmcircbuf_createfilemapping"); +#else + static int s_seg_counter = 0; + + if(size <= 0 || (size % gr::pagesize ()) != 0) { + fprintf(stderr, "gr::vmcircbuf_createfilemapping: invalid size = %d\n", size); + throw std::runtime_error ("gr::vmcircbuf_createfilemapping"); + } + + std::string seg_name = str(boost::format("/gnuradio-%d-%d") % getpid() % s_seg_counter); + + d_handle = CreateFileMapping(INVALID_HANDLE_VALUE, // use paging file + NULL, // default security + PAGE_READWRITE, // read/write access + 0, // max. object size + size, // buffer size + seg_name.c_str()); // name of mapping object + + s_seg_counter++; + if(d_handle == NULL || d_handle == INVALID_HANDLE_VALUE) { + std::string msg = str(boost::format( + "gr::vmcircbuf_mmap_createfilemapping: CreateFileMapping [%s]") % + seg_name); + werror((char*)msg.c_str(), GetLastError()); + throw std::runtime_error("gr::vmcircbuf_mmap_createfilemapping"); + } + + // Allocate virtual memory of the needed size, then free it so we can use it + LPVOID first_tmp; + first_tmp = VirtualAlloc( NULL, 2*size, MEM_RESERVE, PAGE_NOACCESS ); + if(first_tmp == NULL) { + werror("gr::vmcircbuf_mmap_createfilemapping: VirtualAlloc", GetLastError()); + CloseHandle(d_handle); // cleanup + throw std::runtime_error("gr::vmcircbuf_mmap_createfilemapping"); + } + + if(VirtualFree(first_tmp, 0, MEM_RELEASE) == 0) { + werror("gr::vmcircbuf_mmap_createfilemapping: VirtualFree", GetLastError()); + CloseHandle(d_handle); // cleanup + throw std::runtime_error("gr::vmcircbuf_mmap_createfilemapping"); + } + + d_first_copy = MapViewOfFileEx((HANDLE)d_handle, // handle to map object + FILE_MAP_WRITE, // read/write permission + 0, + 0, + size, + first_tmp); + if(d_first_copy != first_tmp) { + werror( "gr::vmcircbuf_mmap_createfilemapping: MapViewOfFileEx(1)", GetLastError()); + CloseHandle(d_handle); // cleanup + throw std::runtime_error ("gr::vmcircbuf_mmap_createfilemapping"); + } + + d_second_copy = MapViewOfFileEx((HANDLE)d_handle, // handle to map object + FILE_MAP_WRITE, // read/write permission + 0, + 0, + size, + (char*)first_tmp + size);//(LPVOID) ((char *)d_first_copy + size)); + + if(d_second_copy != (char *)first_tmp + size) { + werror( "gr::vmcircbuf_mmap_createfilemapping: MapViewOfFileEx(2)", GetLastError()); + UnmapViewOfFile(d_first_copy); + CloseHandle(d_handle); // cleanup + throw std::runtime_error ("gr::vmcircbuf_mmap_createfilemapping"); + } + +#ifdef DEBUG + fprintf(stderr,"gr::vmcircbuf_mmap_createfilemapping: contiguous? mmap %p %p %p %p\n", + (char*)d_first_copy, (char*)d_second_copy, size, (char*)d_first_copy + size); +#endif + + // Now remember the important stuff + d_base = (char*)d_first_copy; + d_size = size; +#endif /*HAVE_CREATEFILEMAPPING*/ + } + + vmcircbuf_createfilemapping::~vmcircbuf_createfilemapping() + { +#ifdef HAVE_CREATEFILEMAPPING + if(UnmapViewOfFile(d_first_copy) == 0) { + werror("gr::vmcircbuf_createfilemapping: UnmapViewOfFile(d_first_copy)", GetLastError()); + } + d_base=NULL; + if(UnmapViewOfFile(d_second_copy) == 0) { + werror("gr::vmcircbuf_createfilemapping: UnmapViewOfFile(d_second_copy)", GetLastError()); + } + //d_second=NULL; + CloseHandle(d_handle); +#endif + } + + // ---------------------------------------------------------------- + // The factory interface + // ---------------------------------------------------------------- + + gr::vmcircbuf_factory *vmcircbuf_createfilemapping_factory::s_the_factory = 0; + + gr::vmcircbuf_factory * + vmcircbuf_createfilemapping_factory::singleton() + { + if(s_the_factory) + return s_the_factory; + s_the_factory = new vmcircbuf_createfilemapping_factory(); + return s_the_factory; + } + + int + vmcircbuf_createfilemapping_factory::granularity() + { +#ifdef HAVE_CREATEFILEMAPPING + // return 65536;//TODO, check, is this needed or can we just use gr::pagesize() + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + //fprintf(stderr,"win32 AllocationGranularity %p\n",(int)system_info.dwAllocationGranularity); + return (int)system_info.dwAllocationGranularity; +#else + return gr::pagesize(); +#endif + } + + gr::vmcircbuf * + vmcircbuf_createfilemapping_factory::make(int size) + { + try { + return new vmcircbuf_createfilemapping(size); + } + catch(...) { + return 0; + } + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/vmcircbuf_createfilemapping.h b/gnuradio-runtime/lib/vmcircbuf_createfilemapping.h new file mode 100644 index 0000000000..0513112f23 --- /dev/null +++ b/gnuradio-runtime/lib/vmcircbuf_createfilemapping.h @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2005,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef GR_VMCIRCBUF_CREATEFILEMAPPING_H +#define GR_VMCIRCBUF_CREATEFILEMAPPING_H + +#include <gnuradio/api.h> +#include "vmcircbuf.h" + +#ifdef HAVE_CREATEFILEMAPPING +#include <windows.h> +#endif + +namespace gr { + + /*! + * \brief concrete class to implement circular buffers with mmap and shm_open + * \ingroup internal + */ + class GR_RUNTIME_API vmcircbuf_createfilemapping : public gr::vmcircbuf + { + public: + // CREATORS + vmcircbuf_createfilemapping(int size); + virtual ~vmcircbuf_createfilemapping(); +#ifdef HAVE_CREATEFILEMAPPING + private: + HANDLE d_handle; + LPVOID d_first_copy; + LPVOID d_second_copy; +#endif + }; + + /*! + * \brief concrete factory for circular buffers built using mmap and shm_open + */ + class GR_RUNTIME_API vmcircbuf_createfilemapping_factory : public gr::vmcircbuf_factory + { + private: + static gr::vmcircbuf_factory *s_the_factory; + + public: + static gr::vmcircbuf_factory *singleton(); + + virtual const char *name() const { return "gr::vmcircbuf_createfilemapping_factory"; } + + /*! + * \brief return granularity of mapping, typically equal to page size + */ + virtual int granularity(); + + /*! + * \brief return a gr::vmcircbuf, or 0 if unable. + * + * Call this to create a doubly mapped circular buffer. + */ + virtual gr::vmcircbuf *make(int size); + }; + +} /* namespace gr */ + +#endif /* GR_VMCIRCBUF_CREATEFILEMAPPING_H */ diff --git a/gnuradio-runtime/lib/vmcircbuf_mmap_shm_open.cc b/gnuradio-runtime/lib/vmcircbuf_mmap_shm_open.cc new file mode 100644 index 0000000000..7b461bc26b --- /dev/null +++ b/gnuradio-runtime/lib/vmcircbuf_mmap_shm_open.cc @@ -0,0 +1,204 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2011,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "vmcircbuf_mmap_shm_open.h" +#include <stdexcept> +#include <assert.h> +#include <unistd.h> +#include <fcntl.h> +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif +#include <errno.h> +#include <stdio.h> +#include "pagesize.h" +#include <gnuradio/sys_paths.h> + +namespace gr { + + vmcircbuf_mmap_shm_open::vmcircbuf_mmap_shm_open(int size) + : gr::vmcircbuf(size) + { +#if !defined(HAVE_MMAP) || !defined(HAVE_SHM_OPEN) + fprintf(stderr, "gr::vmcircbuf_mmap_shm_open: mmap or shm_open is not available\n"); + throw std::runtime_error("gr::vmcircbuf_mmap_shm_open"); +#else + static int s_seg_counter = 0; + + if(size <= 0 || (size % gr::pagesize ()) != 0) { + fprintf(stderr, "gr::vmcircbuf_mmap_shm_open: invalid size = %d\n", size); + throw std::runtime_error("gr::vmcircbuf_mmap_shm_open"); + } + + int shm_fd = -1; + char seg_name[1024]; + static bool portable_format = true; + + // open a new named shared memory segment + while(1) { + if(portable_format) { + + // This is the POSIX recommended "portable format". + // Of course the "portable format" doesn't work on some systems... + + snprintf(seg_name, sizeof(seg_name), + "/gnuradio-%d-%d", getpid(), s_seg_counter); + } + else { + + // Where the "portable format" doesn't work, we try building + // a full filesystem pathname pointing into a suitable temporary directory. + + snprintf(seg_name, sizeof(seg_name), + "%s/gnuradio-%d-%d", gr::tmp_path(), getpid(), s_seg_counter); + } + + shm_fd = shm_open(seg_name, O_RDWR | O_CREAT | O_EXCL, 0600); + if(shm_fd == -1 && errno == EACCES && portable_format) { + portable_format = false; + continue; // try again using "non-portable format" + } + + s_seg_counter++; + + if(shm_fd == -1) { + if(errno == EEXIST) // Named segment already exists (shouldn't happen). Try again + continue; + + char msg[1024]; + snprintf(msg, sizeof(msg), "gr::vmcircbuf_mmap_shm_open: shm_open [%s]", seg_name); + perror(msg); + throw std::runtime_error("gr::vmcircbuf_mmap_shm_open"); + } + break; + } + + // We've got a new shared memory segment fd open. + // Now set it's length to 2x what we really want and mmap it in. + if(ftruncate(shm_fd, (off_t)2 * size) == -1) { + close(shm_fd); // cleanup + perror("gr::vmcircbuf_mmap_shm_open: ftruncate (1)"); + throw std::runtime_error("gr::vmcircbuf_mmap_shm_open"); + } + + void *first_copy = mmap(0, 2 * size, + PROT_READ | PROT_WRITE, MAP_SHARED, + shm_fd, (off_t) 0); + + if(first_copy == MAP_FAILED) { + close(shm_fd); // cleanup + perror("gr::vmcircbuf_mmap_shm_open: mmap (1)"); + throw std::runtime_error("gr::vmcircbuf_mmap_shm_open"); + } + + // unmap the 2nd half + if(munmap ((char *) first_copy + size, size) == -1) { + close(shm_fd); // cleanup + perror("gr::vmcircbuf_mmap_shm_open: munmap (1)"); + throw std::runtime_error("gr::vmcircbuf_mmap_shm_open"); + } + + // map the first half into the now available hole where the + // second half used to be. + void *second_copy = mmap((char*)first_copy + size, size, + PROT_READ | PROT_WRITE, MAP_SHARED, + shm_fd, (off_t)0); + + if(second_copy == MAP_FAILED) { + close(shm_fd); // cleanup + perror("gr::vmcircbuf_mmap_shm_open: mmap (2)"); + throw std::runtime_error("gr::vmcircbuf_mmap_shm_open"); + } + +#if 0 // OS/X doesn't allow you to resize the segment + + // cut the shared memory segment down to size + if(ftruncate(shm_fd, (off_t)size) == -1) { + close(shm_fd); // cleanup + perror("gr::vmcircbuf_mmap_shm_open: ftruncate (2)"); + throw std::runtime_error("gr::vmcircbuf_mmap_shm_open"); + } +#endif + + close(shm_fd); // fd no longer needed. The mapping is retained. + + if(shm_unlink(seg_name) == -1) { // unlink the seg_name. + perror("gr::vmcircbuf_mmap_shm_open: shm_unlink"); + throw std::runtime_error("gr::vmcircbuf_mmap_shm_open"); + } + + // Now remember the important stuff + d_base = (char*)first_copy; + d_size = size; +#endif + } + + vmcircbuf_mmap_shm_open::~vmcircbuf_mmap_shm_open() + { +#if defined(HAVE_MMAP) + if(munmap (d_base, 2 * d_size) == -1) { + perror("gr::vmcircbuf_mmap_shm_open: munmap (2)"); + } +#endif + } + + // ---------------------------------------------------------------- + // The factory interface + // ---------------------------------------------------------------- + + gr::vmcircbuf_factory *vmcircbuf_mmap_shm_open_factory::s_the_factory = 0; + + gr::vmcircbuf_factory * + vmcircbuf_mmap_shm_open_factory::singleton() + { + if(s_the_factory) + return s_the_factory; + + s_the_factory = new gr::vmcircbuf_mmap_shm_open_factory(); + return s_the_factory; + } + + int + vmcircbuf_mmap_shm_open_factory::granularity() + { + return gr::pagesize(); + } + + gr::vmcircbuf * + vmcircbuf_mmap_shm_open_factory::make(int size) + { + try { + return new vmcircbuf_mmap_shm_open(size); + } + catch (...) { + return 0; + } + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/vmcircbuf_mmap_shm_open.h b/gnuradio-runtime/lib/vmcircbuf_mmap_shm_open.h new file mode 100644 index 0000000000..60654ee46e --- /dev/null +++ b/gnuradio-runtime/lib/vmcircbuf_mmap_shm_open.h @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef GR_VMCIRCBUF_MMAP_SHM_OPEN_H +#define GR_VMCIRCBUF_MMAP_SHM_OPEN_H + +#include <gnuradio/api.h> +#include "vmcircbuf.h" + +namespace gr { + + /*! + * \brief concrete class to implement circular buffers with mmap and shm_open + * \ingroup internal + */ + class GR_RUNTIME_API vmcircbuf_mmap_shm_open : public gr::vmcircbuf + { + public: + vmcircbuf_mmap_shm_open(int size); + virtual ~vmcircbuf_mmap_shm_open(); + }; + + /*! + * \brief concrete factory for circular buffers built using mmap and shm_open + */ + class GR_RUNTIME_API vmcircbuf_mmap_shm_open_factory : public gr::vmcircbuf_factory + { + private: + static gr::vmcircbuf_factory *s_the_factory; + + public: + static gr::vmcircbuf_factory *singleton(); + + virtual const char *name() const { return "gr::vmcircbuf_mmap_shm_open_factory"; } + + /*! + * \brief return granularity of mapping, typically equal to page size + */ + virtual int granularity(); + + /*! + * \brief return a gr::vmcircbuf, or 0 if unable. + * + * Call this to create a doubly mapped circular buffer. + */ + virtual gr::vmcircbuf *make(int size); + }; + +} /* namespace gr */ + +#endif /* GR_VMCIRCBUF_MMAP_SHM_OPEN_H */ diff --git a/gnuradio-runtime/lib/vmcircbuf_mmap_tmpfile.cc b/gnuradio-runtime/lib/vmcircbuf_mmap_tmpfile.cc new file mode 100644 index 0000000000..ffe2a3d2c2 --- /dev/null +++ b/gnuradio-runtime/lib/vmcircbuf_mmap_tmpfile.cc @@ -0,0 +1,197 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2011,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "vmcircbuf_mmap_tmpfile.h" +#include <stdexcept> +#include <assert.h> +#include <unistd.h> +#include <stdlib.h> +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include "pagesize.h" +#include <gnuradio/sys_paths.h> + +namespace gr { + + vmcircbuf_mmap_tmpfile::vmcircbuf_mmap_tmpfile (int size) + : gr::vmcircbuf (size) + { +#if !defined(HAVE_MMAP) + fprintf(stderr, "gr::vmcircbuf_mmap_tmpfile: mmap or mkstemp is not available\n"); + throw std::runtime_error("gr::vmcircbuf_mmap_tmpfile"); +#else + + if(size <= 0 || (size % gr::pagesize ()) != 0) { + fprintf(stderr, "gr::vmcircbuf_mmap_tmpfile: invalid size = %d\n", size); + throw std::runtime_error("gr::vmcircbuf_mmap_tmpfile"); + } + + int seg_fd = -1; + char seg_name[1024]; + + static int s_seg_counter = 0; + + // open a temporary file that we'll map in a bit later + while(1) { + snprintf(seg_name, sizeof(seg_name), + "%s/gnuradio-%d-%d-XXXXXX", gr::tmp_path(), getpid(), s_seg_counter); + s_seg_counter++; + + seg_fd = open(seg_name, O_RDWR | O_CREAT | O_EXCL, 0600); + if(seg_fd == -1) { + if(errno == EEXIST) // File already exists (shouldn't happen). Try again + continue; + + char msg[1024]; + snprintf(msg, sizeof (msg), + "gr::vmcircbuf_mmap_tmpfile: open [%s]", seg_name); + perror(msg); + throw std::runtime_error("gr::vmcircbuf_mmap_tmpfile"); + } + break; + } + + if(unlink (seg_name) == -1) { + perror("gr::vmcircbuf_mmap_tmpfile: unlink"); + throw std::runtime_error ("gr::vmcircbuf_mmap_tmpfile"); + } + + // We've got a valid file descriptor to a tmp file. + // Now set it's length to 2x what we really want and mmap it in. + if(ftruncate (seg_fd, (off_t) 2 * size) == -1) { + close(seg_fd); // cleanup + perror("gr::vmcircbuf_mmap_tmpfile: ftruncate (1)"); + throw std::runtime_error("gr::vmcircbuf_mmap_tmpfile"); + } + + void *first_copy = mmap(0, 2 * size, + PROT_READ | PROT_WRITE, MAP_SHARED, + seg_fd, (off_t)0); + + if(first_copy == MAP_FAILED) { + close(seg_fd); // cleanup + perror("gr::vmcircbuf_mmap_tmpfile: mmap (1)"); + throw std::runtime_error ("gr::vmcircbuf_mmap_tmpfile"); + } + + // unmap the 2nd half + if(munmap ((char *) first_copy + size, size) == -1) { + close(seg_fd); // cleanup + perror("gr::vmcircbuf_mmap_tmpfile: munmap (1)"); + throw std::runtime_error("gr::vmcircbuf_mmap_tmpfile"); + } + + // map the first half into the now available hole where the + // second half used to be. + void *second_copy = mmap((char*)first_copy + size, size, + PROT_READ | PROT_WRITE, MAP_SHARED, + seg_fd, (off_t)0); + + if(second_copy == MAP_FAILED) { + munmap(first_copy, size); // cleanup + close(seg_fd); + perror("gr::vmcircbuf_mmap_tmpfile: mmap(2)"); + throw std::runtime_error("gr::vmcircbuf_mmap_tmpfile"); + } + + // check for contiguity + if((char*)second_copy != (char*)first_copy + size) { + munmap(first_copy, size); // cleanup + munmap(second_copy, size); + close(seg_fd); + perror("gr::vmcircbuf_mmap_tmpfile: non-contiguous second copy"); + throw std::runtime_error("gr::vmcircbuf_mmap_tmpfile"); + } + + // cut the tmp file down to size + if(ftruncate (seg_fd, (off_t) size) == -1) { + munmap(first_copy, size); // cleanup + munmap(second_copy, size); + close(seg_fd); + perror("gr::vmcircbuf_mmap_tmpfile: ftruncate (2)"); + throw std::runtime_error("gr::vmcircbuf_mmap_tmpfile"); + } + + close(seg_fd); // fd no longer needed. The mapping is retained. + + // Now remember the important stuff + + d_base = (char*)first_copy; + d_size = size; +#endif + } + + vmcircbuf_mmap_tmpfile::~vmcircbuf_mmap_tmpfile() + { +#if defined(HAVE_MMAP) + if(munmap(d_base, 2 * d_size) == -1) { + perror("gr::vmcircbuf_mmap_tmpfile: munmap(2)"); + } +#endif + } + + // ---------------------------------------------------------------- + // The factory interface + // ---------------------------------------------------------------- + + gr::vmcircbuf_factory *vmcircbuf_mmap_tmpfile_factory::s_the_factory = 0; + + gr::vmcircbuf_factory * + vmcircbuf_mmap_tmpfile_factory::singleton() + { + if(s_the_factory) + return s_the_factory; + + s_the_factory = new gr::vmcircbuf_mmap_tmpfile_factory(); + return s_the_factory; + } + + int + vmcircbuf_mmap_tmpfile_factory::granularity() + { + return gr::pagesize(); + } + + gr::vmcircbuf * + vmcircbuf_mmap_tmpfile_factory::make(int size) + { + try { + return new vmcircbuf_mmap_tmpfile(size); + } + catch (...) { + return 0; + } + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/vmcircbuf_mmap_tmpfile.h b/gnuradio-runtime/lib/vmcircbuf_mmap_tmpfile.h new file mode 100644 index 0000000000..f8959c5736 --- /dev/null +++ b/gnuradio-runtime/lib/vmcircbuf_mmap_tmpfile.h @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef GR_VMCIRCBUF_MMAP_TMPFILE_H +#define GR_VMCIRCBUF_MMAP_TMPFILE_H + +#include <gnuradio/api.h> +#include "vmcircbuf.h" + +namespace gr { + + /*! + * \brief concrete class to implement circular buffers with mmap and shm_open + * \ingroup internal + */ + class GR_RUNTIME_API vmcircbuf_mmap_tmpfile : public gr::vmcircbuf + { + public: + vmcircbuf_mmap_tmpfile(int size); + virtual ~vmcircbuf_mmap_tmpfile(); + }; + + /*! + * \brief concrete factory for circular buffers built using mmap and shm_open + */ + class GR_RUNTIME_API vmcircbuf_mmap_tmpfile_factory : public gr::vmcircbuf_factory + { + private: + static gr::vmcircbuf_factory *s_the_factory; + + public: + static gr::vmcircbuf_factory *singleton(); + + virtual const char *name() const { return "gr::vmcircbuf_mmap_tmpfile_factory"; } + + /*! + * \brief return granularity of mapping, typically equal to page size + */ + virtual int granularity(); + + /*! + * \brief return a gr::vmcircbuf, or 0 if unable. + * + * Call this to create a doubly mapped circular buffer. + */ + virtual gr::vmcircbuf *make(int size); + }; + +} /* namespace gr */ + +#endif /* GR_VMCIRCBUF_MMAP_TMPFILE_H */ diff --git a/gnuradio-runtime/lib/vmcircbuf_prefs.cc b/gnuradio-runtime/lib/vmcircbuf_prefs.cc new file mode 100644 index 0000000000..1fa6350385 --- /dev/null +++ b/gnuradio-runtime/lib/vmcircbuf_prefs.cc @@ -0,0 +1,113 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2010,2011,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "vmcircbuf_prefs.h" +#include <gnuradio/sys_paths.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <string.h> + +#include <boost/filesystem/operations.hpp> +#include <boost/filesystem/path.hpp> +namespace fs = boost::filesystem; + +namespace gr { + + /* + * The simplest thing that could possibly work: + * the key is the filename; the value is the file contents. + */ + static const char * + pathname(const char *key) + { + static fs::path path; + path = fs::path(gr::appdata_path()) / ".gnuradio" / "prefs" / key; + return path.string().c_str(); + } + + static void + ensure_dir_path() + { + fs::path path = fs::path(gr::appdata_path()) / ".gnuradio"; + if(!fs::is_directory(path)) + fs::create_directory(path); + + path = path / "prefs"; + if(!fs::is_directory(path)) + fs::create_directory(path); + } + + const char * + vmcircbuf_prefs::get(const char *key) + { + static char buf[1024]; + + FILE *fp = fopen(pathname (key), "r"); + if(fp == 0) { + perror(pathname (key)); + return 0; + } + + memset(buf, 0, sizeof (buf)); + size_t ret = fread(buf, 1, sizeof(buf) - 1, fp); + if(ret == 0) { + if(ferror(fp) != 0) { + perror(pathname (key)); + fclose(fp); + return 0; + } + } + fclose(fp); + return buf; + } + + void + vmcircbuf_prefs::set(const char *key, const char *value) + { + ensure_dir_path(); + + FILE *fp = fopen(pathname(key), "w"); + if(fp == 0) { + perror(pathname (key)); + return; + } + + size_t ret = fwrite(value, 1, strlen(value), fp); + if(ret == 0) { + if(ferror(fp) != 0) { + perror(pathname (key)); + fclose(fp); + return; + } + } + fclose(fp); + }; + +} /* namespace gr */ diff --git a/gnuradio-runtime/include/gr_preferences.h b/gnuradio-runtime/lib/vmcircbuf_prefs.h index df5aecacba..709b8ff459 100644 --- a/gnuradio-runtime/include/gr_preferences.h +++ b/gnuradio-runtime/lib/vmcircbuf_prefs.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2003 Free Software Foundation, Inc. + * Copyright 2003,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,15 +20,20 @@ * Boston, MA 02110-1301, USA. */ -#ifndef _GR_PREFERENCES_H_ -#define _GR_PREFERENCES_H_ +#ifndef GR_PREFERENCES_H +#define GR_PREFERENCES_H -#include <gr_runtime_api.h> +#include <gnuradio/api.h> -class GR_RUNTIME_API gr_preferences { - public: - static const char *get (const char *key); - static void set (const char *key, const char *value); -}; +namespace gr { -#endif /* _GR_PREFERENCES_H_ */
\ No newline at end of file + class GR_RUNTIME_API vmcircbuf_prefs + { + public: + static const char *get(const char *key); + static void set(const char *key, const char *value); + }; + +} /* namespace gr */ + +#endif /* GR_PREFERENCES_H */ diff --git a/gnuradio-runtime/lib/vmcircbuf_sysv_shm.cc b/gnuradio-runtime/lib/vmcircbuf_sysv_shm.cc new file mode 100644 index 0000000000..0d7e9b7d34 --- /dev/null +++ b/gnuradio-runtime/lib/vmcircbuf_sysv_shm.cc @@ -0,0 +1,196 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "vmcircbuf_sysv_shm.h" +#include <stdexcept> +#include <assert.h> +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> +#ifdef HAVE_SYS_IPC_H +#include <sys/ipc.h> +#endif +#ifdef HAVE_SYS_SHM_H +#include <sys/shm.h> +#endif +#include <errno.h> +#include <stdio.h> +#include "pagesize.h" + + +namespace gr { + + vmcircbuf_sysv_shm::vmcircbuf_sysv_shm(int size) + : gr::vmcircbuf(size) + { +#if !defined(HAVE_SYS_SHM_H) + fprintf(stderr, "gr::vmcircbuf_sysv_shm: sysv shared memory is not available\n"); + throw std::runtime_error("gr::vmcircbuf_sysv_shm"); +#else + + int pagesize = gr::pagesize(); + + if(size <= 0 || (size % pagesize) != 0) { + fprintf(stderr, "gr::vmcircbuf_sysv_shm: invalid size = %d\n", size); + throw std::runtime_error("gr::vmcircbuf_sysv_shm"); + } + + int shmid_guard = -1; + int shmid1 = -1; + int shmid2 = -1; + + // We use this as a guard page. We'll map it read-only on both ends of the buffer. + // Ideally we'd map it no access, but I don't think that's possible with SysV + if((shmid_guard = shmget(IPC_PRIVATE, pagesize, IPC_CREAT | 0400)) == -1) { + perror("gr::vmcircbuf_sysv_shm: shmget (0)"); + throw std::runtime_error("gr::vmcircbuf_sysv_shm"); + } + + if((shmid2 = shmget(IPC_PRIVATE, 2 * size + 2 * pagesize, IPC_CREAT | 0700)) == -1) { + perror("gr::vmcircbuf_sysv_shm: shmget(1)"); + shmctl(shmid_guard, IPC_RMID, 0); + throw std::runtime_error ("gr::vmcircbuf_sysv_shm"); + } + + if((shmid1 = shmget(IPC_PRIVATE, size, IPC_CREAT | 0700)) == -1) { + perror("gr::vmcircbuf_sysv_shm: shmget (2)"); + shmctl(shmid_guard, IPC_RMID, 0); + shmctl(shmid2, IPC_RMID, 0); + throw std::runtime_error("gr::vmcircbuf_sysv_shm"); + } + + void *first_copy = shmat (shmid2, 0, 0); + if(first_copy == (void *) -1) { + perror("gr::vmcircbuf_sysv_shm: shmat(1)"); + shmctl(shmid_guard, IPC_RMID, 0); + shmctl(shmid2, IPC_RMID, 0); + shmctl(shmid1, IPC_RMID, 0); + throw std::runtime_error("gr::vmcircbuf_sysv_shm"); + } + + shmctl(shmid2, IPC_RMID, 0); + + // There may be a race between our detach and attach. + // + // If the system allocates all shared memory segments at the same + // virtual addresses in all processes and if the system allocates + // some other segment to first_copy or first_copoy + size between + // our detach and attach, the attaches below could fail [I've never + // seen it fail for this reason]. + shmdt(first_copy); + + // first read-only guard page + if(shmat(shmid_guard, first_copy, SHM_RDONLY) == (void *) -1) { + perror("gr::vmcircbuf_sysv_shm: shmat(2)"); + shmctl(shmid_guard, IPC_RMID, 0); + shmctl(shmid1, IPC_RMID, 0); + throw std::runtime_error("gr::vmcircbuf_sysv_shm"); + } + + // first copy + if(shmat (shmid1, (char*)first_copy + pagesize, 0) == (void *) -1) { + perror("gr::vmcircbuf_sysv_shm: shmat (3)"); + shmctl(shmid_guard, IPC_RMID, 0); + shmctl(shmid1, IPC_RMID, 0); + shmdt(first_copy); + throw std::runtime_error("gr::vmcircbuf_sysv_shm"); + } + + // second copy + if(shmat (shmid1, (char*)first_copy + pagesize + size, 0) == (void *) -1) { + perror("gr::vmcircbuf_sysv_shm: shmat (4)"); + shmctl(shmid_guard, IPC_RMID, 0); + shmctl(shmid1, IPC_RMID, 0); + shmdt((char *)first_copy + pagesize); + throw std::runtime_error("gr::vmcircbuf_sysv_shm"); + } + + // second read-only guard page + if(shmat(shmid_guard, (char*)first_copy + pagesize + 2 * size, SHM_RDONLY) == (void *) -1) { + perror("gr::vmcircbuf_sysv_shm: shmat(5)"); + shmctl(shmid_guard, IPC_RMID, 0); + shmctl(shmid1, IPC_RMID, 0); + shmdt(first_copy); + shmdt((char *)first_copy + pagesize); + shmdt((char *)first_copy + pagesize + size); + throw std::runtime_error ("gr::vmcircbuf_sysv_shm"); + } + + shmctl(shmid1, IPC_RMID, 0); + shmctl(shmid_guard, IPC_RMID, 0); + + // Now remember the important stuff + d_base = (char*)first_copy + pagesize; + d_size = size; +#endif + } + + vmcircbuf_sysv_shm::~vmcircbuf_sysv_shm() + { +#if defined(HAVE_SYS_SHM_H) + if(shmdt(d_base - gr::pagesize()) == -1 + || shmdt(d_base) == -1 + || shmdt(d_base + d_size) == -1 + || shmdt(d_base + 2 * d_size) == -1){ + perror("gr::vmcircbuf_sysv_shm: shmdt(2)"); + } +#endif + } + + // ---------------------------------------------------------------- + // The factory interface + // ---------------------------------------------------------------- + + gr::vmcircbuf_factory *vmcircbuf_sysv_shm_factory::s_the_factory = 0; + + gr::vmcircbuf_factory * + vmcircbuf_sysv_shm_factory::singleton() + { + if(s_the_factory) + return s_the_factory; + + s_the_factory = new gr::vmcircbuf_sysv_shm_factory(); + return s_the_factory; + } + + int + vmcircbuf_sysv_shm_factory::granularity() + { + return gr::pagesize(); + } + + gr::vmcircbuf * + vmcircbuf_sysv_shm_factory::make(int size) + { + try { + return new vmcircbuf_sysv_shm(size); + } + catch (...) { + return 0; + } + } + +} /* namespace gr */ diff --git a/gnuradio-runtime/lib/vmcircbuf_sysv_shm.h b/gnuradio-runtime/lib/vmcircbuf_sysv_shm.h new file mode 100644 index 0000000000..08e0040bf1 --- /dev/null +++ b/gnuradio-runtime/lib/vmcircbuf_sysv_shm.h @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef GR_VMCIRCBUF_SYSV_SHM_H +#define GR_VMCIRCBUF_SYSV_SHM_H + +#include <gnuradio/api.h> +#include "vmcircbuf.h" + +namespace gr { + + /*! + * \brief concrete class to implement circular buffers with mmap and shm_open + * \ingroup internal + */ + class GR_RUNTIME_API vmcircbuf_sysv_shm : public gr::vmcircbuf + { + public: + vmcircbuf_sysv_shm(int size); + virtual ~vmcircbuf_sysv_shm(); + }; + + /*! + * \brief concrete factory for circular buffers built using mmap and shm_open + */ + class GR_RUNTIME_API vmcircbuf_sysv_shm_factory : public gr::vmcircbuf_factory + { + private: + static gr::vmcircbuf_factory *s_the_factory; + + public: + static gr::vmcircbuf_factory *singleton(); + + virtual const char *name() const { return "gr::vmcircbuf_sysv_shm_factory"; } + + /*! + * \brief return granularity of mapping, typically equal to page size + */ + virtual int granularity(); + + /*! + * \brief return a gr::vmcircbuf, or 0 if unable. + * + * Call this to create a doubly mapped circular buffer. + */ + virtual gr::vmcircbuf *make(int size); + }; + +} /* namespace gr */ + +#endif /* GR_VMCIRCBUF_SYSV_SHM_H */ diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/CMakeLists.txt b/gnuradio-runtime/python/gnuradio/ctrlport/CMakeLists.txt index af563d3327..c910433cf7 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/CMakeLists.txt +++ b/gnuradio-runtime/python/gnuradio/ctrlport/CMakeLists.txt @@ -21,15 +21,15 @@ include(GrPython) EXECUTE_PROCESS( - COMMAND ${ICE_SLICE2PY} -I${CMAKE_SOURCE_DIR}/gnuradio-runtime/lib + COMMAND ${ICE_SLICE2PY} -I${CMAKE_SOURCE_DIR}/gnuradio-runtime/lib/controlport --output-dir=${CMAKE_BINARY_DIR}/gnuradio-runtime/python - ${CMAKE_SOURCE_DIR}/gnuradio-runtime/lib/gnuradio.ice + ${CMAKE_SOURCE_DIR}/gnuradio-runtime/lib/controlport/gnuradio.ice ) EXECUTE_PROCESS( - COMMAND ${ICE_SLICE2PY} -I${CMAKE_SOURCE_DIR}/gnuradio-runtime/lib + COMMAND ${ICE_SLICE2PY} -I${CMAKE_SOURCE_DIR}/gnuradio-runtime/lib/controlport --output-dir=${CMAKE_BINARY_DIR}/gnuradio-runtime/python - ${CMAKE_SOURCE_DIR}/gnuradio-runtime/lib/frontend.ice + ${CMAKE_SOURCE_DIR}/gnuradio-runtime/lib/controlport/frontend.ice ) GR_PYTHON_INSTALL( diff --git a/gnuradio-runtime/python/gnuradio/gr/__init__.py b/gnuradio-runtime/python/gnuradio/gr/__init__.py index c1d6c87629..20a8f97f63 100644 --- a/gnuradio-runtime/python/gnuradio/gr/__init__.py +++ b/gnuradio-runtime/python/gnuradio/gr/__init__.py @@ -36,4 +36,4 @@ from tag_utils import * from gateway import basic_block, sync_block, decim_block, interp_block # Force the preference database to be initialized -prefs = gr_prefs.singleton +prefs = prefs.singleton diff --git a/gnuradio-runtime/python/gnuradio/gr/gateway.py b/gnuradio-runtime/python/gnuradio/gr/gateway.py index b595959494..4ff0c4fe00 100644 --- a/gnuradio-runtime/python/gnuradio/gr/gateway.py +++ b/gnuradio-runtime/python/gnuradio/gr/gateway.py @@ -21,7 +21,7 @@ import runtime_swig as gr from runtime_swig import io_signature, io_signaturev -from runtime_swig import gr_block_gw_message_type +from runtime_swig import block_gw_message_type from runtime_swig import block_gateway import numpy @@ -107,16 +107,16 @@ class gateway_block(object): self.__handler.init(self.__gr_block_handle) self.__gateway = block_gateway( self.__handler, name, gr_in_sig, gr_out_sig, work_type, factor) - self.__message = self.__gateway.gr_block_message() + self.__message = self.__gateway.block_message() #dict to keep references to all message handlers self.__msg_handlers = {} - #register gr_block functions - prefix = 'gr_block__' + #register block functions + prefix = 'block__' for attr in [x for x in dir(self.__gateway) if x.startswith(prefix)]: setattr(self, attr.replace(prefix, ''), getattr(self.__gateway, attr)) - self.pop_msg_queue = lambda: gr.gr_block_gw_pop_msg_queue_safe(self.__gateway) + self.pop_msg_queue = lambda: gr.block_gw_pop_msg_queue_safe(self.__gateway) def to_basic_block(self): """ @@ -128,7 +128,7 @@ class gateway_block(object): """ Dispatch tasks according to the action type specified in the message. """ - if self.__message.action == gr_block_gw_message_type.ACTION_GENERAL_WORK: + if self.__message.action == gr.block_gw_message_type.ACTION_GENERAL_WORK: self.__message.general_work_args_return_value = self.general_work( input_items=[pointer_to_ndarray( @@ -144,7 +144,7 @@ class gateway_block(object): ) for i in self.__out_indexes], ) - elif self.__message.action == gr_block_gw_message_type.ACTION_WORK: + elif self.__message.action == gr.block_gw_message_type.ACTION_WORK: self.__message.work_args_return_value = self.work( input_items=[pointer_to_ndarray( @@ -160,16 +160,16 @@ class gateway_block(object): ) for i in self.__out_indexes], ) - elif self.__message.action == gr_block_gw_message_type.ACTION_FORECAST: + elif self.__message.action == gr.block_gw_message_type.ACTION_FORECAST: self.forecast( noutput_items=self.__message.forecast_args_noutput_items, ninput_items_required=self.__message.forecast_args_ninput_items_required, ) - elif self.__message.action == gr_block_gw_message_type.ACTION_START: + elif self.__message.action == gr.block_gw_message_type.ACTION_START: self.__message.start_args_return_value = self.start() - elif self.__message.action == gr_block_gw_message_type.ACTION_STOP: + elif self.__message.action == gr.block_gw_message_type.ACTION_STOP: self.__message.stop_args_return_value = self.stop() def forecast(self, noutput_items, ninput_items_required): diff --git a/gnuradio-runtime/python/gnuradio/gr/prefs.py b/gnuradio-runtime/python/gnuradio/gr/prefs.py index 25fa8cd6ae..abba6b57a6 100644 --- a/gnuradio-runtime/python/gnuradio/gr/prefs.py +++ b/gnuradio-runtime/python/gnuradio/gr/prefs.py @@ -20,7 +20,7 @@ # import gnuradio_core as gsp -_prefs_base = gsp.gr_prefs +_prefs_base = gsp.prefs import ConfigParser diff --git a/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py b/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py index de1b5aa002..3a0e7889f9 100755 --- a/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py +++ b/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py @@ -38,7 +38,7 @@ class test_tag_utils (gr_unittest.TestCase): self.tb = None def test_001(self): - t = gr.gr_tag_t() + t = gr.tag_t() t.offset = 10 t.key = pmt.string_to_symbol('key') t.value = pmt.from_long(23) diff --git a/gnuradio-runtime/python/gnuradio/gr/tag_utils.py b/gnuradio-runtime/python/gnuradio/gr/tag_utils.py index 8de7110e3f..e35564c1eb 100644 --- a/gnuradio-runtime/python/gnuradio/gr/tag_utils.py +++ b/gnuradio-runtime/python/gnuradio/gr/tag_utils.py @@ -25,7 +25,7 @@ import pmt try: from gnuradio import gr except ImportError: - from runtime_swig import gr_tag_t + from runtime_swig import tag_t class PythonTag(object): " Python container for tags " @@ -46,7 +46,7 @@ def tag_to_python(tag): def tag_to_pmt(tag): """ Convert a Python-readable object to a stream tag """ - newtag = gr_tag_t() + newtag = tag_t() newtag.offset = tag.offset newtag.key = pmt.to_python(tag.key) newtag.value = pmt.from_python(tag.value) diff --git a/gnuradio-runtime/swig/CMakeLists.txt b/gnuradio-runtime/swig/CMakeLists.txt index 3bff08383f..b2fcb180b2 100644 --- a/gnuradio-runtime/swig/CMakeLists.txt +++ b/gnuradio-runtime/swig/CMakeLists.txt @@ -90,38 +90,32 @@ GR_SWIG_INSTALL( install( FILES gnuradio_swig_bug_workaround.h + runtime_swig.i complex_vec_test.i gnuradio.i - gr_basic_block.i - gr_block_detail.i - gr_block.i - gr_buffer.i - gr_constants.i + basic_block.i + constants.i gr_ctrlport.i - gr_dispatcher.i - gr_error_handler.i - gr_feval.i - gr_hier_block2.i - gr_io_signature.i + dispatcher.i + error_handler.i + feval.i + hier_block2.i + io_signature.i + message.i + msg_handler.i + msg_queue.i + prefs.i + realtime.i + single_threaded_scheduler.i + tagged_stream_block.i + tags.i + top_block.i + block_gateway.i gr_logger.i - gr_message.i - gr_msg_handler.i - gr_msg_queue.i - gr_prefs.i - gr_realtime.i gr_shared_ptr.i - gr_single_threaded_scheduler.i gr_swig_block_magic.i - gr_sync_block.i - gr_sync_decimator.i - gr_sync_interpolator.i - gr_tagged_stream_block.i - gr_tags.i - gr_top_block.i gr_types.i gr_extras.i - runtime_block_gateway.i - runtime_swig.i gr_intrusive_ptr.i pmt_swig.i ${CMAKE_CURRENT_BINARY_DIR}/runtime_swig_doc.i diff --git a/gnuradio-runtime/swig/gr_basic_block.i b/gnuradio-runtime/swig/basic_block.i index 2e703278c5..f4ed86aefc 100644 --- a/gnuradio-runtime/swig/gr_basic_block.i +++ b/gnuradio-runtime/swig/basic_block.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006,2010 Free Software Foundation, Inc. + * Copyright 2006,2010,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,44 +20,46 @@ * Boston, MA 02110-1301, USA. */ -class gr_basic_block; -typedef boost::shared_ptr<gr_basic_block> gr_basic_block_sptr; -%template(gr_basic_block_sptr) boost::shared_ptr<gr_basic_block>; +class gr::basic_block; +typedef boost::shared_ptr<gr::basic_block> gr::basic_block_sptr; +%template(basic_block_sptr) boost::shared_ptr<gr::basic_block>; %include "pmt_swig.i" -using namespace pmt; // support vectors of these... namespace std { - %template(x_vector_gr_basic_block_sptr) vector<gr_basic_block_sptr>; + %template(x_vector_basic_block_sptr) vector<gr::basic_block_sptr>; }; -class gr_basic_block -{ -protected: - gr_basic_block(); +namespace gr { -public: - virtual ~gr_basic_block(); + class gr::basic_block + { + protected: + basic_block(); + + public: + virtual ~basic_block(); std::string name() const; std::string symbol_name() const; - gr_io_signature_sptr input_signature() const; - gr_io_signature_sptr output_signature() const; + gr::io_signature::sptr input_signature() const; + gr::io_signature::sptr output_signature() const; long unique_id() const; - gr_basic_block_sptr to_basic_block(); - bool check_topology (int ninputs, int noutputs); + gr::basic_block_sptr to_basic_block(); + bool check_topology(int ninputs, int noutputs); std::string alias(); void set_block_alias(std::string name); - void _post(pmt_t which_port, pmt_t msg); - pmt_t message_ports_in(); - pmt_t message_ports_out(); -}; + void _post(pmt::pmt_t which_port, pmt::pmt_t msg); + pmt::pmt_t message_ports_in(); + pmt::pmt_t message_ports_out(); + }; -%rename(block_ncurrently_allocated) gr_basic_block_ncurrently_allocated; -long gr_basic_block_ncurrently_allocated(); + %rename(block_ncurrently_allocated) basic_block_ncurrently_allocated; + long basic_block_ncurrently_allocated(); +} #ifdef SWIGPYTHON %pythoncode %{ -gr_basic_block_sptr.__repr__ = lambda self: "<gr_basic_block %s (%d)>" % (self.name(), self.unique_id ()) +basic_block_sptr.__repr__ = lambda self: "<basic_block %s (%d)>" % (self.name(), self.unique_id ()) %} #endif diff --git a/gnuradio-runtime/swig/gr_block.i b/gnuradio-runtime/swig/block.i index a53489f9a2..f697089185 100644 --- a/gnuradio-runtime/swig/gr_block.i +++ b/gnuradio-runtime/swig/block.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004,2010 Free Software Foundation, Inc. + * Copyright 2004,2010,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,26 +20,27 @@ * Boston, MA 02110-1301, USA. */ -%include <gr_basic_block.i> +%include <basic_block.i> -class gr_block; -typedef boost::shared_ptr<gr_block> gr_block_sptr; -%template(gr_block_sptr) boost::shared_ptr<gr_block>; +class gr::block; +typedef boost::shared_ptr<gr::block> gr::block_sptr; +%template(block_sptr) boost::shared_ptr<gr::block>; // support vectors of these... namespace std { - %template(x_vector_gr_block_sptr) vector<gr_block_sptr>; + %template(x_vector_block_sptr) vector<gr::block_sptr>; }; -class gr_block : public gr_basic_block { +class gr::block : public gr::basic_block +{ protected: - gr_block (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature); + block (const std::string &name, + gr::io_signature::sptr input_signature, + gr::io_signature::sptr output_signature); public: - virtual ~gr_block (); + virtual ~block (); unsigned history () const; @@ -88,6 +89,6 @@ class gr_block : public gr_basic_block { std::vector<int> processor_affinity(); // internal use - gr_block_detail_sptr detail () const { return d_detail; } - void set_detail (gr_block_detail_sptr detail) { d_detail = detail; } + //block_detail_sptr detail () const { return d_detail; } + //void set_detail (block_detail_sptr detail) { d_detail = detail; } }; diff --git a/gnuradio-runtime/swig/block_detail.i b/gnuradio-runtime/swig/block_detail.i new file mode 100644 index 0000000000..a43e02bc6a --- /dev/null +++ b/gnuradio-runtime/swig/block_detail.i @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +class gr::block_detail; +typedef boost::shared_ptr<gr::block_detail> gr::block_detail_sptr; +%template(block_detail_sptr) boost::shared_ptr<gr::block_detail>; +%rename(block_detail) gr::make_block_detail; +%ignore gr::block_detail; + +gr::block_detail_sptr gr:: +gr::make_block_detail(unsigned int ninputs, unsigned int noutputs); + +namespace gr { + + class gr::block_detail { + public: + + ~block_detail (); + + int ninputs() const; + int noutputs() const; + bool sink_p() const; + bool source_p() const; + + void set_input(unsigned int which, gr::buffer_reader_sptr reader); + gr::buffer_reader_sptr input(unsigned int which); + + void set_output(unsigned int which, gr::buffer_sptr buffer); + gr::buffer_sptr output(unsigned int which); + + private: + block_detail(unsigned int ninputs, unsigned int noutputs); + }; + + %rename(block_detail_ncurrently_allocated) block_detail_ncurrently_allocated; + long block_detail_ncurrently_allocated(); +} diff --git a/gnuradio-runtime/swig/runtime_block_gateway.i b/gnuradio-runtime/swig/block_gateway.i index 52d4194dee..95207a80a2 100644 --- a/gnuradio-runtime/swig/runtime_block_gateway.i +++ b/gnuradio-runtime/swig/block_gateway.i @@ -24,8 +24,8 @@ // standard includes //////////////////////////////////////////////////////////////////////// %include <gnuradio.i> -%include <gr_tags.i> -%include <gr_feval.i> +%include <tags.i> +%include <feval.i> %template(void_start_vector_t) std::vector<void *>; @@ -33,11 +33,17 @@ // block headers //////////////////////////////////////////////////////////////////////// %{ -#include <runtime_block_gateway.h> +#include <gnuradio/block_gateway.h> %} //////////////////////////////////////////////////////////////////////// // block magic //////////////////////////////////////////////////////////////////////// -GR_SWIG_BLOCK_MAGIC(runtime, block_gateway); -%include <runtime_block_gateway.h> +%include <gnuradio/block_gateway.h> + +%template(block_gateway_sptr) boost::shared_ptr<gr::block_gateway>; +%pythoncode %{ +block_gateway_sptr.__repr__ = lambda self: "<block_gateway>" +block_gateway = block_gateway.make; +%} + diff --git a/gnuradio-runtime/swig/buffer.i b/gnuradio-runtime/swig/buffer.i new file mode 100644 index 0000000000..44bd4887a8 --- /dev/null +++ b/gnuradio-runtime/swig/buffer.i @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +class gr::buffer; +typedef boost::shared_ptr<gr::buffer> gr::buffer_sptr; +%template(buffer_sptr) boost::shared_ptr<gr::buffer>; +%rename(buffer) gr::make_buffer; +%ignore gr::buffer; + +gr::buffer_sptr +gr::make_buffer (int nitems, size_t sizeof_item, gr::block_sptr link); + +class gr::buffer_reader; +typedef boost::shared_ptr<gr::buffer_reader> gr::buffer_reader_sptr; +%template(buffer_reader_sptr) boost::shared_ptr<gr::buffer_reader>; +%ignore gr::buffer_reader; + +%rename(buffer_add_reader) gr::buffer_add_reader; +gr::buffer_reader_sptr +gr::buffer_add_reader (gr::buffer_sptr buf, int nzero_preload, gr::block_sptr link); + +namespace gr { + + class gr::buffer + { + public: + ~buffer(); + + private: + buffer(int nitems, size_t sizeof_item, gr::block_sptr link); + }; + + class gr::buffer_reader + { + public: + ~buffer_reader(); + + private: + friend class buffer; + buffer_reader(gr::buffer_sptr buffer, unsigned int read_index, gr::block_sptr link); + }; + + %rename(buffer_ncurrently_allocated) buffer_ncurrently_allocated; + long buffer_ncurrently_allocated(); + + %rename(buffer_reader_ncurrently_allocated) buffer_reader_ncurrently_allocated; + long buffer_reader_ncurrently_allocated(); +} diff --git a/gnuradio-runtime/swig/constants.i b/gnuradio-runtime/swig/constants.i new file mode 100644 index 0000000000..ebc6a93515 --- /dev/null +++ b/gnuradio-runtime/swig/constants.i @@ -0,0 +1,13 @@ +/* -*- c++ -*- */ + +%rename(prefix) gr::prefix; +%rename(sysconfdir) gr::sysconfdir; +%rename(prefsdir) gr::prefsdir; +%rename(build_date) gr::build_date; +%rename(version) gr::version; + +const std::string gr::prefix(); +const std::string gr::sysconfdir(); +const std::string gr::prefsdir(); +const std::string gr::build_date(); +const std::string gr::version(); diff --git a/gnuradio-runtime/swig/gr_dispatcher.i b/gnuradio-runtime/swig/dispatcher.i index 28737cd317..4a039c61e3 100644 --- a/gnuradio-runtime/swig/gr_dispatcher.i +++ b/gnuradio-runtime/swig/dispatcher.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2005,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,36 +20,37 @@ * Boston, MA 02110-1301, USA. */ -class gr_dispatcher; -typedef boost::shared_ptr<gr_dispatcher> gr_dispatcher_sptr; -%template(gr_dispatcher_sptr) boost::shared_ptr<gr_dispatcher>; +class gr::dispatcher; +typedef boost::shared_ptr<gr::dispatcher> gr::dispatcher_sptr; +%template(dispatcher_sptr) boost::shared_ptr<gr::dispatcher>; -%rename(dispatcher) gr_make_dispatcher; -gr_dispatcher_sptr gr_make_dispatcher(); +%rename(dispatcher) gr::make_dispatcher; +gr::dispatcher_sptr gr::make_dispatcher(); -%rename(dispatcher_singleton) gr_dispatcher_singleton; -gr_dispatcher_sptr gr_dispatcher_singleton(); +%rename(dispatcher_singleton) gr::dispatcher_singleton; +gr::dispatcher_sptr gr::dispatcher_singleton(); /*! * \brief invoke callbacks based on select. * - * \sa gr_select_handler + * \sa gr::select_handler */ -class gr_dispatcher +class gr::dispatcher { - gr_dispatcher(); + dispatcher(); public: - ~gr_dispatcher(); + ~dispatcher(); /*! * \brief Event dispatching loop. * - * Enter a polling loop that only terminates after all gr_select_handlers - * have been removed. \p timeout sets the timeout parameter to the select() + * Enter a polling loop that only terminates after all gr::select_handlers + * have been removed. \p timeout sets the timeout parameter to the select() * call, measured in seconds. * * \param timeout maximum number of seconds to block in select. */ void loop(double timeout=10); }; + diff --git a/gnuradio-runtime/swig/gr_error_handler.i b/gnuradio-runtime/swig/error_handler.i index 072394a727..8174128fa2 100644 --- a/gnuradio-runtime/swig/gr_error_handler.i +++ b/gnuradio-runtime/swig/error_handler.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2005,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,10 +20,10 @@ * Boston, MA 02110-1301, USA. */ -%rename(error_handler) gr_error_handler; -%rename(file_error_handler) gr_file_error_handler; +%rename(error_handler) gr::error_handler; +%rename(file_error_handler) gr::file_error_handler; -class gr_error_handler { +class gr::error_handler { public: enum seriousness { ERR_DEBUG = 0x00000000, @@ -33,14 +33,14 @@ public: ERR_FATAL = 0x00040000 }; - gr_error_handler() {} - virtual ~gr_error_handler(); + error_handler() {} + virtual ~error_handler(); - static gr_error_handler *default_handler(); - static gr_error_handler *silent_handler(); + static gr::error_handler *default_handler(); + static gr::error_handler *silent_handler(); static bool has_default_handler(); - static void set_default_handler(gr_error_handler *errh); + static void set_default_handler(gr::error_handler *errh); virtual int nwarnings() const = 0; virtual int nerrors() const = 0; @@ -49,21 +49,21 @@ public: void verror_text(seriousness s, const std::string &text); }; -%ignore gr_base_error_handler; -class gr_base_error_handler : public gr_error_handler { +%ignore gr::base_error_handler; +class gr::base_error_handler : public gr::error_handler { int d_nwarnings; int d_nerrors; public: - gr_base_error_handler() : d_nwarnings(0), d_nerrors(0) {} + base_error_handler() : d_nwarnings(0), d_nerrors(0) {} int nwarnings() const { return d_nwarnings; } int nerrors() const { return d_nerrors; } void reset_counts() { d_nwarnings = d_nerrors = 0; } void count_error(seriousness s); }; -class gr_file_error_handler : public gr_base_error_handler { +class gr::file_error_handler : public gr::base_error_handler { public: - gr_file_error_handler(int file_descriptor); - ~gr_file_error_handler(); + file_error_handler(int file_descriptor); + ~file_error_handler(); }; diff --git a/gnuradio-runtime/swig/feval.i b/gnuradio-runtime/swig/feval.i new file mode 100644 index 0000000000..f773346b1b --- /dev/null +++ b/gnuradio-runtime/swig/feval.i @@ -0,0 +1,243 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2010,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +/* + * N.B., this is a _very_ non-standard SWIG .i file + * + * It contains a bunch of magic that is required to ensure that when + * these classes are used as base classes for python code, + * everything works when calling back from C++ into Python. + * + * The gist of the problem is that our C++ code is usually not holding + * the Python Global Interpreter Lock (GIL). Thus if we invoke a + * "director" method from C++, we'll end up in Python not holding the + * GIL. Disaster (SIGSEGV) will result. To avoid this we insert a + * "shim" that grabs and releases the GIL. + * + * If you don't understand SWIG "directors" or the Python GIL, + * don't bother trying to understand what's going on in here. + * + * [We could eliminate a bunch of this hair by requiring SWIG 1.3.29 + * or later and some additional magic declarations, but many systems + * aren't shipping that version yet. Thus we kludge...] + */ + +// Directors are only supported in Python, Java and C# +#ifdef SWIGPYTHON + +%import "pmt_swig.i" + + // Enable SWIG directors for these classes +%feature("director") gr::py_feval_dd; +%feature("director") gr::py_feval_cc; +%feature("director") gr::py_feval_ll; +%feature("director") gr::py_feval; +%feature("director") gr::py_feval_p; + +%feature("nodirector") gr::py_feval_dd::calleval; +%feature("nodirector") gr::py_feval_cc::calleval; +%feature("nodirector") gr::py_feval_ll::calleval; +%feature("nodirector") gr::py_feval::calleval; +%feature("nodirector") gr::py_feval_p::calleval; + +//%exception { +// try { $action } +// catch (Swig::DirectorException &e) { std::cerr << e.getMessage(); SWIG_fail; } +//} + +%{ + +// class that ensures we acquire and release the Python GIL + +class ensure_py_gil_state { + PyGILState_STATE d_gstate; +public: + ensure_py_gil_state() { d_gstate = PyGILState_Ensure(); } + ~ensure_py_gil_state() { PyGILState_Release(d_gstate); } +}; + +%} + +%ignore gr::feval_dd; +%ignore gr::feval_cc; +%ignore gr::feval_ll; +%ignore gr::feval; +%ignore gr::feval_p; + +namespace gr { +/* + * These are the real C++ base classes, however we don't want these exposed. + */ + class gr::feval_dd + { + protected: + virtual double eval(double x); + + public: + feval_dd() {} + virtual ~feval_dd(); + + virtual double calleval(double x); + }; + //%rename(feval_dd) gr::feval_dd; + + class gr::feval_cc + { + protected: + virtual gr_complex eval(gr_complex x); + + public: + feval_cc() {} + virtual ~feval_cc(); + + virtual gr_complex calleval(gr_complex x); + }; + //%rename(feval_cc) gr::feval_cc; + + class gr::feval_ll + { + protected: + virtual long eval(long x); + + public: + feval_ll() {} + virtual ~feval_ll(); + + virtual long calleval(long x); + }; + //%rename(feval_ll) gr::feval_ll; + + class gr::feval + { + protected: + virtual void eval(); + + public: + feval() {} + virtual ~feval(); + + virtual void calleval(); + }; + //%rename(feval) gr::feval; + + class gr::feval_p + { + protected: + virtual void eval(pmt::pmt_t x); + + public: + feval_p() {} + virtual ~feval_p(); + + virtual void calleval(pmt::pmt_t x); + }; + //%rename(feval_p) gr::feval_p; +} + +/* + * These are the ones to derive from in Python. They have the magic shim + * that ensures that we're holding the Python GIL when we enter Python land... + */ + +namespace gr { + %rename(feval_dd) py_feval_dd; + %rename(feval_cc) py_feval_cc; + %rename(feval_ll) py_feval_ll; + %rename(feval) py_feval; + %rename(feval_p) py_feval_p; +} + +%inline %{ +#include <pmt/pmt.h> + + namespace gr { + + class py_feval_dd : public gr::feval_dd + { + public: + double calleval(double x) + { + ensure_py_gil_state _lock; + return eval(x); + } + }; + + class py_feval_cc : public gr::feval_cc + { + public: + gr_complex calleval(gr_complex x) + { + ensure_py_gil_state _lock; + return eval(x); + } + }; + + class py_feval_ll : public gr::feval_ll + { + public: + long calleval(long x) + { + ensure_py_gil_state _lock; + return eval(x); + } + }; + + class py_feval : public gr::feval + { + public: + void calleval() + { + ensure_py_gil_state _lock; + eval(); + } + }; + + class py_feval_p : public gr::feval_p + { + public: + void calleval(pmt::pmt_t x) + { + ensure_py_gil_state _lock; + eval(x); + } + }; + } +%} + +namespace gr { + // examples / test cases + + %rename(feval_dd_example) gr::feval_dd_example; + double gr::feval_dd_example(gr::feval_dd *f, double x); + + %rename(feval_cc_example) gr::feval_cc_example; + gr_complex gr::feval_cc_example(gr::feval_cc *f, gr_complex x); + + %rename(feval_ll_example) gr::feval_ll_example; + long gr::feval_ll_example(gr::feval_ll *f, long x); + + %rename(feval_example) gr::feval_example; + void gr::feval_example(gr::feval *f); +} + +#endif // SWIGPYTHON diff --git a/gnuradio-runtime/swig/gnuradio_swig_bug_workaround.h b/gnuradio-runtime/swig/gnuradio_swig_bug_workaround.h index 1994f06609..ad9168ce9e 100644 --- a/gnuradio-runtime/swig/gnuradio_swig_bug_workaround.h +++ b/gnuradio-runtime/swig/gnuradio_swig_bug_workaround.h @@ -29,17 +29,17 @@ * %import "gnuradio.i" */ -class gr_base_error_handler; -class gr_basic_block; -class gr_block; -class gr_error_handler; -class gr_file_error_handler; -class gr_hier_block2; -class gr_msg_handler; -class gr_msg_queue; -class gr_sync_block; -class gr_sync_decimator; -class gr_sync_interpolator; -class gr_top_block; +class base_error_handler; +class basic_block; +class block; +class error_handler; +class file_error_handler; +class hier_block2; +class msg_handler; +class msg_queue; +class sync_block; +class sync_decimator; +class sync_interpolator; +class top_block; #endif /* INCLUDED_GNURADIO_SWIG_BUG_WORKAROUND_H */ diff --git a/gnuradio-runtime/swig/gr_block_detail.i b/gnuradio-runtime/swig/gr_block_detail.i deleted file mode 100644 index 74ff463604..0000000000 --- a/gnuradio-runtime/swig/gr_block_detail.i +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -class gr_block_detail; -typedef boost::shared_ptr<gr_block_detail> gr_block_detail_sptr; -%template(gr_block_detail_sptr) boost::shared_ptr<gr_block_detail>; -%rename(block_detail) gr_make_block_detail; -%ignore gr_block_detail; - -gr_block_detail_sptr gr_make_block_detail (unsigned int ninputs, unsigned int noutputs); - -class gr_block_detail { - public: - - ~gr_block_detail (); - - int ninputs () const { return d_ninputs; } - int noutputs () const { return d_noutputs; } - bool sink_p () const { return d_noutputs == 0; } - bool source_p () const { return d_ninputs == 0; } - - void set_input (unsigned int which, gr_buffer_reader_sptr reader); - gr_buffer_reader_sptr input (unsigned int which) - { - if (which >= d_ninputs) - throw std::invalid_argument ("gr_block_detail::input"); - return d_input[which]; - } - - void set_output (unsigned int which, gr_buffer_sptr buffer); - gr_buffer_sptr output (unsigned int which) - { - if (which >= d_noutputs) - throw std::invalid_argument ("gr_block_detail::output"); - return d_output[which]; - } - - // ---------------------------------------------------------------------------- - - private: - gr_block_detail (unsigned int ninputs, unsigned int noutputs); - -}; - - -%rename(block_detail_ncurrently_allocated) gr_block_detail_ncurrently_allocated; -long gr_block_detail_ncurrently_allocated (); diff --git a/gnuradio-runtime/swig/gr_buffer.i b/gnuradio-runtime/swig/gr_buffer.i deleted file mode 100644 index 390a94e050..0000000000 --- a/gnuradio-runtime/swig/gr_buffer.i +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -class gr_buffer; -typedef boost::shared_ptr<gr_buffer> gr_buffer_sptr; -%template(gr_buffer_sptr) boost::shared_ptr<gr_buffer>; -%rename(buffer) gr_make_buffer; -%ignore gr_buffer; - -gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item, gr_block_sptr link); - -class gr_buffer { - public: - ~gr_buffer (); - - private: - gr_buffer (int nitems, size_t sizeof_item, gr_block_sptr link); -}; - - -class gr_buffer_reader; -typedef boost::shared_ptr<gr_buffer_reader> gr_buffer_reader_sptr; -%template(gr_buffer_reader_sptr) boost::shared_ptr<gr_buffer_reader>; -%ignore gr_buffer_reader; - -%rename(buffer_add_reader) gr_buffer_add_reader; -gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link); - -class gr_buffer_reader { - public: - ~gr_buffer_reader (); - - private: - friend class gr_buffer; - gr_buffer_reader (gr_buffer_sptr buffer, unsigned int read_index, gr_block_sptr link); -}; - - -%rename(buffer_ncurrently_allocated) gr_buffer_ncurrently_allocated; -long gr_buffer_ncurrently_allocated (); - -%rename(buffer_reader_ncurrently_allocated) gr_buffer_reader_ncurrently_allocated; -long gr_buffer_reader_ncurrently_allocated (); - diff --git a/gnuradio-runtime/swig/gr_constants.i b/gnuradio-runtime/swig/gr_constants.i deleted file mode 100644 index a5aef14925..0000000000 --- a/gnuradio-runtime/swig/gr_constants.i +++ /dev/null @@ -1,13 +0,0 @@ -/* -*- c++ -*- */ - -%rename(prefix) gr_prefix; -%rename(sysconfdir) gr_sysconfdir; -%rename(prefsdir) gr_prefsdir; -%rename(build_date) gr_build_date; -%rename(version) gr_version; - -const std::string gr_prefix(); -const std::string gr_sysconfdir(); -const std::string gr_prefsdir(); -const std::string gr_build_date(); -const std::string gr_version(); diff --git a/gnuradio-runtime/swig/gr_ctrlport.i b/gnuradio-runtime/swig/gr_ctrlport.i index fa3ae845d7..ac05c05ee5 100644 --- a/gnuradio-runtime/swig/gr_ctrlport.i +++ b/gnuradio-runtime/swig/gr_ctrlport.i @@ -53,14 +53,14 @@ enum KnobType { }; %{ -#include <rpcserver_booter_base.h> -#include <rpcserver_booter_aggregator.h> -#include <pycallback_object.h> +#include <gnuradio/rpcserver_booter_base.h> +#include <gnuradio/rpcserver_booter_aggregator.h> +#include <gnuradio/pycallback_object.h> %} -%include <rpcserver_booter_base.h> -%include <rpcserver_booter_aggregator.h> -%include <pycallback_object.h> +%include <gnuradio/rpcserver_booter_base.h> +%include <gnuradio/rpcserver_booter_aggregator.h> +%include <gnuradio/pycallback_object.h> // Declare this class here but without the nested templated class // inside (replaces include of rpcmanager.h) diff --git a/gnuradio-runtime/swig/gr_feval.i b/gnuradio-runtime/swig/gr_feval.i deleted file mode 100644 index e3b8696fa6..0000000000 --- a/gnuradio-runtime/swig/gr_feval.i +++ /dev/null @@ -1,233 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2006,2010 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - - -/* - * N.B., this is a _very_ non-standard SWIG .i file - * - * It contains a bunch of magic that is required to ensure that when - * these classes are used as base classes for python code, - * everything works when calling back from C++ into Python. - * - * The gist of the problem is that our C++ code is usually not holding - * the Python Global Interpreter Lock (GIL). Thus if we invoke a - * "director" method from C++, we'll end up in Python not holding the - * GIL. Disaster (SIGSEGV) will result. To avoid this we insert a - * "shim" that grabs and releases the GIL. - * - * If you don't understand SWIG "directors" or the Python GIL, - * don't bother trying to understand what's going on in here. - * - * [We could eliminate a bunch of this hair by requiring SWIG 1.3.29 - * or later and some additional magic declarations, but many systems - * aren't shipping that version yet. Thus we kludge...] - */ - - -// Directors are only supported in Python, Java and C# -#ifdef SWIGPYTHON -%include "pmt_swig.i" -using namespace pmt; - -// Enable SWIG directors for these classes -%feature("director") gr_py_feval_dd; -%feature("director") gr_py_feval_cc; -%feature("director") gr_py_feval_ll; -%feature("director") gr_py_feval; -%feature("director") gr_py_feval_p; - -%feature("nodirector") gr_py_feval_dd::calleval; -%feature("nodirector") gr_py_feval_cc::calleval; -%feature("nodirector") gr_py_feval_ll::calleval; -%feature("nodirector") gr_py_feval::calleval; -%feature("nodirector") gr_py_feval_p::calleval; - - -%rename(feval_dd) gr_py_feval_dd; -%rename(feval_cc) gr_py_feval_cc; -%rename(feval_ll) gr_py_feval_ll; -%rename(feval) gr_py_feval; -%rename(feval_p) gr_py_feval_p; - -//%exception { -// try { $action } -// catch (Swig::DirectorException &e) { std::cerr << e.getMessage(); SWIG_fail; } -//} - -%{ - -// class that ensures we acquire and release the Python GIL - -class ensure_py_gil_state { - PyGILState_STATE d_gstate; -public: - ensure_py_gil_state() { d_gstate = PyGILState_Ensure(); } - ~ensure_py_gil_state() { PyGILState_Release(d_gstate); } -}; - -%} - -/* - * These are the real C++ base classes, however we don't want these exposed. - */ -%ignore gr_feval_dd; -class gr_feval_dd -{ -protected: - virtual double eval(double x); - -public: - gr_feval_dd() {} - virtual ~gr_feval_dd(); - - virtual double calleval(double x); -}; - -%ignore gr_feval_cc; -class gr_feval_cc -{ -protected: - virtual gr_complex eval(gr_complex x); - -public: - gr_feval_cc() {} - virtual ~gr_feval_cc(); - - virtual gr_complex calleval(gr_complex x); -}; - -%ignore gr_feval_ll; -class gr_feval_ll -{ -protected: - virtual long eval(long x); - -public: - gr_feval_ll() {} - virtual ~gr_feval_ll(); - - virtual long calleval(long x); -}; - -%ignore gr_feval; -class gr_feval -{ -protected: - virtual void eval(); - -public: - gr_feval() {} - virtual ~gr_feval(); - - virtual void calleval(); -}; - -%ignore gr_feval_p; -class gr_feval_p -{ -protected: - virtual void eval(pmt_t x); - -public: - gr_feval_p() {} - virtual ~gr_feval_p(); - - virtual void calleval(pmt_t x); -}; - -/* - * These are the ones to derive from in Python. They have the magic shim - * that ensures that we're holding the Python GIL when we enter Python land... - */ - -%inline %{ -#include <pmt/pmt.h> - -class gr_py_feval_dd : public gr_feval_dd -{ - public: - double calleval(double x) - { - ensure_py_gil_state _lock; - return eval(x); - } -}; - -class gr_py_feval_cc : public gr_feval_cc -{ - public: - gr_complex calleval(gr_complex x) - { - ensure_py_gil_state _lock; - return eval(x); - } -}; - -class gr_py_feval_ll : public gr_feval_ll -{ - public: - long calleval(long x) - { - ensure_py_gil_state _lock; - return eval(x); - } -}; - -class gr_py_feval : public gr_feval -{ - public: - void calleval() - { - ensure_py_gil_state _lock; - eval(); - } -}; - -class gr_py_feval_p : public gr_feval_p -{ - public: - void calleval(pmt::pmt_t x) - { - ensure_py_gil_state _lock; - eval(x); - } -}; - -%} - - - -// examples / test cases - -%rename(feval_dd_example) gr_feval_dd_example; -double gr_feval_dd_example(gr_feval_dd *f, double x); - -%rename(feval_cc_example) gr_feval_cc_example; -gr_complex gr_feval_cc_example(gr_feval_cc *f, gr_complex x); - -%rename(feval_ll_example) gr_feval_ll_example; -long gr_feval_ll_example(gr_feval_ll *f, long x); - -%rename(feval_example) gr_feval_example; -void gr_feval_example(gr_feval *f); - -#endif // SWIGPYTHON diff --git a/gnuradio-runtime/swig/gr_hier_block2.i b/gnuradio-runtime/swig/gr_hier_block2.i deleted file mode 100644 index a857394ca7..0000000000 --- a/gnuradio-runtime/swig/gr_hier_block2.i +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005,2006,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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -%include <gr_basic_block.i> - -class gr_hier_block2; -typedef boost::shared_ptr<gr_hier_block2> gr_hier_block2_sptr; -%template(gr_hier_block2_sptr) boost::shared_ptr<gr_hier_block2>; - -// Hack to have a Python shim implementation of gr.hier_block2 -// that instantiates one of these and passes through calls -%rename(hier_block2_swig) gr_make_hier_block2; -gr_hier_block2_sptr gr_make_hier_block2(const std::string name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature) - throw (std::runtime_error); - -// Rename connect and disconnect so that we can more easily build a -// better interface in scripting land. -%rename(primitive_connect) gr_hier_block2::connect; -%rename(primitive_disconnect) gr_hier_block2::disconnect; -%rename(primitive_msg_connect) gr_hier_block2::msg_connect; -%rename(primitive_msg_disconnect) gr_hier_block2::msg_disconnect; -%rename(primitive_message_port_register_hier_in) gr_hier_block2::message_port_register_hier_in; -%rename(primitive_message_port_register_hier_out) gr_hier_block2::message_port_register_hier_out; - -class gr_hier_block2 : public gr_basic_block -{ -private: - gr_hier_block2(const std::string name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature); - -public: - ~gr_hier_block2 (); - - void connect(gr_basic_block_sptr block) - throw (std::invalid_argument); - void connect(gr_basic_block_sptr src, int src_port, - gr_basic_block_sptr dst, int dst_port) - throw (std::invalid_argument); - void msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, - gr_basic_block_sptr dst, pmt::pmt_t dstport) - throw (std::runtime_error); - void msg_connect(gr_basic_block_sptr src, std::string srcport, - gr_basic_block_sptr dst, std::string dstport) - throw (std::runtime_error); - void msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport, - gr_basic_block_sptr dst, pmt::pmt_t dstport) - throw (std::runtime_error); - void msg_disconnect(gr_basic_block_sptr src, std::string srcport, - gr_basic_block_sptr dst, std::string dstport) - throw (std::runtime_error); - - void disconnect(gr_basic_block_sptr block) - throw (std::invalid_argument); - void disconnect(gr_basic_block_sptr src, int src_port, - gr_basic_block_sptr dst, int dst_port) - throw (std::invalid_argument); - void disconnect_all(); - void lock(); - void unlock(); - - void message_port_register_hier_in(pmt::pmt_t port_id); - void message_port_register_hier_out(pmt::pmt_t port_id); - - - gr_hier_block2_sptr to_hier_block2(); // Needed for Python type coercion -}; diff --git a/gnuradio-runtime/swig/gr_io_signature.i b/gnuradio-runtime/swig/gr_io_signature.i deleted file mode 100644 index fe1707e410..0000000000 --- a/gnuradio-runtime/swig/gr_io_signature.i +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2004,2005,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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -class gr_io_signature; -typedef boost::shared_ptr<gr_io_signature> gr_io_signature_sptr; -%template(gr_io_signature_sptr) boost::shared_ptr<gr_io_signature>; - -%rename(io_signature) gr_make_io_signature; -%rename(io_signature2) gr_make_io_signature2; -%rename(io_signature3) gr_make_io_signature3; -%rename(io_signaturev) gr_make_io_signaturev; - - -gr_io_signature_sptr -gr_make_io_signature(int min_streams, int max_streams, - int sizeof_stream_item); - -gr_io_signature_sptr -gr_make_io_signature2(int min_streams, int max_streams, - int sizeof_stream_item1, - int sizeof_stream_item2 - ); -gr_io_signature_sptr -gr_make_io_signature3(int min_streams, int max_streams, - int sizeof_stream_item1, - int sizeof_stream_item2, - int sizeof_stream_item3 - ); -gr_io_signature_sptr -gr_make_io_signaturev(int min_streams, int max_streams, - const std::vector<int> &sizeof_stream_items); - - -class gr_io_signature { - gr_io_signature (int min_streams, int max_streams, int sizeof_stream_item); - - friend gr_io_signature_sptr - gr_make_io_signaturev(int min_streams, - int max_streams, - const std::vector<int> &sizeof_stream_item); - - public: - - // disabled. Suspected bug in SWIG 1.3.24 - // static const int IO_INFINITE = -1; - - ~gr_io_signature (); - - int min_streams () const { return d_min_streams; } - int max_streams () const { return d_max_streams; } - int sizeof_stream_item (int index) const; - std::vector<int> sizeof_stream_items() const; -}; - diff --git a/gnuradio-runtime/swig/gr_logger.i b/gnuradio-runtime/swig/gr_logger.i index b43bff5a89..d87ee01b44 100644 --- a/gnuradio-runtime/swig/gr_logger.i +++ b/gnuradio-runtime/swig/gr_logger.i @@ -41,39 +41,43 @@ %{ // The .h files -#include <gr_logger.h> +#include <gnuradio/logger.h> %} -%rename(logger) gr_logger; -%rename(logger_config) gr_logger_config; -%rename(logger_get_names) gr_logger_get_logger_names; -%rename(logger_reset_config) gr_logger_reset_config; +%rename(logger) gr::logger; +%rename(logger_config) gr::logger_config; +%rename(logger_get_names) gr::logger_get_logger_names; +%rename(logger_reset_config) gr::logger_reset_config; +namespace gr { -void gr_logger_config(const std::string config_filename,unsigned int watch_period = 0); -std::vector<std::string> gr_logger_get_logger_names(void); -void gr_logger_reset_config(void); + void logger_config(const std::string config_filename, unsigned int watch_period = 0); + std::vector<std::string> logger_get_logger_names(void); + void logger_reset_config(void); -class gr_logger -{ - public: - gr_logger(std::string logger_name); - void set_level(std::string level){GR_LOG_SET_LEVEL(d_logger,level);} - void get_level(std::string &level){GR_LOG_GET_LEVEL(d_logger,level);} - void debug(std::string msg){GR_LOG_DEBUG(d_logger,msg);}; - void info(std::string msg){GR_LOG_INFO(d_logger,msg);}; - void notice(std::string msg){GR_LOG_NOTICE(d_logger,msg);}; - void warn(std::string msg){GR_LOG_WARN(d_logger,msg);}; - void error(std::string msg){GR_LOG_ERROR(d_logger,msg);}; - void crit(std::string msg){GR_LOG_CRIT(d_logger,msg);}; - void alert(std::string msg){GR_LOG_ALERT(d_logger,msg);}; - void fatal(std::string msg){GR_LOG_FATAL(d_logger,msg);}; - void emerg(std::string msg){GR_LOG_EMERG(d_logger,msg);}; - void errorIF(bool cond,std::string msg){GR_LOG_ERRORIF(d_logger,cond,msg);}; - void log_assert(bool cond,std::string msg){GR_LOG_ASSERT(d_logger,cond,msg);}; + class logger + { + public: + logger(std::string logger_name); + void set_level(std::string level){LOG_SET_LEVEL(d_logger,level);} + void get_level(std::string &level){LOG_GET_LEVEL(d_logger,level);} + void debug(std::string msg){LOG_DEBUG(d_logger,msg);}; + void info(std::string msg){LOG_INFO(d_logger,msg);}; + void notice(std::string msg){LOG_NOTICE(d_logger,msg);}; + void warn(std::string msg){LOG_WARN(d_logger,msg);}; + void error(std::string msg){LOG_ERROR(d_logger,msg);}; + void crit(std::string msg){LOG_CRIT(d_logger,msg);}; + void alert(std::string msg){LOG_ALERT(d_logger,msg);}; + void fatal(std::string msg){LOG_FATAL(d_logger,msg);}; + void emerg(std::string msg){LOG_EMERG(d_logger,msg);}; + void errorIF(bool cond,std::string msg){LOG_ERRORIF(d_logger,cond,msg);}; + void log_assert(bool cond,std::string msg){LOG_ASSERT(d_logger,cond,msg);}; void add_console_appender(std::string target,std::string pattern); void add_file_appender(std::string filename,bool append,std::string pattern); - void add_rollingfile_appender(std::string filename,size_t filesize,int bkup_index,bool append,mode_t mode,std::string pattern); -}; + void add_rollingfile_appender(std::string filename, size_t filesize, + int bkup_index, bool append, mode_t mode, + std::string pattern); + }; +} /* namespace gr */ diff --git a/gnuradio-runtime/swig/gr_message.i b/gnuradio-runtime/swig/gr_message.i deleted file mode 100644 index 356bba5b58..0000000000 --- a/gnuradio-runtime/swig/gr_message.i +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -class gr_message; -typedef boost::shared_ptr<gr_message> gr_message_sptr; -%template(gr_message_sptr) boost::shared_ptr<gr_message>; - -%rename(message_from_string) gr_make_message_from_string; -gr_message_sptr -gr_make_message_from_string(const std::string s, long type = 0, double arg1 = 0, double arg2 = 0); - -%rename(message) gr_make_message; -gr_message_sptr -gr_make_message(long type = 0, double arg1 = 0, double arg2 = 0, size_t length = 0); - -/*! - * \brief Message. - * - * The ideas and method names for adjustable message length were - * lifted from the click modular router "Packet" class. - */ -class gr_message { - gr_message (long type, double arg1, double arg2, size_t length); - - unsigned char *buf_data() const { return d_buf_start; } - size_t buf_len() const { return d_buf_end - d_buf_start; } - -public: - ~gr_message (); - - long type() const { return d_type; } - double arg1() const { return d_arg1; } - double arg2() const { return d_arg2; } - - void set_type(long type) { d_type = type; } - void set_arg1(double arg1) { d_arg1 = arg1; } - void set_arg2(double arg2) { d_arg2 = arg2; } - - size_t length() const; - std::string to_string() const; - -}; - -%rename(message_ncurrently_allocated) gr_message_ncurrently_allocated; -long gr_message_ncurrently_allocated(); - diff --git a/gnuradio-runtime/swig/gr_msg_queue.i b/gnuradio-runtime/swig/gr_msg_queue.i deleted file mode 100644 index 65cbe782b9..0000000000 --- a/gnuradio-runtime/swig/gr_msg_queue.i +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- c++ -*- */ -/* - * Copyright 2005,2009,2010,2011 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 3, 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 GNU Radio; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -class gr_msg_queue; -typedef boost::shared_ptr<gr_msg_queue> gr_msg_queue_sptr; -%template(gr_msg_queue_sptr) boost::shared_ptr<gr_msg_queue>; - -%rename(msg_queue) gr_make_msg_queue; -gr_msg_queue_sptr gr_make_msg_queue(unsigned limit=0); - -/*! - * \brief thread-safe message queue - */ -%ignore gr_msg_queue; -class gr_msg_queue : public gr_msg_handler { -public: - gr_msg_queue(unsigned int limit); - ~gr_msg_queue(); - - //! Generic msg_handler method: insert the message. - //void handle(gr_message_sptr msg) { insert_tail (msg); } - - /*! - * \brief Insert message at tail of queue. - * \param msg message - * - * Block if queue if full. - */ - //void insert_tail(gr_message_sptr msg); - - /*! - * \brief Delete message from head of queue and return it. - * Block if no message is available. - */ - //gr_message_sptr delete_head(); - - /*! - * \brief If there's a message in the q, delete it and return it. - * If no message is available, return 0. - */ - gr_message_sptr delete_head_nowait(); - - //! is the queue empty? - bool empty_p() const; - - //! is the queue full? - bool full_p() const; - - //! return number of messages in queue - unsigned int count() const; - - //! Delete all messages from the queue - void flush(); -}; - -/* - * The following kludge-o-rama releases the Python global interpreter - * lock around these potentially blocking calls. We don't want - * libgnuradio-core to be dependent on Python, thus we create these - * functions that serve as replacements for the normal C++ delete_head - * and insert_tail methods. The %pythoncode smashes these new C++ - * functions into the gr.msg_queue wrapper class, so that everything - * appears normal. (An evil laugh is heard in the distance...) - */ -#ifdef SWIGPYTHON -%inline %{ - gr_message_sptr gr_py_msg_queue__delete_head(gr_msg_queue_sptr q) { - gr_message_sptr msg; - GR_PYTHON_BLOCKING_CODE( - msg = q->delete_head(); - ) - return msg; - } - - void gr_py_msg_queue__insert_tail(gr_msg_queue_sptr q, gr_message_sptr msg) { - GR_PYTHON_BLOCKING_CODE( - q->insert_tail(msg); - ) - } -%} - -// smash in new python delete_head and insert_tail methods... -%pythoncode %{ -gr_msg_queue_sptr.delete_head = gr_py_msg_queue__delete_head -gr_msg_queue_sptr.insert_tail = gr_py_msg_queue__insert_tail -gr_msg_queue_sptr.handle = gr_py_msg_queue__insert_tail -%} -#endif // SWIGPYTHON diff --git a/gnuradio-runtime/swig/gr_types.i b/gnuradio-runtime/swig/gr_types.i index b9bf3ba80b..65577bf35b 100644 --- a/gnuradio-runtime/swig/gr_types.i +++ b/gnuradio-runtime/swig/gr_types.i @@ -30,7 +30,7 @@ #include <string> #include <stddef.h> // size_t #include <stdint.h> -#include <gr_types.h> +#include <gnuradio/types.h> %} %include <std_complex.i> diff --git a/gnuradio-runtime/swig/hier_block2.i b/gnuradio-runtime/swig/hier_block2.i new file mode 100644 index 0000000000..b455e02a7e --- /dev/null +++ b/gnuradio-runtime/swig/hier_block2.i @@ -0,0 +1,92 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005-2007,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +%include <basic_block.i> + +class gr::hier_block2; +typedef boost::shared_ptr<gr::hier_block2> gr::hier_block2_sptr; +%template(hier_block2_sptr) boost::shared_ptr<gr::hier_block2>; + +namespace gr { + // Hack to have a Python shim implementation of gr.hier_block2 + // that instantiates one of these and passes through calls + %rename(hier_block2_swig) make_hier_block2; + gr::hier_block2_sptr + make_hier_block2(const std::string name, + gr::io_signature::sptr input_signature, + gr::io_signature::sptr output_signature) + throw (std::runtime_error); +} + +// Rename connect and disconnect so that we can more easily build a +// better interface in scripting land. +%rename(primitive_connect) gr::hier_block2::connect; +%rename(primitive_disconnect) gr::hier_block2::disconnect; +%rename(primitive_msg_connect) gr::hier_block2::msg_connect; +%rename(primitive_msg_disconnect) gr::hier_block2::msg_disconnect; +%rename(primitive_message_port_register_hier_in) gr::hier_block2::message_port_register_hier_in; +%rename(primitive_message_port_register_hier_out) gr::hier_block2::message_port_register_hier_out; + +namespace gr { + class hier_block2 : public gr::basic_block + { + private: + hier_block2(const std::string name, + gr::io_signature::sptr input_signature, + gr::io_signature::sptr output_signature); + + public: + ~hier_block2 (); + + void connect(gr::basic_block_sptr block) + throw (std::invalid_argument); + void connect(gr::basic_block_sptr src, int src_port, + gr::basic_block_sptr dst, int dst_port) + throw (std::invalid_argument); + void msg_connect(gr::basic_block_sptr src, pmt::pmt_t srcport, + gr::basic_block_sptr dst, pmt::pmt_t dstport) + throw (std::runtime_error); + void msg_connect(gr::basic_block_sptr src, std::string srcport, + gr::basic_block_sptr dst, std::string dstport) + throw (std::runtime_error); + void msg_disconnect(gr::basic_block_sptr src, pmt::pmt_t srcport, + gr::basic_block_sptr dst, pmt::pmt_t dstport) + throw (std::runtime_error); + void msg_disconnect(gr::basic_block_sptr src, std::string srcport, + gr::basic_block_sptr dst, std::string dstport) + throw (std::runtime_error); + + void disconnect(gr::basic_block_sptr block) + throw (std::invalid_argument); + void disconnect(gr::basic_block_sptr src, int src_port, + gr::basic_block_sptr dst, int dst_port) + throw (std::invalid_argument); + void disconnect_all(); + void lock(); + void unlock(); + + void message_port_register_hier_in(pmt::pmt_t port_id); + void message_port_register_hier_out(pmt::pmt_t port_id); + + gr::hier_block2_sptr to_hier_block2(); // Needed for Python type coercion + }; +} diff --git a/gnuradio-runtime/swig/io_signature.i b/gnuradio-runtime/swig/io_signature.i new file mode 100644 index 0000000000..53cde17bff --- /dev/null +++ b/gnuradio-runtime/swig/io_signature.i @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005,2007,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +namespace gr { + + class GR_RUNTIME_API io_signature + { + io_signature(int min_streams, int max_streams, + const std::vector<int> &sizeof_stream_items); + + public: + typedef boost::shared_ptr<io_signature> sptr; + + // Avoids a swig warning, otherwise we could just + // #include <gnuradio/io_signature.h> instead of redoing this + // #entire class + //static const int IO_INFINITE = -1; + + ~io_signature(); + + + static sptr make(int min_streams, int max_streams, + int sizeof_stream_item); + static sptr make2(int min_streams, int max_streams, + int sizeof_stream_item1, + int sizeof_stream_item2); + static sptr make3(int min_streams, int max_streams, + int sizeof_stream_item1, + int sizeof_stream_item2, + int sizeof_stream_item3); + static sptr makev(int min_streams, int max_streams, + const std::vector<int> &sizeof_stream_items); + + int min_streams() const { return d_min_streams; } + int max_streams() const { return d_max_streams; } + int sizeof_stream_item(int index) const; + std::vector<int> sizeof_stream_items() const; + }; + +} /* namespace gr */ + + +%template(io_signature_sptr) boost::shared_ptr<gr::io_signature>; +%pythoncode %{ +io_signature_sptr.__repr__ = lambda self: "<io_signature: %d, %d>" % (self.min_streams(), self.max_streams()) +io_signaturev = io_signature.makev; +io_signature3 = io_signature.make3; +io_signature2 = io_signature.make2; +io_signature = io_signature.make; +%} diff --git a/gnuradio-runtime/swig/message.i b/gnuradio-runtime/swig/message.i new file mode 100644 index 0000000000..ac13c40641 --- /dev/null +++ b/gnuradio-runtime/swig/message.i @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +namespace gr { + + /*! + * \brief Message. + * + * The ideas and method names for adjustable message length were + * lifted from the click modular router "Packet" class. + */ + class message + { + public: + typedef boost::shared_ptr<message> sptr; + + private: + message(long type, double arg1, double arg2, size_t length); + + unsigned char *buf_data() const; + size_t buf_len() const; + + public: + static sptr make(long type = 0, double arg1 = 0, double arg2 = 0, size_t length = 0); + + static sptr make_from_string(const std::string s, long type = 0, + double arg1 = 0, double arg2 = 0); + + ~message(); + + long type() const; + double arg1() const; + double arg2() const; + + void set_type(long type); + void set_arg1(double arg1); + void set_arg2(double arg2); + + size_t length() const; + std::string to_string() const; + }; + + %rename(message_ncurrently_allocated) message_ncurrently_allocated; + long message_ncurrently_allocated(); +} + +%template(message_sptr) boost::shared_ptr<gr::message>; +%pythoncode %{ +message_from_string = message.make_from_string +message = message.make +%} diff --git a/gnuradio-runtime/swig/gr_msg_handler.i b/gnuradio-runtime/swig/msg_handler.i index f493dac1b2..6869152889 100644 --- a/gnuradio-runtime/swig/gr_msg_handler.i +++ b/gnuradio-runtime/swig/msg_handler.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2005 Free Software Foundation, Inc. + * Copyright 2005,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -23,10 +23,11 @@ /*! * \brief abstract class of message handlers */ -class gr_msg_handler { +class gr::msg_handler +{ public: - virtual ~gr_msg_handler () = 0; + virtual ~msg_handler () = 0; //! handle \p msg - virtual void handle (gr_message_sptr msg) = 0; + virtual void handle(gr::message::sptr msg) = 0; }; diff --git a/gnuradio-runtime/swig/msg_queue.i b/gnuradio-runtime/swig/msg_queue.i new file mode 100644 index 0000000000..59dff158ce --- /dev/null +++ b/gnuradio-runtime/swig/msg_queue.i @@ -0,0 +1,108 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2009-2011,2013 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 3, 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 GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +namespace gr { + /*! + * \brief thread-safe message queue + */ + class msg_queue : public gr::msg_handler + { + public: + typedef boost::shared_ptr<msg_queue> sptr; + + static sptr make(unsigned int limit=0); + + msg_queue(unsigned int limit); + ~msg_queue(); + + //! Generic msg_handler method: insert the message. + //void handle(gr::message::sptr msg) { insert_tail (msg); } + + /*! + * \brief Insert message at tail of queue. + * \param msg message + * + * Block if queue if full. + */ + //void insert_tail(gr::message::sptr msg); + + /*! + * \brief Delete message from head of queue and return it. + * Block if no message is available. + */ + //gr::message::sptr delete_head(); + + /*! + * \brief If there's a message in the q, delete it and return it. + * If no message is available, return 0. + */ + gr::message::sptr delete_head_nowait(); + + //! is the queue empty? + bool empty_p() const; + + //! is the queue full? + bool full_p() const; + + //! return number of messages in queue + unsigned int count() const; + + //! Delete all messages from the queue + void flush(); + }; +} + +/* + * The following kludge-o-rama releases the Python global interpreter + * lock around these potentially blocking calls. We don't want + * libgnuradio-core to be dependent on Python, thus we create these + * functions that serve as replacements for the normal C++ delete_head + * and insert_tail methods. The %pythoncode smashes these new C++ + * functions into the gr.msg_queue wrapper class, so that everything + * appears normal. (An evil laugh is heard in the distance...) + */ +#ifdef SWIGPYTHON +%inline %{ + gr::message::sptr py_msg_queue__delete_head(gr::msg_queue::sptr q) { + gr::message::sptr msg; + GR_PYTHON_BLOCKING_CODE( + msg = q->delete_head(); + ) + return msg; + } + + void py_msg_queue__insert_tail(gr::msg_queue::sptr q, gr::message::sptr msg) { + GR_PYTHON_BLOCKING_CODE( + q->insert_tail(msg); + ) + } +%} + +// smash in new python delete_head and insert_tail methods... +%template(msg_queue_sptr) boost::shared_ptr<gr::msg_queue>; +%pythoncode %{ +msg_queue_sptr.delete_head = py_msg_queue__delete_head +msg_queue_sptr.insert_tail = py_msg_queue__insert_tail +msg_queue_sptr.handle = py_msg_queue__insert_tail +msg_queue = msg_queue.make +%} +#endif // SWIGPYTHON diff --git a/gnuradio-runtime/swig/gr_prefs.i b/gnuradio-runtime/swig/prefs.i index c8c4242002..f56c7910ee 100644 --- a/gnuradio-runtime/swig/gr_prefs.i +++ b/gnuradio-runtime/swig/prefs.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2006 Free Software Foundation, Inc. + * Copyright 2006,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,13 +20,13 @@ * Boston, MA 02110-1301, USA. */ -class gr_prefs +class gr::prefs { public: - static gr_prefs *singleton(); - static void set_singleton(gr_prefs *p); + static gr::prefs *singleton(); + static void set_singleton(gr::prefs *p); - virtual ~gr_prefs(); + virtual ~prefs(); std::string to_string(); diff --git a/gnuradio-runtime/swig/gr_realtime.i b/gnuradio-runtime/swig/realtime.i index 4d5c2b856f..d408249a19 100644 --- a/gnuradio-runtime/swig/gr_realtime.i +++ b/gnuradio-runtime/swig/realtime.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2008 Free Software Foundation, Inc. + * Copyright 2008,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,25 +20,26 @@ * Boston, MA 02110-1301, USA. */ -%rename(enable_realtime_scheduling) gr_enable_realtime_scheduling; +%rename(enable_realtime_scheduling) gr::enable_realtime_scheduling; -// NOTE: This is duplicated from gnuradio-runtime/include/gr_realtime.h, +// NOTE: This is duplicated from gnuradio-runtime/include/realtime.h, // and must be kept in sync with it. This is the least evil workaround // for allowing 3rd party code builds to work when GNU Radio is // installed from binary packages into the standard system directories. -// Otherwise, they can't find #include <gr_realtime.h>, since +// Otherwise, they can't find #include <realtime.h>, since // pkg-config strips -I/usr/include from the --cflags path. namespace gr { + namespace impl { - typedef enum { - RT_OK = 0, - RT_NOT_IMPLEMENTED, - RT_NO_PRIVS, - RT_OTHER_ERROR - } rt_status_t; - + typedef enum { + RT_OK = 0, + RT_NOT_IMPLEMENTED, + RT_NO_PRIVS, + RT_OTHER_ERROR + } rt_status_t; + } } -typedef gr::rt_status_t gr_rt_status_t; -gr_rt_status_t gr_enable_realtime_scheduling(); +typedef gr::rt_status_t rt_status_t; +rt_status_t gr::enable_realtime_scheduling(); diff --git a/gnuradio-runtime/swig/runtime_swig.i b/gnuradio-runtime/swig/runtime_swig.i index ae3d1d7dcb..163d4748ec 100644 --- a/gnuradio-runtime/swig/runtime_swig.i +++ b/gnuradio-runtime/swig/runtime_swig.i @@ -33,29 +33,34 @@ %include "gnuradio.i" // the common stuff %{ -#include <gr_endianness.h> -#include <gr_block.h> -#include <gr_block_detail.h> -#include <gr_buffer.h> -#include <gr_constants.h> -#include <gr_dispatcher.h> -#include <gr_error_handler.h> -#include <gr_feval.h> -#include <gr_hier_block2.h> -#include <gr_io_signature.h> -#include <gr_message.h> -#include <gr_msg_handler.h> -#include <gr_msg_queue.h> -#include <gr_prefs.h> -#include <gr_realtime.h> -#include <gr_runtime_types.h> -#include <gr_single_threaded_scheduler.h> -#include <gr_sync_block.h> -#include <gr_sync_decimator.h> -#include <gr_sync_interpolator.h> -#include <gr_tagged_stream_block.h> -#include <gr_tags.h> -#include <gr_top_block.h> +#include <gnuradio/runtime_types.h> +%} + +%include <gnuradio/runtime_types.h> + +%{ +#include <gnuradio/block.h> +#include <gnuradio/block_detail.h> +#include <gnuradio/buffer.h> +#include <gnuradio/constants.h> +#include <gnuradio/dispatcher.h> +#include <gnuradio/endianness.h> +#include <gnuradio/error_handler.h> +#include <gnuradio/feval.h> +#include <gnuradio/hier_block2.h> +#include <gnuradio/io_signature.h> +#include <gnuradio/message.h> +#include <gnuradio/msg_handler.h> +#include <gnuradio/msg_queue.h> +#include <gnuradio/prefs.h> +#include <gnuradio/realtime.h> +#include <gnuradio/single_threaded_scheduler.h> +#include <gnuradio/sync_block.h> +#include <gnuradio/sync_decimator.h> +#include <gnuradio/sync_interpolator.h> +#include <gnuradio/tags.h> +#include <gnuradio/tagged_stream_block.h> +#include <gnuradio/top_block.h> %} %constant int sizeof_char = sizeof(char); @@ -65,30 +70,30 @@ %constant int sizeof_double = sizeof(double); %constant int sizeof_gr_complex = sizeof(gr_complex); -%include <gr_endianness.h> -%include <gr_basic_block.i> -%include <gr_block.i> -%include <gr_block_detail.i> -%include <gr_buffer.i> -%include <gr_constants.i> -%include <gr_dispatcher.i> -%include <gr_error_handler.i> -%include <gr_feval.i> -%include <gr_hier_block2.i> -%include <gr_io_signature.i> -%include <gr_message.i> -%include <gr_msg_handler.i> -%include <gr_msg_queue.i> -%include <gr_prefs.i> -%include <gr_realtime.i> -%include <gr_single_threaded_scheduler.i> -%include <gr_swig_block_magic.i> -%include <gr_sync_block.i> -%include <gr_sync_decimator.i> -%include <gr_sync_interpolator.i> -%include <gr_tagged_stream_block.i> -%include <gr_tags.i> -%include <gr_top_block.i> -%include <runtime_block_gateway.i> +%include <gnuradio/endianness.h> +%include <basic_block.i> +%include <block.i> +%include <block_detail.i> +%include <buffer.i> +%include <constants.i> +%include <dispatcher.i> +%include <feval.i> +%include <error_handler.i> +%include <hier_block2.i> +%include <io_signature.i> +%include <message.i> +%include <msg_handler.i> +%include <msg_queue.i> +%include <prefs.i> +%include <realtime.i> +%include <single_threaded_scheduler.i> +%include <sync_block.i> +%include <sync_decimator.i> +%include <sync_interpolator.i> +%include <tagged_stream_block.i> +%include <tags.i> +%include <top_block.i> +%include <block_gateway.i> +%include <gr_swig_block_magic.i> %include <gr_ctrlport.i> diff --git a/gnuradio-runtime/swig/gr_single_threaded_scheduler.i b/gnuradio-runtime/swig/single_threaded_scheduler.i index 7305cc9ada..f4fbed075c 100644 --- a/gnuradio-runtime/swig/gr_single_threaded_scheduler.i +++ b/gnuradio-runtime/swig/single_threaded_scheduler.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,31 +20,31 @@ * Boston, MA 02110-1301, USA. */ -#include <gr_runtime.h> +#include <gnuradio/runtime.h> -class gr_single_threaded_scheduler; -typedef boost::shared_ptr<gr_single_threaded_scheduler> gr_single_threaded_scheduler_sptr; -%template(gr_single_threaded_scheduler_sptr) boost::shared_ptr<gr_single_threaded_scheduler>; -%rename(single_threaded_scheduler) gr_make_single_threaded_scheduler; -%ignore gr_single_threaded_scheduler; +class gr::single_threaded_scheduler; +typedef boost::shared_ptr<gr::single_threaded_scheduler> gr::single_threaded_scheduler_sptr; +%template(single_threaded_scheduler_sptr) boost::shared_ptr<gr::single_threaded_scheduler>; +%rename(single_threaded_scheduler) gr::make_single_threaded_scheduler; +%ignore gr::single_threaded_scheduler; -gr_single_threaded_scheduler_sptr -gr_make_single_threaded_scheduler (const std::vector<gr_block_sptr> &modules); +gr::single_threaded_scheduler_sptr +gr::make_single_threaded_scheduler(const std::vector<gr::block_sptr> &modules); -class gr_single_threaded_scheduler { +class gr::single_threaded_scheduler { public: - ~gr_single_threaded_scheduler (); + ~single_threaded_scheduler (); // void run (); void stop (); private: - gr_single_threaded_scheduler (const std::vector<gr_block_sptr> &modules); + single_threaded_scheduler (const std::vector<block_sptr> &modules); }; #ifdef SWIGPYTHON %inline %{ - void sts_pyrun (gr_single_threaded_scheduler_sptr s) { + void sts_pyrun (gr::single_threaded_scheduler_sptr s) { Py_BEGIN_ALLOW_THREADS; // release global interpreter lock s->run (); Py_END_ALLOW_THREADS; // acquire global interpreter lock diff --git a/gnuradio-runtime/swig/gr_sync_block.i b/gnuradio-runtime/swig/sync_block.i index d3e1bb9578..892e58e4a0 100644 --- a/gnuradio-runtime/swig/gr_sync_block.i +++ b/gnuradio-runtime/swig/sync_block.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -19,11 +19,12 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ -class gr_sync_block : public gr_block + +class gr::sync_block : public gr::block { protected: - gr_sync_block (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature); + sync_block(const std::string &name, + gr::io_signature::sptr input_signature, + gr::io_signature::sptr output_signature); }; diff --git a/gnuradio-runtime/swig/gr_sync_decimator.i b/gnuradio-runtime/swig/sync_decimator.i index af4574b193..9c0506bd54 100644 --- a/gnuradio-runtime/swig/gr_sync_decimator.i +++ b/gnuradio-runtime/swig/sync_decimator.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,12 +20,12 @@ * Boston, MA 02110-1301, USA. */ -class gr_sync_decimator : public gr_sync_block +class gr::sync_decimator : public gr::sync_block { protected: - gr_sync_decimator (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature, - unsigned decimation); + sync_decimator(const std::string &name, + gr::io_signature::sptr input_signature, + gr::io_signature::sptr output_signature, + unsigned decimation); }; diff --git a/gnuradio-runtime/swig/gr_sync_interpolator.i b/gnuradio-runtime/swig/sync_interpolator.i index 6f8b08252f..9ebbb460dd 100644 --- a/gnuradio-runtime/swig/gr_sync_interpolator.i +++ b/gnuradio-runtime/swig/sync_interpolator.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2004 Free Software Foundation, Inc. + * Copyright 2004,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,12 +20,12 @@ * Boston, MA 02110-1301, USA. */ -class gr_sync_interpolator : public gr_sync_block +class gr::sync_interpolator : public gr::sync_block { protected: - gr_sync_interpolator (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature, - unsigned interpolation); + sync_interpolator(const std::string &name, + gr::io_signature::sptr input_signature, + gr::io_signature::sptr output_signature, + unsigned interpolation); }; diff --git a/gnuradio-runtime/swig/gr_tagged_stream_block.i b/gnuradio-runtime/swig/tagged_stream_block.i index 9fc803dca1..10943f58de 100644 --- a/gnuradio-runtime/swig/gr_tagged_stream_block.i +++ b/gnuradio-runtime/swig/tagged_stream_block.i @@ -19,12 +19,13 @@ * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ -class gr_tagged_stream_block : public gr_block + +class gr::tagged_stream_block : public gr::block { protected: - gr_tagged_stream_block (const std::string &name, - gr_io_signature_sptr input_signature, - gr_io_signature_sptr output_signature, - const std::string &length_tag_key); + tagged_stream_block(const std::string &name, + gr::io_signature::sptr input_signature, + gr::io_signature::sptr output_signature, + const std::string &length_tag_key); }; diff --git a/gnuradio-runtime/swig/gr_tags.i b/gnuradio-runtime/swig/tags.i index 828d0147ce..f466e9f60b 100644 --- a/gnuradio-runtime/swig/gr_tags.i +++ b/gnuradio-runtime/swig/tags.i @@ -1,5 +1,5 @@ /* - * Copyright 2011 Free Software Foundation, Inc. + * Copyright 2011,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,13 +20,13 @@ */ %{ -#include <gr_tags.h> +#include <gnuradio/tags.h> %} %include <pmt_swig.i> //for pmt support -%include <gr_tags.h> +%include <gnuradio/tags.h> //gives support for a vector of tags (get tags in range) %include "std_vector.i" -%template(tags_vector_t) std::vector<gr_tag_t>; +%template(tags_vector_t) std::vector<gr::tag_t>; diff --git a/gnuradio-runtime/swig/gr_top_block.i b/gnuradio-runtime/swig/top_block.i index 1612ddf8c5..7639403393 100644 --- a/gnuradio-runtime/swig/gr_top_block.i +++ b/gnuradio-runtime/swig/top_block.i @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2007,2008,2010 Free Software Foundation, Inc. + * Copyright 2007,2008,2010,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -20,50 +20,50 @@ * Boston, MA 02110-1301, USA. */ -class gr_top_block; -typedef boost::shared_ptr<gr_top_block> gr_top_block_sptr; -%template(gr_top_block_sptr) boost::shared_ptr<gr_top_block>; +%template(top_block_sptr) boost::shared_ptr<gr::top_block>; -// Hack to have a Python shim implementation of gr.top_block -// that instantiates one of these and passes through calls -%rename(top_block_swig) gr_make_top_block; -gr_top_block_sptr gr_make_top_block(const std::string name) - throw (std::logic_error); +namespace gr { + // Hack to have a Python shim implementation of gr.top_block + // that instantiates one of these and passes through calls + %rename(top_block_swig) make_top_block; + gr::top_block_sptr make_top_block(const std::string name) + throw (std::logic_error); -class gr_top_block : public gr_hier_block2 -{ -private: - gr_top_block(const std::string &name); - -public: - ~gr_top_block(); + class top_block : public gr::hier_block2 + { + private: + top_block(const std::string &name); - void start(int max_noutput_items=100000000) throw (std::runtime_error); - void stop(); - //void wait(); - //void run() throw (std::runtime_error); - void lock(); - void unlock() throw (std::runtime_error); - std::string edge_list(); - void dump(); + public: + ~top_block(); - int max_noutput_items(); - void set_max_noutput_items(int nmax); + void start(int max_noutput_items=100000000) throw (std::runtime_error); + void stop(); + //void wait(); + //void run() throw (std::runtime_error); + void lock(); + void unlock() throw (std::runtime_error); + std::string edge_list(); + void dump(); - gr_top_block_sptr to_top_block(); // Needed for Python type coercion -}; + int max_noutput_items(); + void set_max_noutput_items(int nmax); + gr::top_block_sptr to_top_block(); // Needed for Python type coercion + }; +} + #ifdef SWIGPYTHON %inline %{ -void top_block_run_unlocked(gr_top_block_sptr r) throw (std::runtime_error) +void top_block_run_unlocked(gr::top_block_sptr r) throw (std::runtime_error) { Py_BEGIN_ALLOW_THREADS; // release global interpreter lock r->run(); Py_END_ALLOW_THREADS; // acquire global interpreter lock } -void top_block_wait_unlocked(gr_top_block_sptr r) throw (std::runtime_error) +void top_block_wait_unlocked(gr::top_block_sptr r) throw (std::runtime_error) { Py_BEGIN_ALLOW_THREADS; // release global interpreter lock r->wait(); |