#include "bucket_finder.h" #include #include #include void Bucket::insert(const WordList &word_list, size_t first_index, size_t last_index) { for (size_t index = first_index; index < last_index; ++index) { const auto ¤t_word = word_list[index]; groups_[current_word.front()].push_back(¤t_word); } } WordRefList Bucket::find_prefix(std::string_view search_term) const { auto group_it = groups_.find(search_term.front()); if (group_it == groups_.cend()) { return {}; } WordRefList result; for (const auto *word : group_it->second) { if (word->starts_with(search_term)) { result.push_back(word); } } return result; } BucketFinder::BucketFinder(const WordList &word_list) { if (word_list.empty()) { return; } const size_t word_list_size = word_list.size(); const size_t bucket_count = std::min(std::thread::hardware_concurrency(), word_list_size); const size_t bucket_size = word_list_size / bucket_count; buckets_.resize(bucket_count); std::vector insert_threads; for (auto bucket_index = 0; bucket_index < bucket_count; ++bucket_index) { const size_t first_index = bucket_index * bucket_size; const size_t last_index = (bucket_index == bucket_count - 1) ? word_list_size : (bucket_index + 1) * bucket_size; auto &bucket = buckets_[bucket_index]; insert_threads.emplace_back([&bucket, &word_list, first_index, last_index] { bucket.insert(word_list, first_index, last_index); }); } for (auto &thread : insert_threads) { thread.join(); } } WordRefList BucketFinder::find_prefix(std::string_view search_term) const { WordRefList result; std::mutex result_mutex; std::vector search_threads; for (const auto &bucket : buckets_) { search_threads.emplace_back([&] { auto thread_result = bucket.find_prefix(search_term); if (!thread_result.empty()) { std::lock_guard result_lock(result_mutex); std::move(thread_result.begin(), thread_result.end(), std::back_inserter(result)); } }); } for (auto &thread : search_threads) { thread.join(); } return result; };