// // 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{ impl(size_t max_buff_size) : max_buff_size(max_buff_size){ /* NOP */ } size_t max_buff_size; }; phony_zero_copy_recv_if::phony_zero_copy_recv_if(size_t max_buff_size){ _impl = UHD_PIMPL_MAKE(impl, (max_buff_size)); } phony_zero_copy_recv_if::~phony_zero_copy_recv_if(void){ /* NOP */ } 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 ssize_t num_bytes = this->recv(boost::asio::buffer(recv_mem, _impl->max_buff_size)); if (num_bytes <= 0) return managed_recv_buffer::sptr(); //NULL sptr //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 */ } ssize_t commit(size_t num_bytes){ return _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 = 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), 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; } 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 }