summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/include/uhd/transport/CMakeLists.txt2
-rw-r--r--host/include/uhd/transport/alignment_buffer.hpp104
-rw-r--r--host/include/uhd/transport/alignment_buffer.ipp140
-rw-r--r--host/include/uhd/transport/bounded_buffer.hpp86
-rw-r--r--host/include/uhd/transport/bounded_buffer.ipp112
-rw-r--r--host/include/uhd/utils/CMakeLists.txt1
-rw-r--r--host/include/uhd/utils/byteswap.hpp99
-rw-r--r--host/include/uhd/utils/byteswap.ipp120
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 */