diff options
Diffstat (limited to 'host/include')
-rw-r--r-- | host/include/uhd/transport/CMakeLists.txt | 2 | ||||
-rw-r--r-- | host/include/uhd/transport/alignment_buffer.hpp | 104 | ||||
-rw-r--r-- | host/include/uhd/transport/alignment_buffer.ipp | 140 | ||||
-rw-r--r-- | host/include/uhd/transport/bounded_buffer.hpp | 86 | ||||
-rw-r--r-- | host/include/uhd/transport/bounded_buffer.ipp | 112 | ||||
-rw-r--r-- | host/include/uhd/utils/CMakeLists.txt | 1 | ||||
-rw-r--r-- | host/include/uhd/utils/byteswap.hpp | 99 | ||||
-rw-r--r-- | host/include/uhd/utils/byteswap.ipp | 120 |
8 files changed, 401 insertions, 263 deletions
diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt index 4e1f7aca5..93e9a6485 100644 --- a/host/include/uhd/transport/CMakeLists.txt +++ b/host/include/uhd/transport/CMakeLists.txt @@ -18,7 +18,9 @@ INSTALL(FILES alignment_buffer.hpp + alignment_buffer.ipp bounded_buffer.hpp + bounded_buffer.ipp convert_types.hpp if_addrs.hpp udp_simple.hpp diff --git a/host/include/uhd/transport/alignment_buffer.hpp b/host/include/uhd/transport/alignment_buffer.hpp index 5766c2284..29ba74efc 100644 --- a/host/include/uhd/transport/alignment_buffer.hpp +++ b/host/include/uhd/transport/alignment_buffer.hpp @@ -19,16 +19,14 @@ #define INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_HPP #include <uhd/config.hpp> -#include <uhd/transport/bounded_buffer.hpp> -#include <boost/thread/condition_variable.hpp> +#include <uhd/transport/bounded_buffer.hpp> //time_duration_t #include <boost/shared_ptr.hpp> -#include <utility> #include <vector> namespace uhd{ namespace transport{ /*! - * Imlement a templated alignment buffer: + * Implement a templated alignment buffer: * Used for aligning asynchronously pushed elements with matching ids. */ template <typename elem_type, typename seq_type> class alignment_buffer{ @@ -40,9 +38,7 @@ namespace uhd{ namespace transport{ * \param capacity the maximum elements per index * \param width the number of elements to align */ - static sptr make(size_t capacity, size_t width){ - return sptr(new alignment_buffer(capacity, width)); - } + static sptr make(size_t capacity, size_t width); /*! * Push an element with sequence id into the buffer at index. @@ -51,18 +47,11 @@ namespace uhd{ namespace transport{ * \param index the buffer index * \return true if the element fit without popping for space */ - UHD_INLINE bool push_with_pop_on_full( + virtual bool push_with_pop_on_full( const elem_type &elem, const seq_type &seq, size_t index - ){ - //clear the buffer for this index if the seqs are mis-ordered - if (seq < _last_seqs[index]){ - _buffs[index]->clear(); - _there_was_a_clear = true; - } _last_seqs[index] = seq; - return _buffs[index]->push_with_pop_on_full(buff_contents_type(elem, seq)); - } + ) = 0; /*! * Pop an aligned set of elements from this alignment buffer. @@ -70,85 +59,14 @@ namespace uhd{ namespace transport{ * \param time the timeout time * \return false when the operation times out */ - template <typename elems_type, typename time_type> - bool pop_elems_with_timed_wait(elems_type &elems, const time_type &time){ - buff_contents_type buff_contents_tmp; - std::list<size_t> indexes_to_do(_all_indexes); - - //do an initial pop to load an initial sequence id - size_t index = indexes_to_do.front(); - if (not _buffs[index]->pop_with_timed_wait(buff_contents_tmp, time)) return false; - elems[index] = buff_contents_tmp.first; - seq_type expected_seq_id = buff_contents_tmp.second; - indexes_to_do.pop_front(); - - //get an aligned set of elements from the buffers: - while(indexes_to_do.size() != 0){ - - //respond to a clear by starting from scratch - if(_there_was_a_clear){ - _there_was_a_clear = false; - indexes_to_do = _all_indexes; - index = indexes_to_do.front(); - if (not _buffs[index]->pop_with_timed_wait(buff_contents_tmp, time)) return false; - elems[index] = buff_contents_tmp.first; - expected_seq_id = buff_contents_tmp.second; - indexes_to_do.pop_front(); - } - - //pop an element off for this index - index = indexes_to_do.front(); - if (not _buffs[index]->pop_with_timed_wait(buff_contents_tmp, time)) return false; - - //if the sequence id matches: - // store the popped element into the output, - // remove this index from the list and continue - if (buff_contents_tmp.second == expected_seq_id){ - elems[index] = buff_contents_tmp.first; - indexes_to_do.pop_front(); - continue; - } - - //if the sequence id is older: - // continue with the same index to try again - if (buff_contents_tmp.second < expected_seq_id){ - continue; - } - - //if the sequence id is newer: - // store the popped element into the output, - // add all other indexes back into the list - if (buff_contents_tmp.second > expected_seq_id){ - elems[index] = buff_contents_tmp.first; - expected_seq_id = buff_contents_tmp.second; - indexes_to_do = _all_indexes; - indexes_to_do.remove(index); - continue; - } - } - return true; - } - - private: - //a vector of bounded buffers for each index - typedef std::pair<elem_type, seq_type> buff_contents_type; - typedef bounded_buffer<buff_contents_type> bounded_buffer_type; - typedef boost::shared_ptr<bounded_buffer_type> bounded_buffer_sptr; - std::vector<bounded_buffer_sptr> _buffs; - std::vector<seq_type> _last_seqs; - std::list<size_t> _all_indexes; - bool _there_was_a_clear; - - //private constructor - alignment_buffer(size_t capacity, size_t width) : _last_seqs(width){ - for (size_t i = 0; i < width; i++){ - _buffs.push_back(bounded_buffer_type::make(capacity)); - _all_indexes.push_back(i); - } - _there_was_a_clear = false; - } + virtual bool pop_elems_with_timed_wait( + std::vector<elem_type> &elems, + const time_duration_t &time + ) = 0; }; }} //namespace +#include <uhd/transport/alignment_buffer.ipp> + #endif /* INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_HPP */ diff --git a/host/include/uhd/transport/alignment_buffer.ipp b/host/include/uhd/transport/alignment_buffer.ipp new file mode 100644 index 000000000..f89f2886e --- /dev/null +++ b/host/include/uhd/transport/alignment_buffer.ipp @@ -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 <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_IPP +#define INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_IPP + +#include <uhd/transport/bounded_buffer.hpp> +#include <boost/thread/condition_variable.hpp> +#include <utility> + +namespace uhd{ namespace transport{ namespace{ /*anon*/ + + /*! + * Imlement a templated alignment buffer: + * Used for aligning asynchronously pushed elements with matching ids. + */ + template <typename elem_type, typename seq_type> + class alignment_buffer_impl : public alignment_buffer<elem_type, seq_type>{ + public: + + alignment_buffer_impl(size_t capacity, size_t width) : _last_seqs(width){ + for (size_t i = 0; i < width; i++){ + _buffs.push_back(bounded_buffer<buff_contents_type>::make(capacity)); + _all_indexes.push_back(i); + } + _there_was_a_clear = false; + } + + UHD_INLINE bool push_with_pop_on_full( + const elem_type &elem, + const seq_type &seq, + size_t index + ){ + //clear the buffer for this index if the seqs are mis-ordered + if (seq < _last_seqs[index]){ + _buffs[index]->clear(); + _there_was_a_clear = true; + } _last_seqs[index] = seq; + return _buffs[index]->push_with_pop_on_full(buff_contents_type(elem, seq)); + } + + UHD_INLINE bool pop_elems_with_timed_wait( + std::vector<elem_type> &elems, + const time_duration_t &time + ){ + buff_contents_type buff_contents_tmp; + std::list<size_t> indexes_to_do(_all_indexes); + + //do an initial pop to load an initial sequence id + size_t index = indexes_to_do.front(); + if (not _buffs[index]->pop_with_timed_wait(buff_contents_tmp, time)) return false; + elems[index] = buff_contents_tmp.first; + seq_type expected_seq_id = buff_contents_tmp.second; + indexes_to_do.pop_front(); + + //get an aligned set of elements from the buffers: + while(indexes_to_do.size() != 0){ + + //respond to a clear by starting from scratch + if(_there_was_a_clear){ + _there_was_a_clear = false; + indexes_to_do = _all_indexes; + index = indexes_to_do.front(); + if (not _buffs[index]->pop_with_timed_wait(buff_contents_tmp, time)) return false; + elems[index] = buff_contents_tmp.first; + expected_seq_id = buff_contents_tmp.second; + indexes_to_do.pop_front(); + } + + //pop an element off for this index + index = indexes_to_do.front(); + if (not _buffs[index]->pop_with_timed_wait(buff_contents_tmp, time)) return false; + + //if the sequence id matches: + // store the popped element into the output, + // remove this index from the list and continue + if (buff_contents_tmp.second == expected_seq_id){ + elems[index] = buff_contents_tmp.first; + indexes_to_do.pop_front(); + continue; + } + + //if the sequence id is older: + // continue with the same index to try again + if (buff_contents_tmp.second < expected_seq_id){ + continue; + } + + //if the sequence id is newer: + // store the popped element into the output, + // add all other indexes back into the list + if (buff_contents_tmp.second > expected_seq_id){ + elems[index] = buff_contents_tmp.first; + expected_seq_id = buff_contents_tmp.second; + indexes_to_do = _all_indexes; + indexes_to_do.remove(index); + continue; + } + } + return true; + } + + private: + //a vector of bounded buffers for each index + typedef std::pair<elem_type, seq_type> buff_contents_type; + std::vector<typename bounded_buffer<buff_contents_type>::sptr> _buffs; + std::vector<seq_type> _last_seqs; + std::list<size_t> _all_indexes; + bool _there_was_a_clear; + }; + +}}} //namespace + +namespace uhd{ namespace transport{ + + template <typename elem_type, typename seq_type> + typename alignment_buffer<elem_type, seq_type>::sptr + alignment_buffer<elem_type, seq_type>::make(size_t capacity, size_t width){ + return alignment_buffer<elem_type, seq_type>::sptr( + new alignment_buffer_impl<elem_type, seq_type>(capacity, width) + ); + } + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_IPP */ diff --git a/host/include/uhd/transport/bounded_buffer.hpp b/host/include/uhd/transport/bounded_buffer.hpp index 94c360fba..d1deece96 100644 --- a/host/include/uhd/transport/bounded_buffer.hpp +++ b/host/include/uhd/transport/bounded_buffer.hpp @@ -19,15 +19,16 @@ #define INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_HPP #include <uhd/config.hpp> -#include <boost/bind.hpp> #include <boost/shared_ptr.hpp> -#include <boost/circular_buffer.hpp> -#include <boost/thread/condition.hpp> +#include <boost/date_time/posix_time/posix_time_types.hpp> namespace uhd{ namespace transport{ + //! typedef for the time duration type for wait operations + typedef boost::posix_time::time_duration time_duration_t; + /*! - * Imlement a templated bounded buffer: + * Implement a templated bounded buffer: * Used for passing elements between threads in a producer-consumer model. * The bounded buffer implemented waits and timed waits with condition variables. * The pop operation blocks on the bounded_buffer to become non empty. @@ -41,9 +42,7 @@ namespace uhd{ namespace transport{ * Make a new bounded buffer object. * \param capacity the bounded_buffer capacity */ - static sptr make(size_t capacity){ - return sptr(new bounded_buffer(capacity)); - } + static sptr make(size_t capacity); /*! * Push a new element into the bounded buffer. @@ -52,35 +51,14 @@ namespace uhd{ namespace transport{ * \param elem the new element to push * \return true if the element fit without popping for space */ - UHD_INLINE bool push_with_pop_on_full(const elem_type &elem){ - boost::unique_lock<boost::mutex> lock(_mutex); - if(_buffer.full()){ - _buffer.pop_back(); - _buffer.push_front(elem); - lock.unlock(); - _empty_cond.notify_one(); - return false; - } - else{ - _buffer.push_front(elem); - lock.unlock(); - _empty_cond.notify_one(); - return true; - } - } + virtual bool push_with_pop_on_full(const elem_type &elem) = 0; /*! * Push a new element into the bounded_buffer. * Wait until the bounded_buffer becomes non-full. * \param elem the new element to push */ - UHD_INLINE void push_with_wait(const elem_type &elem){ - boost::unique_lock<boost::mutex> lock(_mutex); - _full_cond.wait(lock, boost::bind(&bounded_buffer<elem_type>::not_full, this)); - _buffer.push_front(elem); - lock.unlock(); - _empty_cond.notify_one(); - } + virtual void push_with_wait(const elem_type &elem) = 0; /*! * Push a new element into the bounded_buffer. @@ -89,28 +67,14 @@ namespace uhd{ namespace transport{ * \param time the timeout time * \return false when the operation times out */ - template<typename time_type> UHD_INLINE - bool push_with_timed_wait(const elem_type &elem, const time_type &time){ - boost::unique_lock<boost::mutex> lock(_mutex); - if (not _full_cond.timed_wait(lock, time, boost::bind(&bounded_buffer<elem_type>::not_full, this))) return false; - _buffer.push_front(elem); - lock.unlock(); - _empty_cond.notify_one(); - return true; - } + virtual bool push_with_timed_wait(const elem_type &elem, const time_duration_t &time) = 0; /*! * Pop an element from the bounded_buffer. * Wait until the bounded_buffer becomes non-empty. * \param elem the element reference pop to */ - UHD_INLINE void pop_with_wait(elem_type &elem){ - boost::unique_lock<boost::mutex> lock(_mutex); - _empty_cond.wait(lock, boost::bind(&bounded_buffer<elem_type>::not_empty, this)); - elem = _buffer.back(); _buffer.pop_back(); - lock.unlock(); - _full_cond.notify_one(); - } + virtual void pop_with_wait(elem_type &elem) = 0; /*! * Pop an element from the bounded_buffer. @@ -119,38 +83,16 @@ namespace uhd{ namespace transport{ * \param time the timeout time * \return false when the operation times out */ - template<typename time_type> UHD_INLINE - bool pop_with_timed_wait(elem_type &elem, const time_type &time){ - boost::unique_lock<boost::mutex> lock(_mutex); - if (not _empty_cond.timed_wait(lock, time, boost::bind(&bounded_buffer<elem_type>::not_empty, this))) return false; - elem = _buffer.back(); _buffer.pop_back(); - lock.unlock(); - _full_cond.notify_one(); - return true; - } + virtual bool pop_with_timed_wait(elem_type &elem, const time_duration_t &time) = 0; /*! * Clear all elements from the bounded_buffer. */ - UHD_INLINE void clear(void){ - boost::unique_lock<boost::mutex> lock(_mutex); - while (not_empty()) _buffer.pop_back(); - lock.unlock(); - _full_cond.notify_one(); - } - - private: - boost::mutex _mutex; - boost::condition _empty_cond, _full_cond; - boost::circular_buffer<elem_type> _buffer; - - bool not_full(void) const{return not _buffer.full();} - bool not_empty(void) const{return not _buffer.empty();} - - //private constructor - bounded_buffer(size_t capacity) : _buffer(capacity){} + virtual void clear(void) = 0; }; }} //namespace +#include <uhd/transport/bounded_buffer.ipp> + #endif /* INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_HPP */ diff --git a/host/include/uhd/transport/bounded_buffer.ipp b/host/include/uhd/transport/bounded_buffer.ipp new file mode 100644 index 000000000..6885b357d --- /dev/null +++ b/host/include/uhd/transport/bounded_buffer.ipp @@ -0,0 +1,112 @@ +// +// 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 <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_IPP +#define INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_IPP + +#include <boost/bind.hpp> +#include <boost/circular_buffer.hpp> +#include <boost/thread/condition.hpp> + +namespace uhd{ namespace transport{ namespace{ /*anon*/ + + template <typename elem_type> + class bounded_buffer_impl : public bounded_buffer<elem_type>{ + public: + + bounded_buffer_impl(size_t capacity) : _buffer(capacity){ + /* NOP */ + } + + UHD_INLINE bool push_with_pop_on_full(const elem_type &elem){ + boost::unique_lock<boost::mutex> lock(_mutex); + if(_buffer.full()){ + _buffer.pop_back(); + _buffer.push_front(elem); + lock.unlock(); + _empty_cond.notify_one(); + return false; + } + else{ + _buffer.push_front(elem); + lock.unlock(); + _empty_cond.notify_one(); + return true; + } + } + + UHD_INLINE void push_with_wait(const elem_type &elem){ + boost::unique_lock<boost::mutex> lock(_mutex); + _full_cond.wait(lock, boost::bind(&bounded_buffer_impl<elem_type>::not_full, this)); + _buffer.push_front(elem); + lock.unlock(); + _empty_cond.notify_one(); + } + + bool push_with_timed_wait(const elem_type &elem, const time_duration_t &time){ + boost::unique_lock<boost::mutex> lock(_mutex); + if (not _full_cond.timed_wait(lock, time, boost::bind(&bounded_buffer_impl<elem_type>::not_full, this))) return false; + _buffer.push_front(elem); + lock.unlock(); + _empty_cond.notify_one(); + return true; + } + + UHD_INLINE void pop_with_wait(elem_type &elem){ + boost::unique_lock<boost::mutex> lock(_mutex); + _empty_cond.wait(lock, boost::bind(&bounded_buffer_impl<elem_type>::not_empty, this)); + elem = _buffer.back(); _buffer.pop_back(); + lock.unlock(); + _full_cond.notify_one(); + } + + bool pop_with_timed_wait(elem_type &elem, const time_duration_t &time){ + boost::unique_lock<boost::mutex> lock(_mutex); + if (not _empty_cond.timed_wait(lock, time, boost::bind(&bounded_buffer_impl<elem_type>::not_empty, this))) return false; + elem = _buffer.back(); _buffer.pop_back(); + lock.unlock(); + _full_cond.notify_one(); + return true; + } + + UHD_INLINE void clear(void){ + boost::unique_lock<boost::mutex> lock(_mutex); + while (not_empty()) _buffer.pop_back(); + lock.unlock(); + _full_cond.notify_one(); + } + + private: + boost::mutex _mutex; + boost::condition _empty_cond, _full_cond; + boost::circular_buffer<elem_type> _buffer; + + bool not_full(void) const{return not _buffer.full();} + bool not_empty(void) const{return not _buffer.empty();} + }; +}}} //namespace + +namespace uhd{ namespace transport{ + + template <typename elem_type> typename bounded_buffer<elem_type>::sptr + bounded_buffer<elem_type>::make(size_t capacity){ + return bounded_buffer<elem_type>::sptr(new bounded_buffer_impl<elem_type>(capacity)); + } + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_IPP */ diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt index c98eec639..36f86054a 100644 --- a/host/include/uhd/utils/CMakeLists.txt +++ b/host/include/uhd/utils/CMakeLists.txt @@ -19,6 +19,7 @@ INSTALL(FILES algorithm.hpp assert.hpp byteswap.hpp + byteswap.ipp exception.hpp gain_handler.hpp pimpl.hpp diff --git a/host/include/uhd/utils/byteswap.hpp b/host/include/uhd/utils/byteswap.hpp index 26d60c2ab..9a1871210 100644 --- a/host/include/uhd/utils/byteswap.hpp +++ b/host/include/uhd/utils/byteswap.hpp @@ -45,103 +45,6 @@ namespace uhd{ } //namespace uhd -/*********************************************************************** - * Platform-specific implementation details for byteswap below: - **********************************************************************/ -#ifdef BOOST_MSVC //http://msdn.microsoft.com/en-us/library/a3140177%28VS.80%29.aspx - #include <stdlib.h> - - UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){ - return _byteswap_ushort(x); - } - - UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){ - return _byteswap_ulong(x); - } - - UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){ - return _byteswap_uint64(x); - } - -#elif defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 2 - - UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){ - return (x>>8) | (x<<8); //DNE return __builtin_bswap16(x); - } - - UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){ - return __builtin_bswap32(x); - } - - UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){ - return __builtin_bswap64(x); - } - -#elif defined(__FreeBSD__) || defined(__MACOSX__) || defined(__APPLE__) - #include <libkern/OSByteOrder.h> - - UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){ - return OSSwapInt16(x); - } - - UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){ - return OSSwapInt32(x); - } - - UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){ - return OSSwapInt64(x); - } - -#elif defined(linux) || defined(__linux) - #include <byteswap.h> - - UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){ - return bswap_16(x); - } - - UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){ - return bswap_32(x); - } - - UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){ - return bswap_64(x); - } - -#else //http://www.koders.com/c/fidB93B34CD44F0ECF724F1A4EAE3854BA2FE692F59.aspx - - UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){ - return (x>>8) | (x<<8); - } - - UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){ - return (boost::uint32_t(uhd::byteswap(boost::uint16_t(x&0xfffful)))<<16) | (uhd::byteswap(boost::uint16_t(x>>16))); - } - - UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){ - return (boost::uint64_t(uhd::byteswap(boost::uint32_t(x&0xffffffffull)))<<32) | (uhd::byteswap(boost::uint32_t(x>>32))); - } - -#endif - -/*********************************************************************** - * Define the templated network to/from host conversions - **********************************************************************/ -#include <boost/detail/endian.hpp> - -template<typename T> UHD_INLINE T uhd::ntohx(T num){ - #ifdef BOOST_BIG_ENDIAN - return num; - #else - return uhd::byteswap(num); - #endif -} - -template<typename T> UHD_INLINE T uhd::htonx(T num){ - #ifdef BOOST_BIG_ENDIAN - return num; - #else - return uhd::byteswap(num); - #endif -} +#include <uhd/utils/byteswap.ipp> #endif /* INCLUDED_UHD_UTILS_BYTESWAP_HPP */ diff --git a/host/include/uhd/utils/byteswap.ipp b/host/include/uhd/utils/byteswap.ipp new file mode 100644 index 000000000..11c82a4ec --- /dev/null +++ b/host/include/uhd/utils/byteswap.ipp @@ -0,0 +1,120 @@ +// +// 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 <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_UTILS_BYTESWAP_IPP +#define INCLUDED_UHD_UTILS_BYTESWAP_IPP + +/*********************************************************************** + * Platform-specific implementation details for byteswap below: + **********************************************************************/ +#ifdef BOOST_MSVC //http://msdn.microsoft.com/en-us/library/a3140177%28VS.80%29.aspx + #include <stdlib.h> + + UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){ + return _byteswap_ushort(x); + } + + UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){ + return _byteswap_ulong(x); + } + + UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){ + return _byteswap_uint64(x); + } + +#elif defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 2 + + UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){ + return (x>>8) | (x<<8); //DNE return __builtin_bswap16(x); + } + + UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){ + return __builtin_bswap32(x); + } + + UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){ + return __builtin_bswap64(x); + } + +#elif defined(__FreeBSD__) || defined(__MACOSX__) || defined(__APPLE__) + #include <libkern/OSByteOrder.h> + + UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){ + return OSSwapInt16(x); + } + + UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){ + return OSSwapInt32(x); + } + + UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){ + return OSSwapInt64(x); + } + +#elif defined(linux) || defined(__linux) + #include <byteswap.h> + + UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){ + return bswap_16(x); + } + + UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){ + return bswap_32(x); + } + + UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){ + return bswap_64(x); + } + +#else //http://www.koders.com/c/fidB93B34CD44F0ECF724F1A4EAE3854BA2FE692F59.aspx + + UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){ + return (x>>8) | (x<<8); + } + + UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){ + return (boost::uint32_t(uhd::byteswap(boost::uint16_t(x&0xfffful)))<<16) | (uhd::byteswap(boost::uint16_t(x>>16))); + } + + UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){ + return (boost::uint64_t(uhd::byteswap(boost::uint32_t(x&0xffffffffull)))<<32) | (uhd::byteswap(boost::uint32_t(x>>32))); + } + +#endif + +/*********************************************************************** + * Define the templated network to/from host conversions + **********************************************************************/ +#include <boost/detail/endian.hpp> + +template<typename T> UHD_INLINE T uhd::ntohx(T num){ + #ifdef BOOST_BIG_ENDIAN + return num; + #else + return uhd::byteswap(num); + #endif +} + +template<typename T> UHD_INLINE T uhd::htonx(T num){ + #ifdef BOOST_BIG_ENDIAN + return num; + #else + return uhd::byteswap(num); + #endif +} + +#endif /* INCLUDED_UHD_UTILS_BYTESWAP_IPP */ |