[Spec][Ngram] 3/N: Fix synchronization issues in Ngram.cpp (#21186)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,8 @@
|
||||
#include "ngram.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include "trie.h"
|
||||
|
||||
@@ -72,12 +70,10 @@ Ngram::Ngram(size_t capacity, const Param& param) : param_(param) {
|
||||
|
||||
trie_ = std::make_unique<Trie>(capacity, param_);
|
||||
|
||||
quit_flag_ = false;
|
||||
insert_worker_ = std::thread(&Ngram::insertWorker, this);
|
||||
}
|
||||
|
||||
Ngram::~Ngram() {
|
||||
quit_flag_ = true;
|
||||
insert_queue_.close();
|
||||
if (insert_worker_.joinable()) {
|
||||
insert_worker_.join();
|
||||
@@ -85,25 +81,31 @@ Ngram::~Ngram() {
|
||||
}
|
||||
|
||||
void Ngram::synchronize() const {
|
||||
while (!insert_queue_.empty()) {
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(10));
|
||||
}
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
sync_cv_.wait(lock, [this] { return pending_count_ == 0; });
|
||||
}
|
||||
|
||||
void Ngram::asyncInsert(std::vector<std::vector<int32_t>>&& tokens) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
pending_count_ += tokens.size();
|
||||
}
|
||||
for (auto&& token : tokens) {
|
||||
insert_queue_.enqueue(std::move(token));
|
||||
}
|
||||
}
|
||||
|
||||
void Ngram::insertWorker() {
|
||||
while (!quit_flag_) {
|
||||
for (;;) {
|
||||
std::vector<int32_t> data;
|
||||
if (!insert_queue_.dequeue(data)) {
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
trie_->insert(data.data(), data.size());
|
||||
--pending_count_;
|
||||
lock.unlock();
|
||||
sync_cv_.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <condition_variable>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
@@ -18,8 +19,14 @@ class Ngram {
|
||||
std::unique_ptr<Trie> trie_;
|
||||
Param param_;
|
||||
|
||||
// NOTE: protects trie_ and pending_count_. Ensures batchMatch never reads
|
||||
// trie_ while insertWorker is writing. After synchronize(), no pending
|
||||
// inserts remain so mutex_ contention is effectively zero.
|
||||
mutable std::mutex mutex_;
|
||||
bool quit_flag_ = false;
|
||||
mutable std::condition_variable sync_cv_;
|
||||
// NOTE: tracks inserts from enqueue through trie_->insert() completion,
|
||||
// not just queue occupancy. A dequeued item may still be mid-insert.
|
||||
size_t pending_count_ = 0;
|
||||
utils::Queue<std::vector<int32_t>> insert_queue_;
|
||||
std::thread insert_worker_;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user