-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgc.hpp
95 lines (72 loc) · 1.79 KB
/
gc.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
#ifndef SLIP_GC_HPP
#define SLIP_GC_HPP
// #include <iostream>
#include <utility>
template<class Tag>
class gc {
struct block {
virtual ~block() { }
union {
block* ptr;
std::size_t bits;
} next;
block() {
next.ptr = first;
first = this;
}
// gc mark in lower order bits
void set_mark(bool value) {
if(value) next.bits |= 1ul;
else next.bits &= ~1ul;
}
bool get_mark() const {
return next.bits & 1ul;
}
};
template<class T>
struct managed : block {
T value;
template<class ... Args>
managed(Args&& ... args): value(std::forward<Args>(args)...) { }
};
static block* first;
public:
template<class T>
class ref {
using ptr_type = managed<T>*;
ptr_type ptr;
friend class gc;
ref(ptr_type ptr): ptr(ptr) { }
public:
ref(): ptr(nullptr) { };
explicit operator bool() const { return ptr; }
T* get() const { return &ptr->value; }
T& operator*() const { return ptr->value; }
T* operator->() const { return get();}
inline void mark() { ptr->set_mark(true); }
inline bool marked() const { return ptr->get_mark(); }
friend std::ostream& operator<<(std::ostream& out, const ref& self) {
return out << self.get();
}
};
template<class T, class ... Args>
static ref<T> make_ref(Args&& ... args) {
return {new managed<T>(std::forward<Args>(args)...)};
}
static void sweep() {
block** it = &first;
while(*it) {
if(!(*it)->get_mark()) {
block* obj = *it;
*it = (*it)->next.ptr;
delete obj;
} else {
(*it)->set_mark(false);
it = &(*it)->next.ptr;
}
}
}
};
template<class Tag>
typename gc<Tag>::block* gc<Tag>::first = nullptr;
#endif