annotate libitm/aatree.cc @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1 /* Copyright (C) 2009-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
2 Contributed by Richard Henderson <rth@redhat.com>.
kono
parents:
diff changeset
3
kono
parents:
diff changeset
4 This file is part of the GNU Transactional Memory Library (libitm).
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 Libitm is free software; you can redistribute it and/or modify it
kono
parents:
diff changeset
7 under the terms of the GNU General Public License as published by
kono
parents:
diff changeset
8 the Free Software Foundation; either version 3 of the License, or
kono
parents:
diff changeset
9 (at your option) any later version.
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11 Libitm is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
kono
parents:
diff changeset
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for
kono
parents:
diff changeset
14 more details.
kono
parents:
diff changeset
15
kono
parents:
diff changeset
16 Under Section 7 of GPL version 3, you are granted additional
kono
parents:
diff changeset
17 permissions described in the GCC Runtime Library Exception, version
kono
parents:
diff changeset
18 3.1, as published by the Free Software Foundation.
kono
parents:
diff changeset
19
kono
parents:
diff changeset
20 You should have received a copy of the GNU General Public License and
kono
parents:
diff changeset
21 a copy of the GCC Runtime Library Exception along with this program;
kono
parents:
diff changeset
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
kono
parents:
diff changeset
23 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
24
kono
parents:
diff changeset
25 // Implements an AA tree (http://en.wikipedia.org/wiki/AA_tree) with an
kono
parents:
diff changeset
26 // integer key, and data attached to the node via flexible array member.
kono
parents:
diff changeset
27
kono
parents:
diff changeset
28 #include "libitm_i.h"
kono
parents:
diff changeset
29
kono
parents:
diff changeset
30 namespace GTM HIDDEN {
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 // The code for rebalancing the tree is greatly simplified by never
kono
parents:
diff changeset
33 // having to check for null pointers. Instead, leaf node links point
kono
parents:
diff changeset
34 // to this node, NIL, which points to itself.
kono
parents:
diff changeset
35 const aa_node_base aa_node_base::s_nil(0);
kono
parents:
diff changeset
36
kono
parents:
diff changeset
37
kono
parents:
diff changeset
38 // Remove left horizontal links. Swap the pointers of horizontal left links.
kono
parents:
diff changeset
39
kono
parents:
diff changeset
40 aa_node_base *
kono
parents:
diff changeset
41 aa_node_base::skew ()
kono
parents:
diff changeset
42 {
kono
parents:
diff changeset
43 aa_node_base *l = this->link(L);
kono
parents:
diff changeset
44 if (this->m_level != 0 && l->m_level == this->m_level)
kono
parents:
diff changeset
45 {
kono
parents:
diff changeset
46 this->set_link(L, l->link(R));
kono
parents:
diff changeset
47 l->set_link(R, this);
kono
parents:
diff changeset
48 return l;
kono
parents:
diff changeset
49 }
kono
parents:
diff changeset
50 return this;
kono
parents:
diff changeset
51 }
kono
parents:
diff changeset
52
kono
parents:
diff changeset
53
kono
parents:
diff changeset
54 // Remove consecutive horizontal links. Take the middle node,
kono
parents:
diff changeset
55 // elevate it, and return it.
kono
parents:
diff changeset
56
kono
parents:
diff changeset
57 aa_node_base *
kono
parents:
diff changeset
58 aa_node_base::split ()
kono
parents:
diff changeset
59 {
kono
parents:
diff changeset
60 aa_node_base *r = this->link(R);
kono
parents:
diff changeset
61 if (this->m_level != 0 && r->link(R)->m_level == this->m_level)
kono
parents:
diff changeset
62 {
kono
parents:
diff changeset
63 this->set_link(R, r->link(L));
kono
parents:
diff changeset
64 r->set_link(L, this);
kono
parents:
diff changeset
65 r->m_level += 1;
kono
parents:
diff changeset
66 return r;
kono
parents:
diff changeset
67 }
kono
parents:
diff changeset
68 return this;
kono
parents:
diff changeset
69 }
kono
parents:
diff changeset
70
kono
parents:
diff changeset
71 // Decrease the level of THIS to be one more than the level of its children.
kono
parents:
diff changeset
72
kono
parents:
diff changeset
73 void
kono
parents:
diff changeset
74 aa_node_base::decrease_level ()
kono
parents:
diff changeset
75 {
kono
parents:
diff changeset
76 aa_node_base *l = this->link(L);
kono
parents:
diff changeset
77 aa_node_base *r = this->link(R);
kono
parents:
diff changeset
78 level_type llev = l->m_level;
kono
parents:
diff changeset
79 level_type rlev = r->m_level;
kono
parents:
diff changeset
80 level_type should_be = (llev < rlev ? llev : rlev) + 1;
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 if (should_be < this->m_level)
kono
parents:
diff changeset
83 {
kono
parents:
diff changeset
84 this->m_level = should_be;
kono
parents:
diff changeset
85 if (should_be < rlev)
kono
parents:
diff changeset
86 r->m_level = should_be;
kono
parents:
diff changeset
87 }
kono
parents:
diff changeset
88 }
kono
parents:
diff changeset
89
kono
parents:
diff changeset
90 // Find and return the node in the tree with key K.
kono
parents:
diff changeset
91
kono
parents:
diff changeset
92 template<typename KEY>
kono
parents:
diff changeset
93 typename aa_tree_key<KEY>::node_ptr
kono
parents:
diff changeset
94 aa_tree_key<KEY>::find(KEY k) const
kono
parents:
diff changeset
95 {
kono
parents:
diff changeset
96 node_ptr t = m_tree;
kono
parents:
diff changeset
97 if (t != 0)
kono
parents:
diff changeset
98 do
kono
parents:
diff changeset
99 {
kono
parents:
diff changeset
100 if (t->key == k)
kono
parents:
diff changeset
101 return t;
kono
parents:
diff changeset
102 t = t->link(k > t->key);
kono
parents:
diff changeset
103 }
kono
parents:
diff changeset
104 while (!t->is_nil());
kono
parents:
diff changeset
105 return 0;
kono
parents:
diff changeset
106 }
kono
parents:
diff changeset
107
kono
parents:
diff changeset
108 // Insert N into T and rebalance. Return the new balanced tree.
kono
parents:
diff changeset
109
kono
parents:
diff changeset
110 template<typename KEY>
kono
parents:
diff changeset
111 typename aa_tree_key<KEY>::node_ptr
kono
parents:
diff changeset
112 aa_tree_key<KEY>::insert_1 (node_ptr t, node_ptr n)
kono
parents:
diff changeset
113 {
kono
parents:
diff changeset
114 bool dir = n->key > t->key;
kono
parents:
diff changeset
115 node_ptr c = t->link(dir);
kono
parents:
diff changeset
116
kono
parents:
diff changeset
117 // Insert the node, recursively.
kono
parents:
diff changeset
118 if (c->is_nil())
kono
parents:
diff changeset
119 c = n;
kono
parents:
diff changeset
120 else
kono
parents:
diff changeset
121 c = insert_1 (c, n);
kono
parents:
diff changeset
122 t->set_link(dir, c);
kono
parents:
diff changeset
123
kono
parents:
diff changeset
124 // Rebalance the tree, as needed.
kono
parents:
diff changeset
125 t = t->skew();
kono
parents:
diff changeset
126 t = t->split();
kono
parents:
diff changeset
127
kono
parents:
diff changeset
128 return t;
kono
parents:
diff changeset
129 }
kono
parents:
diff changeset
130
kono
parents:
diff changeset
131 template<typename KEY>
kono
parents:
diff changeset
132 void
kono
parents:
diff changeset
133 aa_tree_key<KEY>::insert(node_ptr n)
kono
parents:
diff changeset
134 {
kono
parents:
diff changeset
135 if (m_tree == 0)
kono
parents:
diff changeset
136 m_tree = n;
kono
parents:
diff changeset
137 else
kono
parents:
diff changeset
138 m_tree = insert_1 (m_tree, n);
kono
parents:
diff changeset
139 }
kono
parents:
diff changeset
140
kono
parents:
diff changeset
141 // Delete K from T and rebalance. Return the new balanced tree.
kono
parents:
diff changeset
142
kono
parents:
diff changeset
143 template<typename KEY>
kono
parents:
diff changeset
144 typename aa_tree_key<KEY>::node_ptr
kono
parents:
diff changeset
145 aa_tree_key<KEY>::erase_1 (node_ptr t, KEY k, node_ptr *pfree)
kono
parents:
diff changeset
146 {
kono
parents:
diff changeset
147 node_ptr r;
kono
parents:
diff changeset
148 bool dir;
kono
parents:
diff changeset
149
kono
parents:
diff changeset
150 // If this is the node we're looking for, delete it. Else recurse.
kono
parents:
diff changeset
151 if (k == t->key)
kono
parents:
diff changeset
152 {
kono
parents:
diff changeset
153 node_ptr l, sub, end;
kono
parents:
diff changeset
154
kono
parents:
diff changeset
155 l = t->link(node::L);
kono
parents:
diff changeset
156 r = t->link(node::R);
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 if (pfree)
kono
parents:
diff changeset
159 *pfree = t;
kono
parents:
diff changeset
160
kono
parents:
diff changeset
161 // If this is a leaf node, simply remove the node. Otherwise,
kono
parents:
diff changeset
162 // we have to find either a predecessor or a successor node to
kono
parents:
diff changeset
163 // replace this one.
kono
parents:
diff changeset
164 if (l->is_nil())
kono
parents:
diff changeset
165 {
kono
parents:
diff changeset
166 if (r->is_nil())
kono
parents:
diff changeset
167 return r;
kono
parents:
diff changeset
168 sub = r, dir = node::L;
kono
parents:
diff changeset
169 }
kono
parents:
diff changeset
170 else
kono
parents:
diff changeset
171 sub = l, dir = node::R;
kono
parents:
diff changeset
172
kono
parents:
diff changeset
173 // Find the successor or predecessor.
kono
parents:
diff changeset
174 for (end = sub; !end->link(dir)->is_nil(); end = end->link(dir))
kono
parents:
diff changeset
175 continue;
kono
parents:
diff changeset
176
kono
parents:
diff changeset
177 // Remove it (but don't free) from the subtree.
kono
parents:
diff changeset
178 sub = erase_1 (sub, end->key, 0);
kono
parents:
diff changeset
179
kono
parents:
diff changeset
180 // Replace T with the successor we just extracted.
kono
parents:
diff changeset
181 end->set_link(!dir, sub);
kono
parents:
diff changeset
182 t = end;
kono
parents:
diff changeset
183 }
kono
parents:
diff changeset
184 else
kono
parents:
diff changeset
185 {
kono
parents:
diff changeset
186 dir = k > t->key;
kono
parents:
diff changeset
187 t->set_link(dir, erase_1 (t->link(dir), k, pfree));
kono
parents:
diff changeset
188 }
kono
parents:
diff changeset
189
kono
parents:
diff changeset
190 // Rebalance the tree.
kono
parents:
diff changeset
191 t->decrease_level();
kono
parents:
diff changeset
192 t = t->skew();
kono
parents:
diff changeset
193 r = t->link(node::R)->skew();
kono
parents:
diff changeset
194 t->set_link(node::R, r);
kono
parents:
diff changeset
195 r->set_link(node::R, r->link(node::R)->skew());
kono
parents:
diff changeset
196 t = t->split ();
kono
parents:
diff changeset
197 t->set_link(node::R, t->link(node::R)->split());
kono
parents:
diff changeset
198
kono
parents:
diff changeset
199 return t;
kono
parents:
diff changeset
200 }
kono
parents:
diff changeset
201
kono
parents:
diff changeset
202 template<typename KEY>
kono
parents:
diff changeset
203 typename aa_tree_key<KEY>::node_ptr
kono
parents:
diff changeset
204 aa_tree_key<KEY>::erase (KEY k)
kono
parents:
diff changeset
205 {
kono
parents:
diff changeset
206 node_ptr t = m_tree;
kono
parents:
diff changeset
207 if (t == 0)
kono
parents:
diff changeset
208 return 0;
kono
parents:
diff changeset
209
kono
parents:
diff changeset
210 node_ptr do_free = 0;
kono
parents:
diff changeset
211 t = erase_1 (t, k, &do_free);
kono
parents:
diff changeset
212 if (t->is_nil())
kono
parents:
diff changeset
213 t = 0;
kono
parents:
diff changeset
214 m_tree = t;
kono
parents:
diff changeset
215 return do_free;
kono
parents:
diff changeset
216 }
kono
parents:
diff changeset
217
kono
parents:
diff changeset
218 // Instantiate key classes.
kono
parents:
diff changeset
219
kono
parents:
diff changeset
220 template class aa_tree_key<uintptr_t>;
kono
parents:
diff changeset
221
kono
parents:
diff changeset
222 } // namespace GTM