-
Notifications
You must be signed in to change notification settings - Fork 2
/
list.hpp
127 lines (120 loc) · 2.57 KB
/
list.hpp
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
#ifndef LOCKFREE_LIST_H_
#define LOCKFREE_LIST_H_
#include "atomics.h"
#include <stdio.h>
#include <assert.h>
namespace lockfree{
template<typename T>
class list{
/* requirement
T()
T(const T&)
bool operator<
bool operator==
*/
private:// typedef
class node{
public:
const T item;
markable_ptr<node> next; // it contains deletion mark in &1
public:
node(const T& t):item(t),next(NULL){ }
node(const T& t,markable_ptr<node> n):item(t),next(n){ }
node():item(),next(NULL){ }// sentinel node
};
typedef markable_ptr<node> mptr;
public:// variants
node mHead;
public:// public methods
list():mHead(){}
bool insert(const T& t){
while(1){
mptr pred,curr;
find(t, &mHead, &pred, &curr);
if(curr.get() == NULL || curr->item != t){
node* newnode = new node(t,curr);
if(compare_and_set(&pred->next, curr.get(), newnode)){
return true;
}else{
continue;
}
}else{
return false; // already exists
}
}
}
bool erase(const T& t){
while(1){
mptr pred,curr;
find(t, &mHead, &pred, &curr);
if(curr.get() == NULL){ return false;} // no item
if(curr->item == t){
mptr succ = curr->next;
if(curr->next.attempt_mark()){
compare_and_set(&pred->next, curr.get(), succ.get()); // although it failed, no problem
return true;
}else{
continue; // curr is changed, retry.
}
}else{
return false; // no item
}
}
}
bool contains(const T& t)const{
mptr ptr = mHead.next;
while(ptr != NULL){
if(ptr->item < t){
ptr = ptr->next;
continue;}
else{break;}
}
if(ptr.get() == NULL){return false;}
if(ptr->item == t){
if(ptr->next.is_marked()){ // marked object is invalid
return false;
}else{
return true;
}
}else {return false;}
}
void dump(void)const{
mptr ptr = mHead.next;
while(ptr != NULL){
printf("%d,",ptr->item);
ptr = ptr->next;
}
}
private:
void find(const T& t, node* head, mptr* pred, mptr* curr){
while(1){
*pred = head;
*curr = (*pred)->next;
if(*pred != head) continue;
while(1){
if(curr->get() == NULL){return;}
mptr succ = (*curr)->next;
if(curr->is_marked()){ // check deleting mark
if(compare_and_set(&(*pred)->next, curr->get(), succ.get())){
*curr = succ;
continue;
}else{ // pred is modified, back to head
break;
}
}else{
if((*curr)->item < t){ // iterate
*pred = *curr;
*curr = succ;
}else{
return;
}
}
}
}
}
private:// forbidden methods
list(const list&);
list& operator=(const list&);
};
}// namespace lockfree
#endif