From e78b3c6b142cdda00a1d2042c56b47c5e31cfb27 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 28 May 2010 18:43:26 -0700 Subject: Made a phony zero-copy interface for those interfaces that are actual copy-interfaces. Using interface in the udp asio transport. --- host/lib/transport/zero_copy.cpp | 140 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 host/lib/transport/zero_copy.cpp (limited to 'host/lib/transport/zero_copy.cpp') diff --git a/host/lib/transport/zero_copy.cpp b/host/lib/transport/zero_copy.cpp new file mode 100644 index 000000000..f69fd2774 --- /dev/null +++ b/host/lib/transport/zero_copy.cpp @@ -0,0 +1,140 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program 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 of the License, or +// (at your option) any later version. +// +// This program 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, see . +// + +#include +#include +#include +#include + +using namespace uhd::transport; + +/*********************************************************************** + * The pure-virtual deconstructor needs an implementation to be happy + **********************************************************************/ +managed_recv_buffer::~managed_recv_buffer(void){ + /* NOP */ +} + +/*********************************************************************** + * Phony zero-copy recv interface implementation + **********************************************************************/ + +//! phony zero-copy recv buffer implementation +class managed_recv_buffer_impl : public managed_recv_buffer{ +public: + managed_recv_buffer_impl(const boost::asio::const_buffer &buff) : _buff(buff){ + /* NOP */ + } + + ~managed_recv_buffer_impl(void){ + delete [] this->cast(); + } + +private: + const boost::asio::const_buffer &get(void) const{ + return _buff; + } + + const boost::asio::const_buffer _buff; +}; + +//! phony zero-copy recv interface implementation +struct phony_zero_copy_recv_if::impl{ + size_t max_buff_size; +}; + +phony_zero_copy_recv_if::phony_zero_copy_recv_if(size_t max_buff_size){ + _impl = new impl; + _impl->max_buff_size = max_buff_size; +} + +phony_zero_copy_recv_if::~phony_zero_copy_recv_if(void){ + delete _impl; +} + +managed_recv_buffer::sptr phony_zero_copy_recv_if::get_recv_buff(void){ + //allocate memory + boost::uint8_t *recv_mem = new boost::uint8_t[_impl->max_buff_size]; + + //call recv() with timeout option + size_t num_bytes = this->recv(boost::asio::buffer(recv_mem, _impl->max_buff_size)); + + //create a new managed buffer to house the data + return managed_recv_buffer::sptr( + new managed_recv_buffer_impl(boost::asio::buffer(recv_mem, num_bytes)) + ); +} + +/*********************************************************************** + * Phony zero-copy send interface implementation + **********************************************************************/ + +//! phony zero-copy send buffer implementation +class managed_send_buffer_impl : public managed_send_buffer{ +public: + typedef boost::function send_fcn_t; + + managed_send_buffer_impl( + const boost::asio::mutable_buffer &buff, + const send_fcn_t &send_fcn + ): + _buff(buff), + _send_fcn(send_fcn) + { + /* NOP */ + } + + ~managed_send_buffer_impl(void){ + /* NOP */ + } + + void commit(size_t num_bytes){ + _send_fcn(boost::asio::buffer(_buff, num_bytes)); + } + +private: + const boost::asio::mutable_buffer &get(void) const{ + return _buff; + } + + const boost::asio::mutable_buffer _buff; + const send_fcn_t _send_fcn; +}; + +//! phony zero-copy send interface implementation +struct phony_zero_copy_send_if::impl{ + boost::uint8_t *send_mem; + managed_send_buffer::sptr send_buff; +}; + +phony_zero_copy_send_if::phony_zero_copy_send_if(size_t max_buff_size){ + _impl = new impl; + _impl->send_mem = new boost::uint8_t[max_buff_size]; + _impl->send_buff = managed_send_buffer::sptr(new managed_send_buffer_impl( + boost::asio::buffer(_impl->send_mem, max_buff_size), + boost::bind(&phony_zero_copy_send_if::send, this, _1) + )); +} + +phony_zero_copy_send_if::~phony_zero_copy_send_if(void){ + delete [] _impl->send_mem; + delete _impl; +} + +managed_send_buffer::sptr phony_zero_copy_send_if::get_send_buff(void){ + return _impl->send_buff; //FIXME there is only ever one send buff, we assume that the caller doesnt hang onto these +} -- cgit v1.2.3 From b2054a45d45ba85e30ff601159b18f5ebd15dd76 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 2 Jun 2010 17:44:20 -0700 Subject: Created macros for dealing with pimpls and implemented in code. --- host/include/uhd/transport/zero_copy.hpp | 27 ++++++++++------ host/include/uhd/usrp/dboard_base.hpp | 4 +-- host/include/uhd/utils/CMakeLists.txt | 1 + host/include/uhd/utils/pimpl.hpp | 55 ++++++++++++++++++++++++++++++++ host/lib/transport/zero_copy.cpp | 7 ++-- host/lib/usrp/dboard_base.cpp | 8 ++--- host/lib/usrp/usrp2/io_impl.cpp | 2 +- host/lib/usrp/usrp2/usrp2_impl.hpp | 3 +- 8 files changed, 85 insertions(+), 22 deletions(-) create mode 100644 host/include/uhd/utils/pimpl.hpp (limited to 'host/lib/transport/zero_copy.cpp') diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp index d6eb89a91..2815e3189 100644 --- a/host/include/uhd/transport/zero_copy.hpp +++ b/host/include/uhd/transport/zero_copy.hpp @@ -19,6 +19,7 @@ #define INCLUDED_UHD_TRANSPORT_ZERO_COPY_HPP #include +#include #include #include #include @@ -156,10 +157,14 @@ namespace uhd{ namespace transport{ */ class UHD_API phony_zero_copy_recv_if : public virtual zero_copy_if{ public: - - //! structors + /*! + * Create a phony zero copy recv interface. + * \param max_buff_size max buffer size in bytes + */ phony_zero_copy_recv_if(size_t max_buff_size); - ~phony_zero_copy_recv_if(void); + + //! destructor + virtual ~phony_zero_copy_recv_if(void); /*! * Get a new receive buffer from this transport object. @@ -167,7 +172,6 @@ namespace uhd{ namespace transport{ managed_recv_buffer::sptr get_recv_buff(void); private: - /*! * Perform a private copying recv. * \param buff the buffer to write data into @@ -175,7 +179,7 @@ namespace uhd{ namespace transport{ */ virtual size_t recv(const boost::asio::mutable_buffer &buff) = 0; - struct impl; impl *_impl; //private implementation details + UHD_PIMPL_DECL(impl) _impl; }; /*! @@ -186,10 +190,14 @@ namespace uhd{ namespace transport{ */ class UHD_API phony_zero_copy_send_if : public virtual zero_copy_if{ public: - - //! structors + /*! + * Create a phony zero copy send interface. + * \param max_buff_size max buffer size in bytes + */ phony_zero_copy_send_if(size_t max_buff_size); - ~phony_zero_copy_send_if(void); + + //! destructor + virtual ~phony_zero_copy_send_if(void); /*! * Get a new send buffer from this transport object. @@ -197,7 +205,6 @@ namespace uhd{ namespace transport{ managed_send_buffer::sptr get_send_buff(void); private: - /*! * Perform a private copying send. * \param buff the buffer to read data from @@ -205,7 +212,7 @@ namespace uhd{ namespace transport{ */ virtual size_t send(const boost::asio::const_buffer &buff) = 0; - struct impl; impl *_impl; //private implementation details + UHD_PIMPL_DECL(impl) _impl; }; }} //namespace diff --git a/host/include/uhd/usrp/dboard_base.hpp b/host/include/uhd/usrp/dboard_base.hpp index 28bf2ae66..e88d39876 100644 --- a/host/include/uhd/usrp/dboard_base.hpp +++ b/host/include/uhd/usrp/dboard_base.hpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -58,8 +59,7 @@ protected: dboard_id_t get_tx_id(void); private: - struct dboard_base_impl; - dboard_base_impl *_impl; + UHD_PIMPL_DECL(impl) _impl; }; /*! diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt index f588c6310..391e684c8 100644 --- a/host/include/uhd/utils/CMakeLists.txt +++ b/host/include/uhd/utils/CMakeLists.txt @@ -20,6 +20,7 @@ INSTALL(FILES assert.hpp exception.hpp gain_handler.hpp + pimpl.hpp props.hpp safe_main.hpp static.hpp diff --git a/host/include/uhd/utils/pimpl.hpp b/host/include/uhd/utils/pimpl.hpp new file mode 100644 index 000000000..09bf0c0a2 --- /dev/null +++ b/host/include/uhd/utils/pimpl.hpp @@ -0,0 +1,55 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program 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 of the License, or +// (at your option) any later version. +// +// This program 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, see . +// + +#ifndef INCLUDED_UHD_UTILS_PIMPL_HPP +#define INCLUDED_UHD_UTILS_PIMPL_HPP + +#include +#include + +/*! \file pimpl.hpp + * "Pimpl idiom" (pointer to implementation idiom). + * The UHD_PIMPL_* macros simplify code overhead for declaring and making pimpls. + * + * Each pimpl is implemented as a shared pointer to the implementation: + * - The container class will not have to deallocate the pimpl. + * - The container class will use the pimpl as a regular pointer. + * - Usage: _impl->method(arg0, arg1) + * - Usage: _impl->member = value; + * + * \see http://en.wikipedia.org/wiki/Opaque_pointer + */ + +/*! + * Make a declaration for a pimpl in a header file. + * - Usage: UHD_PIMPL_DECL(impl) _impl; + * \param _name the name of the pimpl class + */ +#define UHD_PIMPL_DECL(_name) \ + struct _name; boost::shared_ptr<_name> + +/*! + * Make an instance of a pimpl in a source file. + * - Usage: _impl = UHD_PIMPL_MAKE(impl, ()); + * - Usage: _impl = UHD_PIMPL_MAKE(impl, (a0, a1)); + * \param _name the name of the pimpl class + * \param _args the constructor args for the pimpl + */ +#define UHD_PIMPL_MAKE(_name, _args) \ + boost::shared_ptr<_name>(new _name _args) + +#endif /* INCLUDED_UHD_UTILS_PIMPL_HPP */ diff --git a/host/lib/transport/zero_copy.cpp b/host/lib/transport/zero_copy.cpp index f69fd2774..27f41329b 100644 --- a/host/lib/transport/zero_copy.cpp +++ b/host/lib/transport/zero_copy.cpp @@ -58,12 +58,12 @@ struct phony_zero_copy_recv_if::impl{ }; phony_zero_copy_recv_if::phony_zero_copy_recv_if(size_t max_buff_size){ - _impl = new impl; + _impl = UHD_PIMPL_MAKE(impl, ()); _impl->max_buff_size = max_buff_size; } phony_zero_copy_recv_if::~phony_zero_copy_recv_if(void){ - delete _impl; + /* NOP */ } managed_recv_buffer::sptr phony_zero_copy_recv_if::get_recv_buff(void){ @@ -122,7 +122,7 @@ struct phony_zero_copy_send_if::impl{ }; phony_zero_copy_send_if::phony_zero_copy_send_if(size_t max_buff_size){ - _impl = new impl; + _impl = UHD_PIMPL_MAKE(impl, ()); _impl->send_mem = new boost::uint8_t[max_buff_size]; _impl->send_buff = managed_send_buffer::sptr(new managed_send_buffer_impl( boost::asio::buffer(_impl->send_mem, max_buff_size), @@ -132,7 +132,6 @@ phony_zero_copy_send_if::phony_zero_copy_send_if(size_t max_buff_size){ phony_zero_copy_send_if::~phony_zero_copy_send_if(void){ delete [] _impl->send_mem; - delete _impl; } managed_send_buffer::sptr phony_zero_copy_send_if::get_send_buff(void){ diff --git a/host/lib/usrp/dboard_base.cpp b/host/lib/usrp/dboard_base.cpp index bd4b37ef3..eafb8897f 100644 --- a/host/lib/usrp/dboard_base.cpp +++ b/host/lib/usrp/dboard_base.cpp @@ -25,17 +25,17 @@ using namespace uhd::usrp; /*********************************************************************** * dboard_base dboard dboard_base class **********************************************************************/ -struct dboard_base::dboard_base_impl{ +struct dboard_base::impl{ ctor_args_impl args; - dboard_base_impl(ctor_args_t args) : args(*args){} + impl(ctor_args_t args) : args(*args){} }; dboard_base::dboard_base(ctor_args_t args){ - _impl = new dboard_base_impl(args); + _impl = UHD_PIMPL_MAKE(impl, (args)); } dboard_base::~dboard_base(void){ - delete _impl; + /* NOP */ } std::string dboard_base::get_subdev_name(void){ diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 5d425bd8a..18f2d013f 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -122,7 +122,7 @@ void usrp2_impl::io_init(void){ std::cout << "TX samples per packet: " << get_max_send_samps_per_packet() << std::endl; //create new io impl - _io_impl = boost::shared_ptr(new io_impl(_data_transport)); + _io_impl = UHD_PIMPL_MAKE(io_impl, (_data_transport)); } /*********************************************************************** diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index bb4554e8d..40c193866 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -23,6 +23,7 @@ #include "codec_ctrl.hpp" #include "serdes_ctrl.hpp" #include +#include #include #include #include @@ -153,7 +154,7 @@ private: ; uhd::otw_type_t _rx_otw_type, _tx_otw_type; - struct io_impl; boost::shared_ptr _io_impl; + UHD_PIMPL_DECL(io_impl) _io_impl; void io_init(void); //udp transports for control and data -- cgit v1.2.3