void TaskRunner::_runTasks() { // We initialize cc() because ServiceContextMongoD::_newOpCtx() expects cc() to be equal to the // client used to create the operation context. Client* client = &cc(); if (AuthorizationManager::get(client->getServiceContext())->isAuthEnabled()) { AuthorizationSession::get(client)->grantInternalAuthorization(client); } ServiceContext::UniqueOperationContext opCtx; while (Task task = _waitForNextTask()) { if (!opCtx) { opCtx = client->makeOperationContext(); } NextAction nextAction = runSingleTask(task, opCtx.get(), Status::OK()); if (nextAction != NextAction::kKeepOperationContext) { opCtx.reset(); } if (nextAction == NextAction::kCancel) { break; } // Release thread back to pool after disposing if no scheduled tasks in queue. if (nextAction == NextAction::kDisposeOperationContext || nextAction == NextAction::kInvalid) { stdx::lock_guard<stdx::mutex> lk(_mutex); if (_tasks.empty()) { _finishRunTasks_inlock(); return; } } } opCtx.reset(); std::list<Task> tasks; UniqueLock lk{_mutex}; auto cancelTasks = [&]() { tasks.swap(_tasks); lk.unlock(); // Cancel remaining tasks with a CallbackCanceled status. for (auto&& task : tasks) { runSingleTask(std::move(task), nullptr, Status(ErrorCodes::CallbackCanceled, "this task has been canceled by a previously invoked task")); } tasks.clear(); }; cancelTasks(); lk.lock(); _finishRunTasks_inlock(); cancelTasks(); }
void TaskRunner::_runTasks() { Client* client = nullptr; ServiceContext::UniqueOperationContext txn; while (Task task = _waitForNextTask()) { if (!txn) { if (!client) { // We initialize cc() because ServiceContextMongoD::_newOpCtx() expects cc() // to be equal to the client used to create the operation context. Client::initThreadIfNotAlready(); client = &cc(); if (getGlobalAuthorizationManager()->isAuthEnabled()) { AuthorizationSession::get(client)->grantInternalAuthorization(); } } txn = client->makeOperationContext(); } NextAction nextAction = runSingleTask(task, txn.get(), Status::OK()); if (nextAction != NextAction::kKeepOperationContext) { txn.reset(); } if (nextAction == NextAction::kCancel) { break; } // Release thread back to pool after disposing if no scheduled tasks in queue. if (nextAction == NextAction::kDisposeOperationContext || nextAction == NextAction::kInvalid) { stdx::lock_guard<stdx::mutex> lk(_mutex); if (_tasks.empty()) { _finishRunTasks_inlock(); return; } } } txn.reset(); std::list<Task> tasks; { stdx::lock_guard<stdx::mutex> lk(_mutex); tasks.swap(_tasks); } // Cancel remaining tasks with a CallbackCanceled status. for (auto task : tasks) { runSingleTask(task, nullptr, Status(ErrorCodes::CallbackCanceled, "this task has been canceled by a previously invoked task")); } stdx::lock_guard<stdx::mutex> lk(_mutex); _finishRunTasks_inlock(); }