24 #ifndef GRAPHLAB_PARALLEL_LOCKFREE_PUSHBACK_HPP
25 #define GRAPHLAB_PARALLEL_LOCKFREE_PUSHBACK_HPP
26 #include <graphlab/parallel/atomic.hpp>
30 namespace lockfree_push_back_impl {
32 idx_ref(): reference_count(0), idx(0) { }
33 idx_ref(
size_t idx): reference_count(0), idx(idx) { }
35 volatile int reference_count;
41 inline void inc_ref() {
43 int curref = reference_count;
44 if ((curref & MAX_REF) == 0 &&
51 inline void wait_till_no_ref() {
52 while((reference_count & (MAX_REF - 1)) != 0);
55 inline void dec_ref() {
56 __sync_fetch_and_sub(&reference_count, 1);
59 inline void flag_ref() {
60 __sync_fetch_and_xor(&reference_count, MAX_REF);
63 inline size_t inc_idx() {
64 return idx.inc_ret_last();
67 inline size_t inc_idx(
size_t n) {
68 return idx.inc_ret_last(n);
85 template <
typename Container,
typename T =
typename Container::value_type>
89 lockfree_push_back_impl::idx_ref cur;
94 container(container),cur(startidx), scalefactor(scalefactor) { }
100 void set_size(
size_t s) {
104 template <
typename Iterator>
105 size_t push_back(Iterator begin, Iterator end) {
106 size_t numel = std::distance(begin, end);
107 size_t putpos = cur.inc_idx(numel);
108 size_t endidx = putpos + numel;
111 if (endidx <= container.size()) {
112 while(putpos < endidx) {
113 container[putpos] = (*begin);
126 cur.wait_till_no_ref();
128 if (endidx > container.size()) {
129 container.resize(std::max<size_t>(endidx, container.size() * scalefactor));
131 while(putpos < endidx) {
132 container[putpos] = (*begin);
144 bool query(
size_t item, T& value) {
147 if (item < cur.idx) {
148 value = container[item];
155 T* query(
size_t item) {
158 if (item < cur.idx) {
159 ret = &(container[item]);
165 bool query_unsafe(
size_t item, T& value) {
167 if (item < cur.idx) {
168 value = container[item];
174 T* query_unsafe(
size_t item) {
176 if (item < cur.idx) {
177 ret = &(container[item]);
183 size_t push_back(
const T& t) {
184 size_t putpos = cur.inc_idx();
187 if (putpos < container.size()) {
188 container[putpos] = t;
199 cur.wait_till_no_ref();
201 if (putpos >= container.size()) {
202 container.resize(std::max<size_t>(putpos + 1, container.size() * scalefactor));
204 container[putpos] = t;