+ {
+ unique_lock<mutex> lock(mu);
+ queue_removed.wait(lock, [&work_queue] { return work_queue.size() < 256; }); // Allow ~2MB of data queued up.
+ work_queue.emplace_back(io_docid, last_docid, move(compressed));
+ queue_added.notify_one(); // Avoid the thundering herd.
+ }
+
+ // Pick up some results, so that we are sure that we won't just overload.
+ // (Seemingly, going through all of these causes slowness with many threads,
+ // but taking only one is OK.)
+ unsigned i = io_docid / 32;
+ deliver_results(&threads[i % num_threads], &serializer);
+ }
+ {
+ lock_guard<mutex> lock(mu);
+ done = true;
+ queue_added.notify_all();
+ }
+ for (unsigned i = 0; i < num_threads; ++i) {
+ threads[i].t.join();
+ deliver_results(&threads[i], &serializer);
+ }
+ return matched;
+}
+
+// Takes the given posting list, unions it into the parts of the trigram disjunction
+// already read; if the list is complete, intersects with “cur_candidates”.
+//
+// Returns true if the search should be aborted (we are done).
+bool new_posting_list_read(TrigramDisjunction *td, vector<uint32_t> decoded, vector<uint32_t> *cur_candidates, vector<uint32_t> *tmp)
+{
+ if (td->docids.empty()) {
+ td->docids = move(decoded);
+ } else {
+ tmp->clear();
+ set_union(decoded.begin(), decoded.end(), td->docids.begin(), td->docids.end(), back_inserter(*tmp));
+ swap(*tmp, td->docids);
+ }
+ if (--td->remaining_trigrams_to_read > 0) {
+ // Need to wait for more.
+ if (ignore_case) {
+ dprintf(" ... %u reads left in OR group %u (%zu docids in list)\n",
+ td->remaining_trigrams_to_read, td->index, td->docids.size());
+ }
+ return false;
+ }
+ if (cur_candidates->empty()) {
+ if (ignore_case) {
+ dprintf(" ... all reads done for OR group %u (%zu docids)\n",
+ td->index, td->docids.size());
+ }
+ *cur_candidates = move(td->docids);
+ } else {
+ tmp->clear();
+ set_intersection(cur_candidates->begin(), cur_candidates->end(),
+ td->docids.begin(), td->docids.end(),
+ back_inserter(*tmp));
+ swap(*cur_candidates, *tmp);
+ if (ignore_case) {
+ if (cur_candidates->empty()) {
+ dprintf(" ... all reads done for OR group %u (%zu docids), intersected (none left, search is done)\n",
+ td->index, td->docids.size());
+ return true;
+ } else {
+ dprintf(" ... all reads done for OR group %u (%zu docids), intersected (%zu left)\n",
+ td->index, td->docids.size(), cur_candidates->size());
+ }