Now I need to connect the way processing section to use the `combined_reader` and the stashed `first_way_buf`. Let me find where the old Pass 3 reader was used:


2593:                    while (auto buf = reader_ways.read()) {
2601:                    reader_ways.close();


  2315→                std::cerr << "  Node processing complete: " << total_addrs
  2316→                          << " address points collected." << std::endl;
  2317→                log_phase("Pass 2: node processing", _pt);
  2318→                std::cerr << "  Processing ways with " << num_threads << " threads..." << std::endl;
  2319→
  2320→                // --- Phase 2: Way processing using same reader ---
  2321→
  2322→                // Thread-local data for parallel way processing
  2323→                struct ThreadLocalData {
  2324→                    std::vector<WayHeader> ways;

                std::cerr << "  Node processing complete: " << total_addrs
                          << " address points collected." << std::endl;
                log_phase("Pass 2: node processing", _pt);
                std::cerr << "  Processing ways with " << num_threads << " threads..." << std::endl;

                // --- Phase 2: Way processing using same reader ---

                // Thread-local data for parallel way processing
                struct ThreadLocalData {
                    std::vector<WayHeader> ways;


Good, the way processing setup (ThreadLocalData, workers) follows. Now I need to find and replace the way reader section. Let me look at where the old `reader_ways` was opened:


  2585→                                std::cerr << "  Processed " << done << " way blocks..." << std::endl;
  2586→                            }
  2587→                        }
  2588→                    });
  2589→                }
  2590→
  2591→                // Way reader (producer)
  2592→                {
  2593→                    while (auto buf = reader_ways.read()) {
  2594→                        {
  2595→                            std::unique_lock<std::mutex> lock(way_queue_mutex);
  2596→                            way_queue_cv.wait(lock, [&]{ return way_block_queue.size() < WAY_MAX_QUEUE; });
  2597→                            way_block_queue.push_back(std::move(buf));
  2598→                        }
  2599→                        way_queue_cv.notify_one();
  2600→                    }
  2601→                    reader_ways.close();
  2602→                    {
  2603→                        std::lock_guard<std::mutex> lock(way_queue_mutex);
  2604→                        way_reader_done = true;
  2605→                    }
  2606→                    way_queue_cv.notify_all();
  2607→                }
  2608→
  2609→                for (auto& w : workers) w.join();

                                std::cerr << "  Processed " << done << " way blocks..." << std::endl;
                            }
                        }
                    });
                }

                // Way reader (producer)
                {
                    while (auto buf = reader_ways.read()) {
                        {
                            std::unique_lock<std::mutex> lock(way_queue_mutex);
                            way_queue_cv.wait(lock, [&]{ return way_block_queue.size() < WAY_MAX_QUEUE; });
                            way_block_queue.push_back(std::move(buf));
                        }
                        way_queue_cv.notify_one();
                    }
                    reader_ways.close();
                    {
                        std::lock_guard<std::mutex> lock(way_queue_mutex);
                        way_reader_done = true;
                    }
                    way_queue_cv.notify_all();
                }

                for (auto& w : workers) w.join();


Now let me replace the old reader_ways section with one that uses the combined_reader:


Edit

                // Way reader (producer)
                {
                    while (auto buf = reader_ways.read()) {
                        {
                            std::unique_lock<std::mutex> lock(way_queue_mutex);
                            way_queue_cv.wait(lock, [&]{ return way_block_queue.size() < WAY_MAX_QUEUE; });
                            way_block_queue.push_back(std::move(buf));
                        }
                        way_queue_cv.notify_one();
                    }
                    reader_ways.close();
                    {
                        std::lock_guard<std::mutex> lock(way_queue_mutex);
                        way_reader_done = true;
                    }
                    way_queue_cv.notify_all();
                }

                // Way reader: use the combined_reader (continuing from where nodes left off)
                {
                    // First, push the stashed way buffer
                    if (first_way_buf) {
                        std::unique_lock<std::mutex> lock(way_queue_mutex);
                        way_queue_cv.wait(lock, [&]{ return way_block_queue.size() < WAY_MAX_QUEUE; });
                        way_block_queue.push_back(std::move(first_way_buf));
                        way_queue_cv.notify_one();
                    }
                    // Continue reading remaining blocks from the same reader
                    while (auto buf = combined_reader.read()) {
                        {
                            std::unique_lock<std::mutex> lock(way_queue_mutex);
                            way_queue_cv.wait(lock, [&]{ return way_block_queue.size() < WAY_MAX_QUEUE; });
                            way_block_queue.push_back(std::move(buf));
                        }
                        way_queue_cv.notify_one();
                    }
                    combined_reader.close();
                    {
                        std::lock_guard<std::mutex> lock(way_queue_mutex);
                        way_reader_done = true;
                    }
                    way_queue_cv.notify_all();
                }