| 163 | } |
| 164 | |
| 165 | void* NPar::TLocalExecutor::TImpl::HostWorkerThread(void* p) { |
| 166 | static constexpr int FAST_ITERATIONS = 200; |
| 167 | |
| 168 | auto* const ctx = (TImpl*)p; |
| 169 | TThread::SetCurrentThreadName("ParLocalExecutor"); |
| 170 | ctx->WorkerThreadId = ctx->ThreadId.fetch_add(1) + 1; |
| 171 | for (bool cont = true; cont;) { |
| 172 | TSingleJob job; |
| 173 | bool gotJob = false; |
| 174 | for (int iter = 0; iter < FAST_ITERATIONS; ++iter) { |
| 175 | if (ctx->GetJob(&job)) { |
| 176 | gotJob = true; |
| 177 | break; |
| 178 | } |
| 179 | } |
| 180 | if (!gotJob) { |
| 181 | ctx->HasJob.Reset(); |
| 182 | if (!ctx->GetJob(&job)) { |
| 183 | ctx->HasJob.Wait(); |
| 184 | continue; |
| 185 | } |
| 186 | } |
| 187 | if (job.Exec.Get()) { |
| 188 | job.Exec->LocalExec(job.Id); |
| 189 | RegularYield(); |
| 190 | } else { |
| 191 | ++ctx->QueueSize; |
| 192 | ctx->JobQueue.Enqueue(job); |
| 193 | ctx->HasJob.Signal(); |
| 194 | cont = false; |
| 195 | } |
| 196 | } |
| 197 | --ctx->ThreadCount; |
| 198 | return nullptr; |
| 199 | } |
| 200 | |
| 201 | bool NPar::TLocalExecutor::TImpl::GetJob(TSingleJob* job) { |
| 202 | if (JobQueue.Dequeue(job)) { |