USRP Hardware Driver and USRP Manual  Version: 003.010.001.HEAD-0-gc705922a
UHD and USRP Manual
atomic.hpp
Go to the documentation of this file.
1 //
2 // Copyright 2012-2013,2016 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 #define BOOST_IPC_DETAIL boost::interprocess::ipcdetail
30 
31 namespace uhd{
32 
35  public:
36 
39  this->write(0);
40  }
41 
43  UHD_INLINE uint32_t cas(uint32_t newval, uint32_t cmp){
44  return BOOST_IPC_DETAIL::atomic_cas32(&_num, newval, cmp);
45  }
46 
48  UHD_INLINE void write(const uint32_t newval){
49  BOOST_IPC_DETAIL::atomic_write32(&_num, newval);
50  }
51 
53  UHD_INLINE uint32_t read(void){
54  return BOOST_IPC_DETAIL::atomic_read32(&_num);
55  }
56 
58  UHD_INLINE uint32_t inc(void){
59  return BOOST_IPC_DETAIL::atomic_inc32(&_num);
60  }
61 
63  UHD_INLINE uint32_t dec(void){
64  return BOOST_IPC_DETAIL::atomic_dec32(&_num);
65  }
66 
67  private: volatile uint32_t _num;
68  };
69 
75  public:
76 
77  reusable_barrier():_size (0) {}
78 
79  reusable_barrier(const size_t size):_size(size) {}
80 
82  void resize(const size_t size){
83  _size = size;
84  }
85 
90  void interrupt(void)
91  {
92  _done.inc();
93  }
94 
96  UHD_INLINE void wait(void)
97  {
98  if (_size == 1) return;
99 
100  //entry barrier with condition variable
101  _entry_counter.inc();
102  _entry_counter.cas(0, _size);
103  boost::mutex::scoped_lock lock(_mutex);
104  while (_entry_counter.read() != 0)
105  {
106  this->check_interrupt();
107  _cond.timed_wait(lock, boost::posix_time::milliseconds(1));
108  }
109  lock.unlock(); //unlock before notify
110  _cond.notify_one();
111 
112  //exit barrier to ensure known condition of entry count
113  _exit_counter.inc();
114  _exit_counter.cas(0, _size);
115  while (_exit_counter.read() != 0) this->check_interrupt();
116  }
117 
120  {
121  while (_entry_counter.read() != (_size-1)) this->check_interrupt();
122  }
123 
124  private:
125  size_t _size;
126  atomic_uint32_t _entry_counter;
127  atomic_uint32_t _exit_counter;
128  atomic_uint32_t _done;
129  boost::mutex _mutex;
130  boost::condition_variable _cond;
131 
132  UHD_INLINE void check_interrupt(void)
133  {
134  if (_done.read() != 0) throw boost::thread_interrupted();
135  boost::this_thread::interruption_point();
136  boost::this_thread::yield();
137  }
138  };
139 
148  atomic_uint32_t &cond,
149  uint32_t value,
150  const double timeout
151  ){
152  if (cond.read() == value) return true;
153  const time_spec_t exit_time = time_spec_t::get_system_time() + time_spec_t(timeout);
154  while (cond.read() != value){
155  if (time_spec_t::get_system_time() > exit_time) return false;
156  boost::this_thread::interruption_point();
157  boost::this_thread::yield();
158  }
159  return true;
160  }
161 
167  public:
169  this->release();
170  }
171 
172  UHD_INLINE void release(void){
173  _locked.write(0);
174  }
175 
176  UHD_INLINE bool claim_with_wait(const double timeout){
177  if (spin_wait_with_timeout(_locked, 0, timeout)){
178  _locked.write(1);
179  return true;
180  }
181  return false;
182  }
183 
184  private:
185  atomic_uint32_t _locked;
186  };
187 
188 } //namespace uhd
189 
190 #endif /* INCLUDED_UHD_UTILS_ATOMIC_HPP */
UHD_INLINE void wait(void)
Wait on the barrier condition.
Definition: atomic.hpp:96
UHD_INLINE void release(void)
Definition: atomic.hpp:172
UHD_INLINE uint32_t inc(void)
Increment by 1 and return the old value.
Definition: atomic.hpp:58
Definition: atomic.hpp:74
Definition: time_spec.hpp:39
A 32-bit integer that can be atomically accessed.
Definition: atomic.hpp:34
UHD_INLINE void wait_others(void)
Wait on the barrier condition.
Definition: atomic.hpp:119
static time_spec_t get_system_time(void)
Definition: build_info.hpp:25
UHD_INLINE bool claim_with_wait(const double timeout)
Definition: atomic.hpp:176
UHD_INLINE atomic_uint32_t(void)
Create a new atomic 32-bit integer, initialized to zero.
Definition: atomic.hpp:38
UHD_INLINE uint32_t cas(uint32_t newval, uint32_t cmp)
Compare with cmp, swap with newval if same, return old value.
Definition: atomic.hpp:43
simple_claimer(void)
Definition: atomic.hpp:168
#define UHD_INLINE
Definition: config.h:63
UHD_INLINE bool spin_wait_with_timeout(atomic_uint32_t &cond, uint32_t value, const double timeout)
Definition: atomic.hpp:147
UHD_INLINE uint32_t read(void)
Gets the current value of the atomic integer.
Definition: atomic.hpp:53
void resize(const size_t size)
Resize the barrier for N threads.
Definition: atomic.hpp:82
#define UHD_API
Definition: config.h:73
reusable_barrier(const size_t size)
Definition: atomic.hpp:79
UHD_INLINE uint32_t dec(void)
Decrement by 1 and return the old value.
Definition: atomic.hpp:63
Definition: atomic.hpp:166
reusable_barrier()
Definition: atomic.hpp:77
UHD_INLINE void write(const uint32_t newval)
Sets the atomic integer to a new value.
Definition: atomic.hpp:48
void interrupt(void)
Definition: atomic.hpp:90