static void done(double ms, ImplicitString config, ImplicitString src, ImplicitString srcOptions, ImplicitString name, ImplicitString note, ImplicitString log) { SkString id = SkStringPrintf("%s %s %s %s", config.c_str(), src.c_str(), srcOptions.c_str(), name.c_str()); { SkAutoMutexAcquire lock(gRunningAndTallyMutex); for (int i = 0; i < gRunning.count(); i++) { if (gRunning[i] == id) { gRunning.removeShuffle(i); break; } } if (!note.isEmpty()) { if (int* tally = gNoteTally.find(note)) { *tally += 1; } else { gNoteTally.set(note, 1); } } } if (!log.isEmpty()) { log.prepend("\n"); } auto pending = sk_atomic_dec(&gPending)-1; if (!FLAGS_quiet && note.isEmpty()) { SkDebugf("%s(%4d/%-4dMB %6d) %s\t%s%s", FLAGS_verbose ? "\n" : kSkOverwriteLine , sk_tools::getCurrResidentSetSizeMB() , sk_tools::getMaxResidentSetSizeMB() , pending , HumanizeMs(ms).c_str() , id.c_str() , log.c_str()); } // We write our dm.json file every once in a while in case we crash. // Notice this also handles the final dm.json when pending == 0. if (pending % 500 == 0) { JsonWriter::DumpJson(); } }
DEF_TEST(HashMap, r) { SkTHashMap<int, double> map; map.set(3, 4.0); REPORTER_ASSERT(r, map.count() == 1); REPORTER_ASSERT(r, map.approxBytesUsed() > 0); double* found = map.find(3); REPORTER_ASSERT(r, found); REPORTER_ASSERT(r, *found == 4.0); map.foreach([](int key, double* d){ *d = -key; }); REPORTER_ASSERT(r, count(map) == 1); found = map.find(3); REPORTER_ASSERT(r, found); REPORTER_ASSERT(r, *found == -3.0); REPORTER_ASSERT(r, !map.find(2)); const int N = 20; for (int i = 0; i < N; i++) { map.set(i, 2.0*i); } for (int i = 0; i < N; i++) { double* found = map.find(i); REPORTER_ASSERT(r, found); REPORTER_ASSERT(r, *found == i*2.0); } for (int i = N; i < 2*N; i++) { REPORTER_ASSERT(r, !map.find(i)); } REPORTER_ASSERT(r, map.count() == N); for (int i = 0; i < N/2; i++) { map.remove(i); } for (int i = 0; i < N; i++) { double* found = map.find(i); REPORTER_ASSERT(r, (found == nullptr) == (i < N/2)); } REPORTER_ASSERT(r, map.count() == N/2); map.reset(); REPORTER_ASSERT(r, map.count() == 0); }
int dm_main() { SetupCrashHandler(); JsonWriter::DumpJson(); // It's handy for the bots to assume this is ~never missing. SkAutoGraphics ag; SkTaskGroup::Enabler enabled(FLAGS_threads); gCreateTypefaceDelegate = &create_from_name; start_keepalive(); gather_gold(); gather_uninteresting_hashes(); if (!gather_srcs()) { return 1; } gather_sinks(); gather_tests(); gPending = gSrcs.count() * gSinks.count() + gParallelTests.count() + gSerialTests.count(); SkDebugf("%d srcs * %d sinks + %d tests == %d tasks\n", gSrcs.count(), gSinks.count(), gParallelTests.count() + gSerialTests.count(), gPending); // Kick off as much parallel work as we can, making note of any serial work we'll need to do. SkTaskGroup parallel; SkTArray<Task> serial; for (auto& sink : gSinks) for (auto& src : gSrcs) { Task task(src, sink); if (src->serial() || sink->serial()) { serial.push_back(task); } else { parallel.add([task] { Task::Run(task); }); } } for (auto test : gParallelTests) { parallel.add([test] { run_test(test); }); } // With the parallel work running, run serial tasks and tests here on main thread. for (auto task : serial) { Task::Run(task); } for (auto test : gSerialTests) { run_test(test); } // Wait for any remaining parallel work to complete (including any spun off of serial tasks). parallel.wait(); gDefinitelyThreadSafeWork.wait(); // At this point we're back in single-threaded land. sk_tool_utils::release_portable_typefaces(); if (FLAGS_verbose && gNoteTally.count() > 0) { SkDebugf("\nNote tally:\n"); gNoteTally.foreach([](const SkString& note, int* tally) { SkDebugf("%dx\t%s\n", *tally, note.c_str()); }); } SkDebugf("\n"); if (gFailures.count() > 0) { SkDebugf("Failures:\n"); for (int i = 0; i < gFailures.count(); i++) { SkDebugf("\t%s\n", gFailures[i].c_str()); } SkDebugf("%d failures\n", gFailures.count()); return 1; } if (gPending > 0) { SkDebugf("Hrm, we didn't seem to run everything we intended to! Please file a bug.\n"); return 1; } #ifdef SK_PDF_IMAGE_STATS SkPDFImageDumpStats(); #endif // SK_PDF_IMAGE_STATS SkDebugf("Finished!\n"); return 0; }
// Tests use of const foreach(). map.count() is of course the better way to do this. static int count(const SkTHashMap<int, double>& map) { int n = 0; map.foreach([&n](int, double) { n++; }); return n; }