#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); } } std::forward_list Bucket::find_prefix(std::string_view search_term) const { const auto group = groups_.find(search_term.front()); if (group == groups_.cend()) { return {}; } std::forward_list result; for (const auto *word : group->second) { if (word->starts_with(search_term)) { result.push_front(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(); } } std::forward_list BucketFinder::find_prefix(std::string_view search_term) const { std::forward_list 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); result.merge(thread_result); } }); } for (auto &thread : search_threads) { thread.join(); } return result; };