+ else
+ {
+ SORT_TRACE("Skipped presorting");
+ ins[0] = b;
+ }
+
+ SORT_TRACE("Main sorting");
+ do {
+ if (ins[0]->runs == 1 && ins[1]->runs == 1 && join)
+ {
+ // This is guaranteed to produce a single run, so join if possible
+ outs[0] = join;
+ outs[1] = NULL;
+ ctx->twoway_merge(ctx, ins, outs);
+ ASSERT(outs[0]->runs == 2);
+ outs[0]->runs--;
+ SORT_TRACE("Pass done (joined final run)");
+ sbuck_drop(ins[0]);
+ sbuck_drop(ins[1]);
+ return;
+ }
+ outs[0] = sbuck_new(ctx);
+ outs[1] = sbuck_new(ctx);
+ outs[2] = NULL;
+ ctx->twoway_merge(ctx, ins, outs);
+ SORT_TRACE("Pass done (%d+%d runs, %jd+%jd bytes)", outs[0]->runs, outs[1]->runs, (uintmax_t) sbuck_size(outs[0]), (uintmax_t) sbuck_size(outs[1]));
+ sbuck_drop(ins[0]);
+ sbuck_drop(ins[1]);
+ memcpy(ins, outs, 3*sizeof(struct sort_bucket *));
+ } while (sbuck_have(ins[1]));
+
+ sbuck_drop(ins[1]);
+ clist_insert_after(&ins[0]->n, list_pos);