@@ -518,20 +518,8 @@ class sharing_mapt
518
518
protected:
519
519
// helpers
520
520
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 ;
535
523
536
524
// / Move a container node (containing a single leaf) further down the tree
537
525
// / such as to resolve a collision with another key-value pair. This method is
@@ -551,11 +539,14 @@ class sharing_mapt
551
539
// / container node to move further down the tree
552
540
// / \return pointer to the container to which the element to be newly inserted
553
541
// / can be added
554
- innert *migrate (
542
+ template <class valueU >
543
+ void migrate (
555
544
const std::size_t starting_level,
556
545
const std::size_t key_suffix,
557
546
const std::size_t bit_last,
558
- innert &inner);
547
+ innert &inner,
548
+ const key_type &k,
549
+ valueU &&m);
559
550
560
551
void iterate(
561
552
const innert &n,
@@ -1031,7 +1022,7 @@ ::get_delta_view(
1031
1022
while (!stack.empty ());
1032
1023
}
1033
1024
1034
- SHARING_MAPT2 (, innert *)::get_container_node (const key_type &k)
1025
+ SHARING_MAPT2 (, leaft *)::get_leaf_node (const key_type &k)
1035
1026
{
1036
1027
SM_ASSERT (has_key (k));
1037
1028
@@ -1045,19 +1036,30 @@ SHARING_MAPT2(, innert *)::get_container_node(const key_type &k)
1045
1036
1046
1037
ip = ip->add_child (bit);
1047
1038
SM_ASSERT (ip != nullptr );
1048
- SM_ASSERT (!ip->empty ());
1039
+ SM_ASSERT (!ip->empty ()); // since the key must exist in the map
1049
1040
1050
- if (ip->is_container ())
1041
+ if (ip->is_internal ())
1042
+ {
1043
+ key >>= chunk;
1044
+ continue ;
1045
+ }
1046
+
1047
+ if (ip->is_leaf ())
1048
+ {
1051
1049
return ip;
1050
+ }
1052
1051
1053
- key >>= chunk;
1052
+ if (ip->is_container ())
1053
+ {
1054
+ return ip->find_leaf (k);
1055
+ }
1054
1056
}
1055
1057
1056
1058
UNREACHABLE;
1057
1059
return nullptr ;
1058
1060
}
1059
1061
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
1061
1063
{
1062
1064
if (empty ())
1063
1065
return nullptr ;
@@ -1077,10 +1079,21 @@ SHARING_MAPT2(const, innert *)::get_container_node(const key_type &k) const
1077
1079
1078
1080
SM_ASSERT (!ip->empty ());
1079
1081
1080
- if (ip->is_container ())
1081
- return ip;
1082
+ if (ip->is_internal ())
1083
+ {
1084
+ key >>= chunk;
1085
+ continue ;
1086
+ }
1082
1087
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
+ }
1084
1097
}
1085
1098
1086
1099
UNREACHABLE;
@@ -1111,62 +1124,72 @@ SHARING_MAPT(void)::erase(const key_type &k)
1111
1124
1112
1125
ip = ip->add_child (bit);
1113
1126
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
+ }
1115
1144
1116
1145
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 ());
1118
1150
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
+ }
1121
1161
1122
- PRECONDITION (!ip->empty ());
1123
- const leaf_listt &ll = as_const (ip)->get_container ();
1124
- PRECONDITION (!ll.empty ());
1162
+ num--;
1125
1163
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
+ }
1135
1166
}
1136
1167
1137
- num-- ;
1168
+ UNREACHABLE ;
1138
1169
}
1139
1170
1140
- SHARING_MAPT2 (, innert *)::migrate(
1171
+ SHARING_MAPT4 (valueU, void )
1172
+ ::migrate(
1141
1173
const std::size_t starting_level,
1142
1174
const std::size_t key_suffix,
1143
1175
const std::size_t bit_last,
1144
- innert &inner)
1176
+ innert &inner,
1177
+ const key_type &k,
1178
+ valueU &&m)
1145
1179
{
1146
1180
SM_ASSERT (starting_level < levels - 1 );
1147
1181
SM_ASSERT (inner.is_defined_internal ());
1148
1182
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 ());
1156
1185
1157
- const leaft &leaf = ll.front ();
1158
1186
std::size_t key_existing = hash ()(leaf.get_key ());
1159
-
1160
1187
key_existing >>= chunk * starting_level;
1161
1188
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);
1167
1191
1168
- // Add internal node
1169
- innert *ip = inner.add_child (bit_last);
1192
+ innert *ip = &leaf;
1170
1193
SM_ASSERT (ip->empty ());
1171
1194
1172
1195
// Find place for both elements
@@ -1181,18 +1204,24 @@ SHARING_MAPT2(, innert *)::migrate(
1181
1204
1182
1205
do
1183
1206
{
1207
+ SM_ASSERT (ip->empty ());
1208
+
1184
1209
std::size_t bit_existing = key_existing & mask;
1185
1210
std::size_t bit = key & mask;
1186
1211
1187
1212
if (bit != bit_existing)
1188
1213
{
1189
1214
// Place found
1190
1215
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);
1193
1219
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 ;
1196
1225
}
1197
1226
1198
1227
SM_ASSERT (bit == bit_existing);
@@ -1204,10 +1233,17 @@ SHARING_MAPT2(, innert *)::migrate(
1204
1233
level++;
1205
1234
} while (level < levels);
1206
1235
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
1209
1237
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));
1211
1247
}
1212
1248
1213
1249
SHARING_MAPT4 (valueU, void )
@@ -1218,7 +1254,7 @@ ::insert(const key_type &k, valueU &&m)
1218
1254
std::size_t key = hash ()(k);
1219
1255
innert *ip = ↦
1220
1256
1221
- // The root cannot be a container node
1257
+ // The root must be an internal node
1222
1258
SM_ASSERT (ip->is_internal ());
1223
1259
1224
1260
std::size_t level = 0 ;
@@ -1236,51 +1272,63 @@ ::insert(const key_type &k, valueU &&m)
1236
1272
// Place is unoccupied
1237
1273
if (child->empty ())
1238
1274
{
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 );
1241
1283
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
+ }
1243
1289
1244
1290
num++;
1245
1291
1246
1292
return ;
1247
1293
}
1248
1294
1249
- if (child->is_container ())
1295
+ if (child->is_internal ())
1250
1296
{
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++;
1255
1300
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));
1263
1308
1264
1309
num++;
1265
1310
1266
1311
return ;
1267
1312
}
1268
1313
1269
- SM_ASSERT (level == levels - 1 || child->is_defined_internal ());
1314
+ if (child->is_container ())
1315
+ {
1316
+ SM_ASSERT (level == levels - 1 );
1270
1317
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
+ }
1274
1325
}
1275
1326
}
1276
1327
1277
1328
SHARING_MAPT4 (valueU, void )
1278
1329
::replace(const key_type &k, valueU &&m)
1279
1330
{
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);
1284
1332
PRECONDITION (lp != nullptr ); // key must exist in map
1285
1333
1286
1334
INVARIANT (
@@ -1293,10 +1341,7 @@ ::replace(const key_type &k, valueU &&m)
1293
1341
SHARING_MAPT (void )
1294
1342
::update(const key_type &k, std::function<void (mapped_type &)> mutator)
1295
1343
{
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);
1300
1345
PRECONDITION (lp != nullptr ); // key must exist in map
1301
1346
1302
1347
value_comparatort comparator (as_const (lp)->get_value ());
0 commit comments