UHD
003.005.000-54-stable
|
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 00089 void interrupt(void) 00090 { 00091 _count.write(boost::uint32_t(~0)); 00092 } 00093 00095 UHD_INLINE void wait(void){ 00096 _count.dec(); 00097 _count.cas(_size, 0); 00098 while (_count.read() != _size){ 00099 boost::this_thread::interruption_point(); 00100 if (_count.read() == boost::uint32_t(~0)) 00101 throw boost::thread_interrupted(); 00102 boost::this_thread::yield(); 00103 } 00104 } 00105 00106 private: 00107 size_t _size; 00108 atomic_uint32_t _count; 00109 }; 00110 00118 UHD_INLINE bool spin_wait_with_timeout( 00119 atomic_uint32_t &cond, 00120 boost::uint32_t value, 00121 const double timeout 00122 ){ 00123 if (cond.read() == value) return true; 00124 const time_spec_t exit_time = time_spec_t::get_system_time() + time_spec_t(timeout); 00125 while (cond.read() != value){ 00126 if (time_spec_t::get_system_time() > exit_time) return false; 00127 boost::this_thread::interruption_point(); 00128 boost::this_thread::yield(); 00129 } 00130 return true; 00131 } 00132 00137 class simple_claimer{ 00138 public: 00139 simple_claimer(void){ 00140 this->release(); 00141 } 00142 00143 UHD_INLINE void release(void){ 00144 _locked.write(0); 00145 } 00146 00147 UHD_INLINE bool claim_with_wait(const double timeout){ 00148 if (spin_wait_with_timeout(_locked, 0, timeout)){ 00149 _locked.write(1); 00150 return true; 00151 } 00152 return false; 00153 } 00154 00155 private: 00156 atomic_uint32_t _locked; 00157 }; 00158 00159 } //namespace uhd 00160 00161 #endif /* INCLUDED_UHD_UTILS_ATOMIC_HPP */