Example #1
0
Replacements mergeReplacements(const Replacements &First,
                               const Replacements &Second) {
  if (First.empty() || Second.empty())
    return First.empty() ? Second : First;

  // Delta is the amount of characters that replacements from 'Second' need to
  // be shifted so that their offsets refer to the original text.
  int Delta = 0;
  Replacements Result;

  // Iterate over both sets and always add the next element (smallest total
  // Offset) from either 'First' or 'Second'. Merge that element with
  // subsequent replacements as long as they overlap. See more details in the
  // comment on MergedReplacement.
  for (auto FirstI = First.begin(), SecondI = Second.begin();
       FirstI != First.end() || SecondI != Second.end();) {
    bool NextIsFirst = SecondI == Second.end() ||
                       (FirstI != First.end() &&
                        FirstI->getOffset() < SecondI->getOffset() + Delta);
    MergedReplacement Merged(NextIsFirst ? *FirstI : *SecondI, NextIsFirst,
                             Delta);
    ++(NextIsFirst ? FirstI : SecondI);

    while ((Merged.mergeSecond() && SecondI != Second.end()) ||
           (!Merged.mergeSecond() && FirstI != First.end())) {
      auto &I = Merged.mergeSecond() ? SecondI : FirstI;
      if (Merged.endsBefore(*I))
        break;
      Merged.merge(*I);
      ++I;
    }
    Delta -= Merged.deltaFirst();
    Result.insert(Merged.asReplacement());
  }
  return Result;
}
Example #2
0
std::vector<PartialSolution*>
LHConstraintKit::solveLeastMT(std::vector<std::string> kinds, bool useDefaultSinks) {
  assert(leastSolutions.count("default"));

  PartialSolution *P = leastSolutions["default"];
  PartialSolution *DS = leastSolutions["default-sinks"];
  std::vector<PartialSolution*> ToMerge;
  for (std::vector<std::string>::iterator kind = kinds.begin(), end = kinds.end();
       kind != end; ++kind) {
    assert(lockedConstraintKinds.insert(*kind).second && "Already solved");
    assert(!leastSolutions.count(*kind));
    leastSolutions[*kind] = new PartialSolution(getOrCreateConstraintSet(*kind), false);
    ToMerge.push_back(new PartialSolution(*leastSolutions[*kind]));
  }

  // Make copy of the set of solutions for returning when we're done
  std::vector<PartialSolution*> Merged(ToMerge);

  const unsigned T = 16;
  // Now kick off up to 'T' jobs, each with a vector of merges to do
  MergeInfo MI[T];

  // Make sure all threads know the default solution:
  for (unsigned i = 0; i < T; ++i) {
    MI[i].Default = P;
    MI[i].DefaultSinks = DS;
    MI[i].useDefaultSinks = useDefaultSinks;
  }

  // And round-robin hand out merge jobs:
  unsigned TID = 0;
  while (!ToMerge.empty()) {
    MergeInfo* M = &MI[TID];
    TID = (TID + 1) % T;

    M->Mergees.push_back(ToMerge.back());
    ToMerge.pop_back();
  }

  // Finally, kick off all the threads
  // with non-empty work queues
  std::vector<pthread_t> Threads;
  for (unsigned i = 0; i < T; ++i) {
    MergeInfo *M = &MI[i];
    if (!M->Mergees.empty()) {
      pthread_t Thread;
      if (::pthread_create(&Thread, NULL, merge, M)) {
        assert(0 && "Failed to create thread!");
      }
      Threads.push_back(Thread);
    }
  }

  // Wait for them all to finish
  while (!Threads.empty()) {
    ::pthread_join(Threads.back(), NULL);
    Threads.pop_back();
  }

  return Merged;
}