MCPcopy Create free account
hub / github.com/DFHack/dfhack / manageJobCompletedEvent

Function manageJobCompletedEvent

library/modules/EventManager.cpp:539–730  ·  view source on GitHub ↗

TODO: consider checking item creation / experience gain just in case */

Source from the content-addressed store, hash-verified

537TODO: consider checking item creation / experience gain just in case
538*/
539static void manageJobCompletedEvent(color_ostream& out) {
540 if (!df::global::world)
541 return;
542
543 multimap<Plugin*, EventHandler> copy(handlers[EventType::JOB_COMPLETED].begin(), handlers[EventType::JOB_COMPLETED].end());
544 std::vector<JobCompleteData> nowJobs;
545 // predict the size in advance, this will prevent or reduce memory reallocation.
546 nowJobs.reserve(prevJobs.size());
547 for (const auto jobPtr : df::global::world->jobs.list) {
548 auto& job = *jobPtr;
549
550 auto seenIt = seenJobs.find(job.id);
551 if (seenIt != seenJobs.end()) {
552 /*
553 * No reference here, to prevent dangling reference situation
554 * when job is re-cloned.
555 */
556 auto seenJob = seenIt->second.get();
557 // The key here is to strategically check the most important bits to reduce churn.
558 if (seenJob->flags.whole != job.flags.whole
559 || (seenJob->items.size() != job.items.size())
560 || (seenJob->general_refs.size() != job.general_refs.size())) {
561 seenIt->second = Job::JobUniquePtr(Job::cloneJobStruct(&job, true));
562 }
563 } else if (job.completion_timer != -1) {
564 // Restrict additions to seenJobs to jobs that we know have started.
565 seenJobs.emplace(job.id, Job::JobUniquePtr(Job::cloneJobStruct(&job, true)));
566 }
567 /*
568 * We still need to push back all jobs to maintain the invariant of the
569 * algorithm used with prevJobs and nowJobs.
570 *
571 * Consider a list of job IDs from the job list, including those
572 * that haven't started:
573 * 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
574 *
575 * We push back all jobs, including those that haven't started or have
576 * been assigned yet. Jobs that haven't started or finished have a
577 * completion_timer of -1.
578 *
579 * If we don't push back all jobs to the vector, we could encounter
580 * this situation:
581 *
582 * prevJob IDs (jobs with completion_timer != -1):
583 * 2, 4, 8, 10
584 *
585 * nowJobs IDs (completion_timer != -1 or had completion_timer != -1):
586 * 1, 2, 4, 8, 10
587 *
588 * In this case, Job with ID 1 has started after jobs 2, 4, 8, and 10.
589 * But, nowJobs is not greater than or equal to prevJobs because the ID
590 * 1 in nowJobs is less than the smallest ID in prevJobs,
591 * which breaks the algorithm.
592 */
593 nowJobs.emplace_back(job.id, job.completion_timer, (bool)job.flags.bits.repeat);
594 }
595
596 // Do we want this check?

Callers

nothing calls this directly

Calls 10

run_handlerFunction · 0.85
reserveMethod · 0.80
beginMethod · 0.45
endMethod · 0.45
sizeMethod · 0.45
findMethod · 0.45
getMethod · 0.45
printMethod · 0.45
eraseMethod · 0.45
swapMethod · 0.45

Tested by

no test coverage detected