| 90 | |
| 91 | |
| 92 | void* CPartFileHashThread::Entry() |
| 93 | { |
| 94 | m_bRun = true; |
| 95 | |
| 96 | AddDebugLogLineN(logPartFile, wxT("Hash thread: started")); |
| 97 | |
| 98 | while (m_bRun) |
| 99 | { |
| 100 | // Move queued jobs to a local work list under the lock. |
| 101 | // Mirrors CPartFileWriteThread's pattern: minimise lock hold |
| 102 | // time so the main thread can keep enqueueing. |
| 103 | std::list<HashJob> workList; |
| 104 | { |
| 105 | wxMutexLocker lock(m_mutex); |
| 106 | if (m_bRun && !m_bWorkPending) { |
| 107 | m_condition.WaitTimeout(500); |
| 108 | } |
| 109 | m_bWorkPending = false; |
| 110 | workList.swap(m_jobList); |
| 111 | } |
| 112 | |
| 113 | for (std::list<HashJob>::iterator it = workList.begin(); |
| 114 | it != workList.end() && m_bRun; ++it) |
| 115 | { |
| 116 | const uint64 startTick = GetTickCount64(); |
| 117 | |
| 118 | // CPartFile::m_pendingHashes was incremented before enqueue |
| 119 | // and is the gate that ~CPartFile waits on, so the file |
| 120 | // pointer is guaranteed valid here. |
| 121 | // |
| 122 | // Lock m_hpartfileMutex against CPartFileWriteThread: with |
| 123 | // ENABLE_MMAP=OFF, HashSinglePart's CFileArea::ReadAt does |
| 124 | // Seek+Read on the same fd that the write thread does |
| 125 | // Seek+Write on for FlushAt; concurrent execution races |
| 126 | // on the fd's file position. The quiescent guard at |
| 127 | // enqueue time only gates dispatch — it does not prevent |
| 128 | // writes from resuming while the hash thread is still |
| 129 | // chewing through a backlog (e.g. user pause → drain → |
| 130 | // resume mid-drain). See CPartFile::m_hpartfileMutex. |
| 131 | bool ok; |
| 132 | { |
| 133 | std::lock_guard<std::mutex> lock(it->pFile->m_hpartfileMutex); |
| 134 | ok = it->pFile->HashSinglePart(it->partNumber); |
| 135 | } |
| 136 | //uint32 shall be enough time to hash a file |
| 137 | const uint32 elapsedMs = GetTickCount64() - startTick; |
| 138 | |
| 139 | AddDebugLogLineN(logPartFile, CFormat( |
| 140 | "Hash thread: part %u %s in %u ms for '%s'") |
| 141 | % it->partNumber |
| 142 | % (ok ? wxT("ok") : wxT("CORRUPT")) |
| 143 | % elapsedMs |
| 144 | % it->pFile->GetFileName()); |
| 145 | // Silence the unused-variable warning in release builds, where |
| 146 | // AddDebugLogLineN above compiles to a no-op. Caught on lint |
| 147 | // as clang-analyzer-deadcode.DeadStores. |
| 148 | wxUnusedVar(elapsedMs); |
| 149 |
nothing calls this directly
no test coverage detected