FlashGraph-ng
A new frontier in large-scale graph analysis and data mining
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
concurrency.h
1 #ifndef __CONCURRENCY_H__
2 #define __CONCURRENCY_H__
3 
4 /*
5  * Copyright 2014 Open Connectome Project (http://openconnecto.me)
6  * Written by Da Zheng (zhengda1936@gmail.com)
7  *
8  * This file is part of SAFSlib.
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  */
22 
23 #include <pthread.h>
24 #include <numa.h>
25 
26 template<class T>
27 class atomic_number
28 {
29  volatile T v;
30 public:
31  atomic_number() {
32  v = 0;
33  }
34 
35  atomic_number(T init) {
36  v = init;
37  }
38 
39  T inc(T by) {
40  return __sync_add_and_fetch(&v, by);
41  }
42 
43  T dec(T by) {
44  return __sync_sub_and_fetch(&v, by);
45  }
46 
47  T get() const {
48  return v;
49  }
50 
51  bool CAS(T expected, T value) {
52  return __sync_bool_compare_and_swap(&v, expected, value);
53  }
54 };
55 
56 class atomic_unsigned_integer: public atomic_number<unsigned int>
57 {
58 public:
59  atomic_unsigned_integer() {
60  }
61 
62  atomic_unsigned_integer(unsigned int init): atomic_number<unsigned int>(
63  init) {
64  }
65 };
66 
67 class atomic_integer: public atomic_number<int>
68 {
69 public:
70  atomic_integer() {
71  }
72 
73  atomic_integer(int init): atomic_number<int>(init) {
74  }
75 };
76 
77 class atomic_long: public atomic_number<long>
78 {
79 public:
80  atomic_long() {
81  }
82 
83  atomic_long(long init): atomic_number<long>(init) {
84  }
85 };
86 
87 template<class T>
88 class atomic_array
89 {
90  volatile T *arr;
91  int size;
92 public:
93  atomic_array(int size) {
94  this->size = size;
95  arr = (T *) numa_alloc_local(sizeof(T) * size);
96  memset((void *) arr, 0, sizeof(T) * size);
97  }
98 
99  ~atomic_array() {
100  numa_free((void *) arr, sizeof(T) * size);
101  }
102 
103  T get(int idx) const {
104  return arr[idx];
105  }
106 
107  bool CAS(int idx, T expected, T value) {
108  return __sync_bool_compare_and_swap(&arr[idx], expected, value);
109  }
110 };
111 
112 class seq_lock
113 {
114  volatile unsigned long count;
115  pthread_spinlock_t lock;
116 public:
117  seq_lock() {
118  count = 0;
119  pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE);
120  }
121 
122  ~seq_lock() {
123  pthread_spin_destroy(&lock);
124  }
125 
126  void read_lock(unsigned long &count) const {
127  /*
128  * If the count is odd, it means another thread is changing
129  * the data structure the lock tries to protect.
130  */
131  do {
132  count = this->count;
133  } while (count & 1);
134  }
135 
136  bool read_unlock(unsigned long count) const {
137  return this->count == count;
138  }
139 
140  void write_lock() {
141  pthread_spin_lock(&lock);
142  __sync_fetch_and_add(&count, 1);
143  }
144 
145  void write_unlock() {
146  __sync_fetch_and_add(&count, 1);
147  pthread_spin_unlock(&lock);
148  }
149 };
150 
151 template<class T>
152 class atomic_flags
153 {
154  volatile T flags;
155 public:
156  atomic_flags() {
157  flags = 0;
158  }
159 
160  /*
161  * Set the flag and return the orig flag.
162  */
163  bool set_flag(int flag) {
164  int orig = __sync_fetch_and_or(&flags, 0x1 << flag);
165  return orig & (0x1 << flag);
166  }
167 
168  /*
169  * Clear the flag and return the orig flag.
170  */
171  bool clear_flag(int flag) {
172  int orig = __sync_fetch_and_and(&flags, ~(0x1 << flag));
173  return orig & (0x1 << flag);
174  }
175 
176  bool test_flag(int flag) const {
177  return flags & (0x1 << flag);
178  }
179 
180  int get_num_tot_flags() const {
181  return sizeof(T) * 8;
182  }
183 };
184 
185 class spin_lock
186 {
187  pthread_spinlock_t _lock;
188 public:
189  spin_lock() {
190  pthread_spin_init(&_lock, PTHREAD_PROCESS_PRIVATE);
191  }
192 
193  void lock() {
194  pthread_spin_lock(&_lock);
195  }
196 
197  void unlock() {
198  pthread_spin_unlock(&_lock);
199  }
200 };
201 
202 #endif