UHD  003.005.000-release
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 
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 */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines