-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathutils.h
More file actions
106 lines (95 loc) · 2.77 KB
/
utils.h
File metadata and controls
106 lines (95 loc) · 2.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#pragma once
#include <climits>
#include <cstring>
#include <iostream>
#include "parlay/utilities.h"
using namespace std;
constexpr size_t BLOCK_SIZE = 1024;
template <typename ET>
inline bool atomic_compare_and_swap(ET *a, ET oldval, ET newval) {
static_assert(sizeof(ET) <= 8, "Bad CAS length");
if (sizeof(ET) == 1) {
uint8_t r_oval, r_nval;
std::memcpy(&r_oval, &oldval, sizeof(ET));
std::memcpy(&r_nval, &newval, sizeof(ET));
return __sync_bool_compare_and_swap(reinterpret_cast<uint8_t *>(a), r_oval,
r_nval);
} else if (sizeof(ET) == 4) {
uint32_t r_oval, r_nval;
std::memcpy(&r_oval, &oldval, sizeof(ET));
std::memcpy(&r_nval, &newval, sizeof(ET));
return __sync_bool_compare_and_swap(reinterpret_cast<uint32_t *>(a), r_oval,
r_nval);
} else { // if (sizeof(ET) == 8) {
uint64_t r_oval, r_nval;
std::memcpy(&r_oval, &oldval, sizeof(ET));
std::memcpy(&r_nval, &newval, sizeof(ET));
return __sync_bool_compare_and_swap(reinterpret_cast<uint64_t *>(a), r_oval,
r_nval);
}
}
template <class ET>
inline bool compare_and_swap(std::atomic<ET> *a, ET oldval, ET newval) {
return a->load() == oldval &&
atomic_compare_exchange_weak(a, &oldval, newval);
}
template <class ET>
inline bool compare_and_swap(ET *a, ET oldval, ET newval) {
return (*a) == oldval && atomic_compare_and_swap(a, oldval, newval);
}
template <typename E, typename EV>
inline E fetch_and_add(E *a, EV b) {
volatile E newV, oldV;
do {
oldV = *a;
newV = oldV + b;
} while (!atomic_compare_and_swap(a, oldV, newV));
return oldV;
}
template <typename E, typename EV>
inline void write_add(E *a, EV b) {
// volatile E newV, oldV;
E newV, oldV;
do {
oldV = *a;
newV = oldV + b;
} while (!atomic_compare_and_swap(a, oldV, newV));
}
template <typename ET, typename F>
inline bool write_min(ET *a, ET b, F less) {
ET c;
bool r = 0;
do c = *a;
while (less(b, c) && !(r = atomic_compare_and_swap(a, c, b)));
return r;
}
template <typename ET, typename F>
inline bool write_max(ET *a, ET b, F less) {
ET c;
bool r = 0;
do c = *a;
while (less(c, b) && !(r = atomic_compare_and_swap(a, c, b)));
return r;
}
template <class ET>
inline ET _hash(ET a) {
if (sizeof(ET) == 4) {
return parlay::hash32(a);
} else if (sizeof(ET) == 8) {
return parlay::hash64(a);
} else {
std::cout << "hash bad length: " << sizeof(ET) << std::endl;
abort();
}
}
template <class ET>
inline ET _hash_2(ET a) {
if (sizeof(ET) == 4) {
return parlay::hash32_2(a);
} else if (sizeof(ET) == 8) {
return parlay::hash64_2(a);
} else {
std::cout << "hash bad length: " << sizeof(ET) << std::endl;
abort();
}
}