| 153 | } |
| 154 | |
| 155 | void ThreadPool::threadMain(int thread_id, int device_id, bool set_affinity, const std::string& name) { |
| 156 | setThreadName(name.c_str()); |
| 157 | try { |
| 158 | DeviceGuard g(device_id); |
| 159 | #if NVML_ENABLED |
| 160 | if (set_affinity) { |
| 161 | const char* env_affinity = std::getenv("NVIMGCODEC_AFFINITY_MASK"); |
| 162 | int core = -1; |
| 163 | if (env_affinity) { |
| 164 | const auto& vec = string_split(env_affinity, ','); |
| 165 | if ((size_t)thread_id < vec.size()) { |
| 166 | core = std::stoi(vec[thread_id]); |
| 167 | } else { |
| 168 | NVIMGCODEC_LOG_WARNING(Logger::get_default(), |
| 169 | "NVIMGCODEC environment variable is set, " |
| 170 | "but does not have enough entries: thread_id (", |
| 171 | thread_id, ") vs #entries (", vec.size(), "). Ignoring..."); |
| 172 | } |
| 173 | } |
| 174 | nvml::SetCPUAffinity(core); |
| 175 | } |
| 176 | #endif |
| 177 | } catch (std::exception& e) { |
| 178 | tl_errors_[thread_id].push(e.what()); |
| 179 | } catch (...) { |
| 180 | tl_errors_[thread_id].push("Caught unknown exception"); |
| 181 | } |
| 182 | |
| 183 | while (running_) { |
| 184 | // Block on the condition to wait for work |
| 185 | std::unique_lock<std::mutex> lock(mutex_); |
| 186 | condition_.wait(lock, [this] { return !running_ || (!work_queue_.empty() && started_); }); |
| 187 | // If we're no longer running, exit the run loop |
| 188 | if (!running_) |
| 189 | break; |
| 190 | |
| 191 | // Get work from the queue & mark |
| 192 | // this thread as active |
| 193 | auto it = work_queue_.begin(); |
| 194 | |
| 195 | // if no suitable work for this thread, go to sleep |
| 196 | if (it == work_queue_.end()) |
| 197 | continue; |
| 198 | |
| 199 | Work work = std::move(*it); |
| 200 | work_queue_.erase(it); |
| 201 | ++active_threads_; |
| 202 | |
| 203 | // Unlock the lock |
| 204 | lock.unlock(); |
| 205 | |
| 206 | // If an error occurs, we save it in tl_errors_. When |
| 207 | // WaitForWork is called, we will check for any errors |
| 208 | // in the threads and return an error if one occured. |
| 209 | try { |
| 210 | work(thread_id); |
| 211 | } catch (std::exception& e) { |
| 212 | lock.lock(); |
nothing calls this directly
no test coverage detected