/
children.h
83 lines (70 loc) · 1.82 KB
/
children.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
#ifndef _CHILDREN_H_
#define _CHILDREN_H_
#include "thread.h"
template <class Node> class Children {
static const int LOCK = 1; //needs to be cast to (Node *) at usage point
uint32_t _num; //can be smaller, but will be padded anyway.
Node * _children;
public:
typedef Node * iterator;
Children() : _num(0), _children(NULL) { }
Children(int n) : _num(0), _children(NULL) { alloc(n); }
~Children() { assert_empty(); }
void assert_consistent() const { assert((_num == 0) || (_children > (Node *) LOCK)); }
void assert_empty() const { assert((_num == 0) && (_children == NULL)); }
bool lock() { return CAS(_children, (Node *) NULL, (Node *) LOCK); }
bool unlock() { return CAS(_children, (Node *) LOCK, (Node *) NULL); }
void atomic_set(Children & o){
assert(CAS(_children, (Node *) LOCK, o._children)); //undoes the lock
assert(CAS(_num, 0, o._num)); //keeps consistency
}
unsigned int alloc(unsigned int n){
assert(_num == 0);
assert(_children == NULL);
assert(n > 0);
_num = n;
_children = new Node[_num];
return _num;
}
void neuter(){
_children = 0;
_num = 0;
}
unsigned int dealloc(){
assert_consistent();
int n = _num;
if(_children){
Node * temp = _children; //CAS!
neuter();
delete[] temp;
}
return n;
}
void swap(Children & other){
Children temp = other;
other = *this;
*this = temp;
temp.neuter(); //to avoid problems with the destructor of temp
}
unsigned int num() const {
assert_consistent();
return _num;
}
bool empty() const {
return num() == 0;
}
Node & operator[](unsigned int offset){
assert(_children > (Node *) LOCK);
assert(offset >= 0 && offset < _num);
return _children[offset];
}
Node * begin() const {
assert_consistent();
return _children;
}
Node * end() const {
assert_consistent();
return _children + _num;
}
};
#endif