-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHashSetGCC_RTM.h
134 lines (123 loc) · 3.77 KB
/
HashSetGCC_RTM.h
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//
// Created by mguzek on 6/3/20.
//
#ifndef HASHSETHTM_HASHSETGCC_RTM_H
#define HASHSETHTM_HASHSETGCC_RTM_H
//Compile with -mrtm under g++ to work
#include <immintrin.h> //present under g++
#include <thread>
#include <chrono>
#include <random>
#include "HashSet.h"
class HashSetGCC_RTM : public HashSet {
protected:
void resize() override {
size_t status;
for(int i = 0 ; i < RTM_ATTEMPTS ; ++i)
{
status = _xbegin();
if (status == _XBEGIN_STARTED) {
if (!(rmutex.isLocked())) {
HashSet::resize();
_xend();
return;
}
_xabort(0xFF);
}
if((status & _XABORT_EXPLICIT) && _XABORT_CODE(status) == 0xff) {
std::this_thread::sleep_for(std::chrono::nanoseconds(dist(rng)));
}
else if(!(status & _XABORT_RETRY)) {
break;
}
}
rmutex.lock();
HashSet::resize();
rmutex.unlock();
}
std::mt19937 rng;
std::uniform_int_distribution<std::mt19937::result_type> dist;
static constexpr size_t RTM_ATTEMPTS = 3;
public:
explicit HashSetGCC_RTM(size_t initCapacity = 11) : HashSet{initCapacity}, rng{std::random_device{}()}, dist(1, 50) {
}
bool add(int item) override {
bool result;
size_t status;
for(int i = 0 ; i < RTM_ATTEMPTS ; ++i)
{
status = _xbegin();
if (status == _XBEGIN_STARTED) {
if (!(rmutex.isLocked())) {
result = HashSet::add(item);
_xend();
return result;
}
_xabort(0xFF);
}
if((status & _XABORT_EXPLICIT) && _XABORT_CODE(status) == 0xff) {
std::this_thread::sleep_for(std::chrono::nanoseconds(dist(rng)));
}
else if(!(status & _XABORT_RETRY)) {
break;
}
}
rmutex.lock();
result = HashSet::add(item);
rmutex.unlock();
return result;
}
bool remove(int item) override {
bool result;
size_t status;
for(int i = 0 ; i < RTM_ATTEMPTS ; ++i)
{
status = _xbegin();
if (status == _XBEGIN_STARTED) {
if (!(rmutex.isLocked())) {
result = HashSet::remove(item);
_xend();
return result;
}
_xabort(0xFF);
}
if((status & _XABORT_EXPLICIT) && _XABORT_CODE(status) == 0xff) {
std::this_thread::sleep_for(std::chrono::nanoseconds(dist(rng)));
}
else if(!(status & _XABORT_RETRY)) {
break;
}
}
rmutex.lock();
result = HashSet::remove(item);
rmutex.unlock();
return result;
}
bool contains(int item) override {
bool result;
size_t status;
for(int i = 0 ; i < RTM_ATTEMPTS ; ++i)
{
status = _xbegin();
if (status == _XBEGIN_STARTED) {
if (!(rmutex.isLocked())) {
result = HashSet::contains(item);
_xend();
return result;
}
_xabort(0xFF);
}
if((status & _XABORT_EXPLICIT) && _XABORT_CODE(status) == 0xff) {
std::this_thread::sleep_for(std::chrono::nanoseconds(dist(rng)));
}
else if(!(status & _XABORT_RETRY)) {
break;
}
}
rmutex.lock();
result = HashSet::contains(item);
rmutex.unlock();
return result;
}
};
#endif //HASHSETHTM_HASHSETGCC_RTM_H