Skip to content

Commit 9b2f32b

Browse files
committed
Adapt methods for finding, erasing, and inserting elements into the sharing map
This adapts the methods for the case where a leafs can directly be attached to internal nodes.
1 parent 9cacc35 commit 9b2f32b

File tree

2 files changed

+149
-98
lines changed

2 files changed

+149
-98
lines changed

src/util/sharing_map.h

Lines changed: 139 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -518,20 +518,8 @@ class sharing_mapt
518518
protected:
519519
// helpers
520520

521-
innert *get_container_node(const key_type &k);
522-
const innert *get_container_node(const key_type &k) const;
523-
524-
const leaft *get_leaf_node(const key_type &k) const
525-
{
526-
const innert *cp = get_container_node(k);
527-
if(cp == nullptr)
528-
return nullptr;
529-
530-
const leaft *lp;
531-
lp = cp->find_leaf(k);
532-
533-
return lp;
534-
}
521+
leaft *get_leaf_node(const key_type &k);
522+
const leaft *get_leaf_node(const key_type &k) const;
535523

536524
/// Move a container node (containing a single leaf) further down the tree
537525
/// such as to resolve a collision with another key-value pair. This method is
@@ -551,11 +539,14 @@ class sharing_mapt
551539
/// container node to move further down the tree
552540
/// \return pointer to the container to which the element to be newly inserted
553541
/// can be added
554-
innert *migrate(
542+
template <class valueU>
543+
void migrate(
555544
const std::size_t starting_level,
556545
const std::size_t key_suffix,
557546
const std::size_t bit_last,
558-
innert &inner);
547+
innert &inner,
548+
const key_type &k,
549+
valueU &&m);
559550

560551
void iterate(
561552
const innert &n,
@@ -1031,7 +1022,7 @@ ::get_delta_view(
10311022
while(!stack.empty());
10321023
}
10331024

1034-
SHARING_MAPT2(, innert *)::get_container_node(const key_type &k)
1025+
SHARING_MAPT2(, leaft *)::get_leaf_node(const key_type &k)
10351026
{
10361027
SM_ASSERT(has_key(k));
10371028

@@ -1045,19 +1036,30 @@ SHARING_MAPT2(, innert *)::get_container_node(const key_type &k)
10451036

10461037
ip = ip->add_child(bit);
10471038
SM_ASSERT(ip != nullptr);
1048-
SM_ASSERT(!ip->empty());
1039+
SM_ASSERT(!ip->empty()); // since the key must exist in the map
10491040

1050-
if(ip->is_container())
1041+
if(ip->is_internal())
1042+
{
1043+
key >>= chunk;
1044+
continue;
1045+
}
1046+
1047+
if(ip->is_leaf())
1048+
{
10511049
return ip;
1050+
}
10521051

1053-
key >>= chunk;
1052+
if(ip->is_container())
1053+
{
1054+
return ip->find_leaf(k);
1055+
}
10541056
}
10551057

10561058
UNREACHABLE;
10571059
return nullptr;
10581060
}
10591061

1060-
SHARING_MAPT2(const, innert *)::get_container_node(const key_type &k) const
1062+
SHARING_MAPT2(const, leaft *)::get_leaf_node(const key_type &k) const
10611063
{
10621064
if(empty())
10631065
return nullptr;
@@ -1077,10 +1079,21 @@ SHARING_MAPT2(const, innert *)::get_container_node(const key_type &k) const
10771079

10781080
SM_ASSERT(!ip->empty());
10791081

1080-
if(ip->is_container())
1081-
return ip;
1082+
if(ip->is_internal())
1083+
{
1084+
key >>= chunk;
1085+
continue;
1086+
}
10821087

1083-
key >>= chunk;
1088+
if(ip->is_leaf())
1089+
{
1090+
return equalT()(ip->get_key(), k) ? ip : nullptr;
1091+
}
1092+
1093+
if(ip->is_container())
1094+
{
1095+
return ip->find_leaf(k); // returns nullptr if leaf is not found
1096+
}
10841097
}
10851098

10861099
UNREACHABLE;
@@ -1111,62 +1124,72 @@ SHARING_MAPT(void)::erase(const key_type &k)
11111124

11121125
ip = ip->add_child(bit);
11131126

1114-
SM_ASSERT(!ip->empty());
1127+
PRECONDITION(!ip->empty());
1128+
1129+
if(ip->is_internal())
1130+
{
1131+
key >>= chunk;
1132+
continue;
1133+
}
1134+
1135+
if(ip->is_leaf())
1136+
{
1137+
PRECONDITION(equalT()(ip->get_key(), k));
1138+
del->remove_child(del_bit);
1139+
1140+
num--;
1141+
1142+
return;
1143+
}
11151144

11161145
if(ip->is_container())
1117-
break;
1146+
{
1147+
PRECONDITION(!ip->empty());
1148+
const leaf_listt &ll = as_const(ip)->get_container();
1149+
PRECONDITION(!ll.empty());
11181150

1119-
key >>= chunk;
1120-
}
1151+
// forward list has one element
1152+
if(std::next(ll.begin()) == ll.end())
1153+
{
1154+
PRECONDITION(equalT()(ll.front().get_key(), k));
1155+
del->remove_child(del_bit);
1156+
}
1157+
else
1158+
{
1159+
ip->remove_leaf(k);
1160+
}
11211161

1122-
PRECONDITION(!ip->empty());
1123-
const leaf_listt &ll = as_const(ip)->get_container();
1124-
PRECONDITION(!ll.empty());
1162+
num--;
11251163

1126-
// forward list has one element
1127-
if(std::next(ll.begin()) == ll.end())
1128-
{
1129-
PRECONDITION(equalT()(ll.front().get_key(), k));
1130-
del->remove_child(del_bit);
1131-
}
1132-
else
1133-
{
1134-
ip->remove_leaf(k);
1164+
return;
1165+
}
11351166
}
11361167

1137-
num--;
1168+
UNREACHABLE;
11381169
}
11391170

1140-
SHARING_MAPT2(, innert *)::migrate(
1171+
SHARING_MAPT4(valueU, void)
1172+
::migrate(
11411173
const std::size_t starting_level,
11421174
const std::size_t key_suffix,
11431175
const std::size_t bit_last,
1144-
innert &inner)
1176+
innert &inner,
1177+
const key_type &k,
1178+
valueU &&m)
11451179
{
11461180
SM_ASSERT(starting_level < levels - 1);
11471181
SM_ASSERT(inner.is_defined_internal());
11481182

1149-
const innert &child = *inner.find_child(bit_last);
1150-
SM_ASSERT(child.is_defined_container());
1151-
1152-
const leaf_listt &ll = child.get_container();
1153-
1154-
// Only containers at the bottom can contain more than two elements
1155-
SM_ASSERT(is_singular(ll));
1183+
leaft &leaf = *inner.add_child(bit_last);
1184+
SM_ASSERT(leaf.is_defined_leaf());
11561185

1157-
const leaft &leaf = ll.front();
11581186
std::size_t key_existing = hash()(leaf.get_key());
1159-
11601187
key_existing >>= chunk * starting_level;
11611188

1162-
// Copy the container
1163-
innert container_copy(child);
1164-
1165-
// Delete existing container
1166-
inner.remove_child(bit_last);
1189+
leaft leaf_kept;
1190+
leaf_kept.swap(leaf);
11671191

1168-
// Add internal node
1169-
innert *ip = inner.add_child(bit_last);
1192+
innert *ip = &leaf;
11701193
SM_ASSERT(ip->empty());
11711194

11721195
// Find place for both elements
@@ -1181,18 +1204,24 @@ SHARING_MAPT2(, innert *)::migrate(
11811204

11821205
do
11831206
{
1207+
SM_ASSERT(ip->empty());
1208+
11841209
std::size_t bit_existing = key_existing & mask;
11851210
std::size_t bit = key & mask;
11861211

11871212
if(bit != bit_existing)
11881213
{
11891214
// Place found
11901215

1191-
innert *cp2 = ip->add_child(bit_existing);
1192-
cp2->swap(container_copy);
1216+
innert *l1 = ip->add_child(bit_existing);
1217+
SM_ASSERT(l1->empty());
1218+
l1->swap(leaf_kept);
11931219

1194-
innert *cp1 = ip->add_child(bit);
1195-
return cp1;
1220+
innert *l2 = ip->add_child(bit);
1221+
SM_ASSERT(l2->empty());
1222+
l2->make_leaf(k, std::forward<valueU>(m));
1223+
1224+
return;
11961225
}
11971226

11981227
SM_ASSERT(bit == bit_existing);
@@ -1204,10 +1233,17 @@ SHARING_MAPT2(, innert *)::migrate(
12041233
level++;
12051234
} while(level < levels);
12061235

1207-
leaft leaf_copy(as_const(&container_copy)->get_container().front());
1208-
ip->get_container().push_front(leaf_copy);
1236+
// Hash collision, create container and add both elements to it
12091237

1210-
return ip;
1238+
PRECONDITION(!equalT()(k, leaf_kept.get_key()));
1239+
1240+
SM_ASSERT(ip->empty());
1241+
// Make container and add existing leaf
1242+
ip->get_container().push_front(leaf_kept);
1243+
1244+
SM_ASSERT(ip->is_defined_container());
1245+
// Insert new element in same container
1246+
ip->place_leaf(k, std::forward<valueU>(m));
12111247
}
12121248

12131249
SHARING_MAPT4(valueU, void)
@@ -1218,7 +1254,7 @@ ::insert(const key_type &k, valueU &&m)
12181254
std::size_t key = hash()(k);
12191255
innert *ip = &map;
12201256

1221-
// The root cannot be a container node
1257+
// The root must be an internal node
12221258
SM_ASSERT(ip->is_internal());
12231259

12241260
std::size_t level = 0;
@@ -1236,51 +1272,63 @@ ::insert(const key_type &k, valueU &&m)
12361272
// Place is unoccupied
12371273
if(child->empty())
12381274
{
1239-
// Create container and insert leaf
1240-
child->place_leaf(k, std::forward<valueU>(m));
1275+
if(level < levels - 1)
1276+
{
1277+
// Create leaf
1278+
child->make_leaf(k, m);
1279+
}
1280+
else
1281+
{
1282+
SM_ASSERT(level == levels - 1);
12411283

1242-
SM_ASSERT(child->is_defined_container());
1284+
// Create container and insert leaf
1285+
child->place_leaf(k, std::forward<valueU>(m));
1286+
1287+
SM_ASSERT(child->is_defined_container());
1288+
}
12431289

12441290
num++;
12451291

12461292
return;
12471293
}
12481294

1249-
if(child->is_container())
1295+
if(child->is_internal())
12501296
{
1251-
if(level < levels - 1)
1252-
{
1253-
// Migrate the elements downwards
1254-
innert *cp = migrate(level, key, bit, *ip);
1297+
ip = child;
1298+
key >>= chunk;
1299+
level++;
12551300

1256-
cp->place_leaf(k, std::forward<valueU>(m));
1257-
}
1258-
else
1259-
{
1260-
// Add to the bottom container
1261-
child->place_leaf(k, std::forward<valueU>(m));
1262-
}
1301+
continue;
1302+
}
1303+
1304+
if(child->is_leaf())
1305+
{
1306+
// migrate leaf downwards
1307+
migrate(level, key, bit, *ip, k, std::forward<valueU>(m));
12631308

12641309
num++;
12651310

12661311
return;
12671312
}
12681313

1269-
SM_ASSERT(level == levels - 1 || child->is_defined_internal());
1314+
if(child->is_container())
1315+
{
1316+
SM_ASSERT(level == levels - 1);
12701317

1271-
ip = child;
1272-
key >>= chunk;
1273-
level++;
1318+
// Add to the container
1319+
child->place_leaf(k, std::forward<valueU>(m));
1320+
1321+
num++;
1322+
1323+
return;
1324+
}
12741325
}
12751326
}
12761327

12771328
SHARING_MAPT4(valueU, void)
12781329
::replace(const key_type &k, valueU &&m)
12791330
{
1280-
innert *cp = get_container_node(k);
1281-
SM_ASSERT(cp != nullptr);
1282-
1283-
leaft *lp = cp->find_leaf(k);
1331+
leaft *lp = get_leaf_node(k);
12841332
PRECONDITION(lp != nullptr); // key must exist in map
12851333

12861334
INVARIANT(
@@ -1293,10 +1341,7 @@ ::replace(const key_type &k, valueU &&m)
12931341
SHARING_MAPT(void)
12941342
::update(const key_type &k, std::function<void(mapped_type &)> mutator)
12951343
{
1296-
innert *cp = get_container_node(k);
1297-
SM_ASSERT(cp != nullptr);
1298-
1299-
leaft *lp = cp->find_leaf(k);
1344+
leaft *lp = get_leaf_node(k);
13001345
PRECONDITION(lp != nullptr); // key must exist in map
13011346

13021347
value_comparatort comparator(as_const(lp)->get_value());

0 commit comments

Comments
 (0)