35 #ifndef GRAPHLAB_ATOMIC_ADD_VECTOR_HPP
36 #define GRAPHLAB_ATOMIC_ADD_VECTOR_HPP
42 #include <graphlab/parallel/pthread_tools.hpp>
43 #include <graphlab/util/lock_free_pool.hpp>
53 template<
typename ValueType>
56 typedef ValueType value_type;
60 #define VALUE_PENDING (value_type*)(size_t)(-1)
63 lock_free_pool<value_type> pool;
64 atomic<size_t> joincounter;
66 class atomic_box_type {
68 value_type*
volatile value_ptr;
70 atomic_box_type() : value_ptr(NULL) { }
103 inline bool peek(lock_free_pool<value_type>& pool,
104 value_type& new_value,
105 atomic<size_t>& joincounter) {
109 value_type* vptr = VALUE_PENDING;
112 if (vptr == VALUE_PENDING) {
123 if (__unlikely__(vptr != NULL && vptr != VALUE_PENDING)) {
124 retval =
set(pool, (*vptr), new_value, joincounter);
133 inline bool set(lock_free_pool<value_type>& pool,
134 const value_type& other,
135 value_type& new_value,
136 atomic<size_t>& joincounter) {
138 value_type toinsert = other;
140 value_type* vptr = VALUE_PENDING;
149 }
else if (vptr == VALUE_PENDING) {
152 }
else { (*vptr) += toinsert; joincounter.inc(); }
154 ASSERT_TRUE(vptr != VALUE_PENDING);
159 if (__unlikely__(vptr != NULL && vptr != VALUE_PENDING)) {
166 void clear(lock_free_pool<value_type>& pool) {
170 bool empty() {
return value_ptr == NULL; }
172 inline bool test_and_get(lock_free_pool<value_type>& pool,
177 if (ret == NULL)
return false;
178 else if (__likely__(ret != VALUE_PENDING)) {
180 (value_type*)NULL))) {
197 typedef std::vector< atomic_box_type > atomic_box_vec_type;
198 atomic_box_vec_type atomic_box_vec;
208 pool(num_vertices + 256), atomic_box_vec(num_vertices) { }
214 atomic_box_vec.resize(num_vertices);
215 pool.reset_pool(num_vertices + 256);
220 bool add(
const size_t& idx,
221 const value_type& val) {
222 ASSERT_LT(idx, atomic_box_vec.size());
223 value_type new_value;
224 return atomic_box_vec[idx].set(pool, val, new_value, joincounter);
237 bool add(
const size_t& idx,
238 const value_type& val,
239 value_type& new_value) {
240 ASSERT_LT(idx, atomic_box_vec.size());
241 return atomic_box_vec[idx].set(pool, val, new_value, joincounter);
271 value_type& ret_val) {
272 ASSERT_LT(idx, atomic_box_vec.size());
273 return atomic_box_vec[idx].test_and_get(pool, ret_val);
276 bool peek(
const size_t& idx,
277 value_type& ret_val) {
278 ASSERT_LT(idx, atomic_box_vec.size());
279 return atomic_box_vec[idx].peek(pool, ret_val, joincounter);
282 bool empty(
const size_t& idx) {
283 return atomic_box_vec[idx].empty();
286 size_t size()
const {
287 return atomic_box_vec.size();
290 size_t num_joins()
const {
291 return joincounter.value;
296 for (
size_t i = 0; i < atomic_box_vec.size(); ++i) clear(i);
299 void clear(
size_t i) { atomic_box_vec[i].clear(pool); }