GraphLab: Distributed Graph-Parallel API  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
inplace_lf_queue.hpp
1 #ifndef GRAPHLAB_INPLACE_LOCKFREE_QUEUE_HPP
2 #define GRAPHLAB_INPLACE_LOCKFREE_QUEUE_HPP
3 #include <stdint.h>
4 #include <cstring>
5 #include <graphlab/parallel/atomic.hpp>
6 #include <graphlab/parallel/atomic_ops.hpp>
7 #include <utility>
8 namespace graphlab {
9 
10 /*
11  * A lock free queue where each element is a byte sequence,
12  * where the first 8 bytes can be used for a next pointer.
13  *
14  * head is the head of the queue. Always sentinel.
15  * tail is current last element of the queue.
16  * completed is the last element that is completely inserted.
17  * There can only be one thread dequeueing.
18  *
19  * On dequeue_all, the dequeu-er should use get_next() to get the
20  * next element in the list. If get_next() returns NULL, it should spin
21  * until not null, and quit only when end_of_dequeue_list() evaluates to true
22  */
23 class inplace_lf_queue {
24  public:
25  inline inplace_lf_queue():head(sentinel),tail(sentinel) {
26  for (size_t i = 0;i < sizeof(size_t); ++i) sentinel[i] = 0;
27  }
28 
29  void enqueue(char* c);
30 
31  char* dequeue_all();
32 
33  static inline char* get_next(char* ptr) {
34  return *(reinterpret_cast<char**>(ptr));
35  }
36 
37  static inline char** get_next_ptr(char* ptr) {
38  return reinterpret_cast<char**>(ptr);
39  }
40 
41  inline const bool end_of_dequeue_list(char* ptr) {
42  return ptr == sentinel;
43  }
44 
45  private:
46 
47  char sentinel[sizeof(size_t)];
48  char* head;
49  char* tail;
50 };
51 
52 
53 } // namespace graphlab
54 
55 #endif