USRP Hardware Driver and USRP Manual  Version: 003.008.003-0-g6eacba0a
UHD and USRP Manual
atomic.hpp
Go to the documentation of this file.
1 //
2 // Copyright 2012-2013 Ettus Research LLC
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 //
17 
18 #ifndef INCLUDED_UHD_UTILS_ATOMIC_HPP
19 #define INCLUDED_UHD_UTILS_ATOMIC_HPP
20 
21 #include <uhd/config.hpp>
22 #include <uhd/types/time_spec.hpp>
23 #include <boost/thread/thread.hpp>
24 #include <boost/thread/mutex.hpp>
25 #include <boost/thread/condition_variable.hpp>
26 #include <boost/interprocess/detail/atomic.hpp>
27 
28 #include <boost/version.hpp>
29 #if BOOST_VERSION >= 104800
30 # define BOOST_IPC_DETAIL boost::interprocess::ipcdetail
31 #else
32 # define BOOST_IPC_DETAIL boost::interprocess::detail
33 #endif
34 
35 namespace uhd{
36 
39  public:
40 
43  this->write(0);
44  }
45 
47  UHD_INLINE boost::uint32_t cas(boost::uint32_t newval, boost::uint32_t cmp){
48  return BOOST_IPC_DETAIL::atomic_cas32(&_num, newval, cmp);
49  }
50 
52  UHD_INLINE void write(const boost::uint32_t newval){
53  BOOST_IPC_DETAIL::atomic_write32(&_num, newval);
54  }
55 
57  UHD_INLINE boost::uint32_t read(void){
58  return BOOST_IPC_DETAIL::atomic_read32(&_num);
59  }
60 
62  UHD_INLINE boost::uint32_t inc(void){
63  return BOOST_IPC_DETAIL::atomic_inc32(&_num);
64  }
65 
67  UHD_INLINE boost::uint32_t dec(void){
68  return BOOST_IPC_DETAIL::atomic_dec32(&_num);
69  }
70 
71  private: volatile boost::uint32_t _num;
72  };
73 
79  public:
80 
81  reusable_barrier():_size (0) {}
82 
83  reusable_barrier(const size_t size):_size(size) {}
84 
86  void resize(const size_t size){
87  _size = size;
88  }
89 
94  void interrupt(void)
95  {
96  _done.inc();
97  }
98 
100  UHD_INLINE void wait(void)
101  {
102  if (_size == 1) return;
103 
104  //entry barrier with condition variable
105  _entry_counter.inc();
106  _entry_counter.cas(0, _size);
107  boost::mutex::scoped_lock lock(_mutex);
108  while (_entry_counter.read() != 0)
109  {
110  this->check_interrupt();
111  _cond.timed_wait(lock, boost::posix_time::milliseconds(1));
112  }
113  lock.unlock(); //unlock before notify
114  _cond.notify_one();
115 
116  //exit barrier to ensure known condition of entry count
117  _exit_counter.inc();
118  _exit_counter.cas(0, _size);
119  while (_exit_counter.read() != 0) this->check_interrupt();
120  }
121 
124  {
125  while (_entry_counter.read() != (_size-1)) this->check_interrupt();
126  }
127 
128  private:
129  size_t _size;
130  atomic_uint32_t _entry_counter;
131  atomic_uint32_t _exit_counter;
132  atomic_uint32_t _done;
133  boost::mutex _mutex;
134  boost::condition_variable _cond;
135 
136  UHD_INLINE void check_interrupt(void)
137  {
138  if (_done.read() != 0) throw boost::thread_interrupted();
139  boost::this_thread::interruption_point();
140  boost::this_thread::yield();
141  }
142  };
143 
152  atomic_uint32_t &cond,
153  boost::uint32_t value,
154  const double timeout
155  ){
156  if (cond.read() == value) return true;
157  const time_spec_t exit_time = time_spec_t::get_system_time() + time_spec_t(timeout);
158  while (cond.read() != value){
159  if (time_spec_t::get_system_time() > exit_time) return false;
160  boost::this_thread::interruption_point();
161  boost::this_thread::yield();
162  }
163  return true;
164  }
165 
171  public:
173  this->release();
174  }
175 
176  UHD_INLINE void release(void){
177  _locked.write(0);
178  }
179 
180  UHD_INLINE bool claim_with_wait(const double timeout){
181  if (spin_wait_with_timeout(_locked, 0, timeout)){
182  _locked.write(1);
183  return true;
184  }
185  return false;
186  }
187 
188  private:
189  atomic_uint32_t _locked;
190  };
191 
192 } //namespace uhd
193 
194 #endif /* INCLUDED_UHD_UTILS_ATOMIC_HPP */
UHD_INLINE boost::uint32_t read(void)
Gets the current value of the atomic integer.
Definition: atomic.hpp:57
UHD_INLINE void wait(void)
Wait on the barrier condition.
Definition: atomic.hpp:100
UHD_INLINE void release(void)
Definition: atomic.hpp:176
Definition: atomic.hpp:78
Definition: time_spec.hpp:39
A 32-bit integer that can be atomically accessed.
Definition: atomic.hpp:38
UHD_INLINE void wait_others(void)
Wait on the barrier condition.
Definition: atomic.hpp:123
UHD_INLINE bool spin_wait_with_timeout(atomic_uint32_t &cond, boost::uint32_t value, const double timeout)
Definition: atomic.hpp:151
static time_spec_t get_system_time(void)
#define UHD_API
Definition: config.hpp:79
Definition: convert.hpp:28
UHD_INLINE boost::uint32_t cas(boost::uint32_t newval, boost::uint32_t cmp)
Compare with cmp, swap with newval if same, return old value.
Definition: atomic.hpp:47
UHD_INLINE bool claim_with_wait(const double timeout)
Definition: atomic.hpp:180
#define UHD_INLINE
Definition: config.hpp:69
UHD_INLINE atomic_uint32_t(void)
Create a new atomic 32-bit integer, initialized to zero.
Definition: atomic.hpp:42
UHD_INLINE void write(const boost::uint32_t newval)
Sets the atomic integer to a new value.
Definition: atomic.hpp:52
UHD_INLINE boost::uint32_t inc(void)
Increment by 1 and return the old value.
Definition: atomic.hpp:62
simple_claimer(void)
Definition: atomic.hpp:172
UHD_INLINE boost::uint32_t dec(void)
Decrement by 1 and return the old value.
Definition: atomic.hpp:67
void resize(const size_t size)
Resize the barrier for N threads.
Definition: atomic.hpp:86
reusable_barrier(const size_t size)
Definition: atomic.hpp:83
Definition: atomic.hpp:170
reusable_barrier()
Definition: atomic.hpp:81
void interrupt(void)
Definition: atomic.hpp:94