UHD
003.005.000-release
|
00001 // 00002 // Copyright 2012 Ettus Research LLC 00003 // 00004 // This program is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with this program. If not, see <http://www.gnu.org/licenses/>. 00016 // 00017 00018 #ifndef INCLUDED_UHD_UTILS_ATOMIC_HPP 00019 #define INCLUDED_UHD_UTILS_ATOMIC_HPP 00020 00021 #include <uhd/config.hpp> 00022 #include <uhd/types/time_spec.hpp> 00023 #include <boost/thread/thread.hpp> 00024 #include <boost/interprocess/detail/atomic.hpp> 00025 00026 #include <boost/version.hpp> 00027 #if BOOST_VERSION >= 104800 00028 # define BOOST_IPC_DETAIL boost::interprocess::ipcdetail 00029 #else 00030 # define BOOST_IPC_DETAIL boost::interprocess::detail 00031 #endif 00032 00033 namespace uhd{ 00034 00036 class UHD_API atomic_uint32_t{ 00037 public: 00038 00040 UHD_INLINE atomic_uint32_t(void){ 00041 this->write(0); 00042 } 00043 00045 UHD_INLINE boost::uint32_t cas(boost::uint32_t newval, boost::uint32_t cmp){ 00046 return BOOST_IPC_DETAIL::atomic_cas32(&_num, newval, cmp); 00047 } 00048 00050 UHD_INLINE void write(const boost::uint32_t newval){ 00051 BOOST_IPC_DETAIL::atomic_write32(&_num, newval); 00052 } 00053 00055 UHD_INLINE boost::uint32_t read(void){ 00056 return BOOST_IPC_DETAIL::atomic_read32(&_num); 00057 } 00058 00060 UHD_INLINE boost::uint32_t inc(void){ 00061 return BOOST_IPC_DETAIL::atomic_inc32(&_num); 00062 } 00063 00065 UHD_INLINE boost::uint32_t dec(void){ 00066 return BOOST_IPC_DETAIL::atomic_dec32(&_num); 00067 } 00068 00069 private: volatile boost::uint32_t _num; 00070 }; 00071 00076 class UHD_API reusable_barrier{ 00077 public: 00078 00080 void resize(const size_t size){ 00081 _size = size; 00082 _count.write(size); 00083 } 00084 00086 UHD_INLINE void wait(void){ 00087 _count.dec(); 00088 _count.cas(_size, 0); 00089 while (_count.read() != _size){ 00090 boost::this_thread::interruption_point(); 00091 boost::this_thread::yield(); 00092 } 00093 } 00094 00095 private: 00096 size_t _size; 00097 atomic_uint32_t _count; 00098 }; 00099 00107 UHD_INLINE bool spin_wait_with_timeout( 00108 atomic_uint32_t &cond, 00109 boost::uint32_t value, 00110 const double timeout 00111 ){ 00112 if (cond.read() == value) return true; 00113 const time_spec_t exit_time = time_spec_t::get_system_time() + time_spec_t(timeout); 00114 while (cond.read() != value){ 00115 if (time_spec_t::get_system_time() > exit_time) return false; 00116 boost::this_thread::interruption_point(); 00117 boost::this_thread::yield(); 00118 } 00119 return true; 00120 } 00121 00126 class simple_claimer{ 00127 public: 00128 simple_claimer(void){ 00129 this->release(); 00130 } 00131 00132 UHD_INLINE void release(void){ 00133 _locked.write(0); 00134 } 00135 00136 UHD_INLINE bool claim_with_wait(const double timeout){ 00137 if (spin_wait_with_timeout(_locked, 0, timeout)){ 00138 _locked.write(1); 00139 return true; 00140 } 00141 return false; 00142 } 00143 00144 private: 00145 atomic_uint32_t _locked; 00146 }; 00147 00148 } //namespace uhd 00149 00150 #endif /* INCLUDED_UHD_UTILS_ATOMIC_HPP */