+ bool sub_full = false;
+ key += rec_alloc(new_node, shift - radix_bits, &sub_full);
+
+ if (sub_full)
+ dn->index_bmap |= 1UL << off;
+ } else {
+ assert(shift == radix_bits);
+
+ LeafNode *ln = static_cast<LeafNode *>(node);
+ assert(~ln->nodes[off] != 0);
+
+ int leaf_bit = ll_ffs(ln->nodes[off]);
+ key |= ((Key)1) << leaf_bit;
+
+ if (key >= max_key)
+ throw_idl(::System::Exceptions::Std::OutOfSpace,
+ ::System::RunTime::nullarray);
+
+ ln->nodes[off] |= 1UL << leaf_bit;
+
+ if (~ln->nodes[off] == 0)
+ ln->index_bmap |= 1UL << off;
+ }
+
+ if (~node->index_bmap == 0 && full)
+ *full = true;
+
+ return key;
+ }
+
+ public:
+ // Throws System::Exceptions::Std::OutOfSpace on failure
+ Key alloc()
+ {
+ if (unlikely(~toplevel->index_bmap == 0)) {
+ int new_shift = toplevel_shift + radix_bits;
+
+ if (new_shift >= key_bits ||
+ (((Key)1) << new_shift) >= max_key)
+ throw_idl(::System::Exceptions::Std::OutOfSpace,
+ ::System::RunTime::nullarray);
+
+ DirNode *dn = new DirNode;
+ dn->nodes[0] = toplevel;
+ toplevel_shift = new_shift;
+ toplevel = dn;
+ }
+
+ return rec_alloc(toplevel, toplevel_shift, NULL);
+ }
+
+ // Throws System::InvalidArgument if key is already free
+ void free(Key key)
+ {
+ Node *node = toplevel;
+ int shift = toplevel_shift;
+ int max_bits = toplevel_shift + radix_bits;
+
+ if (max_bits < key_bits && key >= (((Key)1) << max_bits))
+ throw_idl(::System::Exceptions::Std::InvalidArgument, 0,
+ ::System::RunTime::nullarray);
+
+ while (shift > radix_bits) {
+ assert(shift >= radix_bits * 2);
+
+ int off = key_to_offset(key, shift);
+ node->index_bmap &= ~(1UL << off);
+
+ DirNode *dn = static_cast<DirNode *>(node);
+ node = dn->nodes[off];