-
Notifications
You must be signed in to change notification settings - Fork 0
/
intrusive_stack.h
123 lines (106 loc) · 2.94 KB
/
intrusive_stack.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
// Copyright © 2016 zendo (734181759@qq.com). All rights reserved.
#pragma once
#include "intrusive_hook.h"
namespace zendo
{
template<typename T, bool CacheSize, int Tag = 0>
class intrusive_stack;
template<typename T, int Tag>
class intrusive_stack<T, false, Tag> : protected detail::hook_access
{
public:
using hook_type = forward_hook<Tag>;
using hook_ptr = hook_type*;
using value_type = T;
using value_ptr = value_type*;
static_assert(std::is_base_of<hook_type, T>::value, "");
private:
hook_ptr top_{nullptr};
public:
intrusive_stack() = default;
intrusive_stack(const intrusive_stack&) = delete;
intrusive_stack(intrusive_stack&& rhs)
: top_(rhs.top_)
{
rhs.top_ = nullptr;
}
void swap(intrusive_stack& lhs)
{
const hook_ptr top_one = top_;
top_ = lhs.top_;
lhs.top_ = top_one;
}
bool empty() const
{
return top_ == nullptr;
}
void push(hook_ptr element)
{
if(element && (next(element) == nullptr))
{
next(element) = top_;
top_ = element;
}
}
value_ptr pop()
{
hook_ptr ret = top_;
if(top_)
{
top_ = next(top_);
}
return static_cast<value_type*>(ret);
}
};
template<typename T, int Tag>
class intrusive_stack<T, true, Tag> : protected detail::hook_access
{
public:
using hook_type = forward_hook<Tag>;
using hook_ptr = hook_type*;
using value_type = T;
using value_ptr = value_type*;
static_assert(std::is_base_of<hook_type, T>::value, "");
private:
hook_ptr top_{nullptr};
size_t size_{0};
public:
intrusive_stack() = default;
intrusive_stack(const intrusive_stack&) = delete;
intrusive_stack(intrusive_stack&& rhs)
: top_(rhs.top_)
, size_(rhs.size_)
{
rhs.top_ = nullptr;
rhs.size_ = 0;
}
void swap(intrusive_stack& lhs)
{
std::swap(top_, lhs.top_);
std::swap(size_, lhs.size_);
}
bool empty() const
{
return top_ == nullptr;
}
void push(hook_ptr element)
{
if(element && (next(element) == nullptr))
{
next(element) = top_;
top_ = element;
++size_;
}
}
value_ptr pop()
{
hook_ptr ret = top_;
if(top_)
{
top_ = next(top_);
--size_;
}
return static_cast<value_type*>(ret);
}
};
}