-
Notifications
You must be signed in to change notification settings - Fork 0
/
holder.cpp
68 lines (60 loc) · 1.87 KB
/
holder.cpp
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
#include "holder.hpp"
USING_MEMORY_ORDERS;
using std::make_pair;
intptr_t raw_holder::get(intptr_t* value) {
intptr_t version = contents_[0].load_1(memory_order_seq_cst);
for(int i=0;i<element_size_;i++) {
if (contents_[i].load_1(memory_order_seq_cst) != version)
return INVALID_VERSION;
value[i] = contents_[i].load_2(memory_order_seq_cst);
if (contents_[i].load_1(memory_order_seq_cst) != version)
return INVALID_VERSION;
}
return version;
}
void raw_holder::update(intptr_t version, const intptr_t* value) {
for(int i=0;i<element_size_;i++) {
intptr_t previous_version = contents_[i].load_1(memory_order_seq_cst);
if (previous_version >= version)
continue;
assert(previous_version == version - 1);
intptr_t previous_data = contents_[i].load_2(memory_order_seq_cst);
std::pair<intptr_t, intptr_t> previous(previous_version, previous_data);
contents_[i].compare_exchange_strong(previous, make_pair(version, value[i]), memory_order_seq_cst);
}
}
raw_holder::raw_holder(int element_size) :
element_size_(element_size),
contents_(new large_atomic<intptr_t, intptr_t>[element_size])
{
}
intptr_t raw_locked_holder::get(intptr_t* value) {
m_.lock($);
for(int i=0;i<element_size_;i++)
value[i] = VAR(contents_[i]);
intptr_t ver = VAR(version_);
m_.unlock($);
return ver;
}
void raw_locked_holder::update(intptr_t version, const intptr_t* value) {
m_.lock($);
if (VAR(version_) == version) {
for(int i=0;i<element_size_;i++)
assert(value[i] == VAR(contents_[i]));
}
if (VAR(version_) < version) {
assert(VAR(version_) == version - 1);
VAR(version_) = version;
for(int i=0;i<element_size_;i++)
VAR(contents_[i]) = value[i];
}
m_.unlock($);
}
raw_locked_holder::raw_locked_holder(int element_size) :
element_size_(element_size),
contents_(new VAR_T(intptr_t)[element_size]),
version_(0)
{
for(int i=0;i<element_size_;i++)
VAR(contents_[i]) = 0;
}