UHD  003.005.000-62-stable
include/uhd/utils/atomic.hpp
Go to the documentation of this file.
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 */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines