diff options
| -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 */ | 
