void finishRequest() { auto const threadIdx = Treadmill::threadIdx(); assert(threadIdx != -1); FTRACE(1, "tid {} finish\n", threadIdx); std::vector<std::unique_ptr<WorkItem>> toFire; { GenCountGuard g; assert(s_inflightRequests[threadIdx].startTime != kIdleGenCount); GenCount finishedRequest = s_inflightRequests[threadIdx].startTime; s_inflightRequests[threadIdx].startTime = kIdleGenCount; // After finishing a request, check to see if we've allowed any triggers // to fire and update the time of the oldest request in flight. // However if the request just finished is not the current oldest we // don't need to check anything as there cannot be any WorkItem to run. if (s_oldestRequestInFlight.load(std::memory_order_relaxed) == finishedRequest) { GenCount limit = s_latestCount + 1; for (auto& val : s_inflightRequests) { if (val.startTime != kIdleGenCount && val.startTime < limit) { limit = val.startTime; } } // update "oldest in flight" or kill it if there are no running requests s_oldestRequestInFlight = limit == s_latestCount + 1 ? 0 : limit; // collect WorkItem to run auto it = s_tq.begin(); auto end = s_tq.end(); while (it != end) { TRACE(2, "considering delendum %d\n", int((*it)->m_gen)); if ((*it)->m_gen >= limit) { TRACE(2, "not unreachable! %d\n", int((*it)->m_gen)); break; } toFire.emplace_back(std::move(*it)); it = s_tq.erase(it); } } } for (unsigned i = 0; i < toFire.size(); ++i) { toFire[i]->run(); } }
void finishRequest(int threadId) { TRACE(1, "tid %d finish\n", threadId); std::vector<WorkItem*> toFire; { GenCountGuard g; assert(*idToCount(threadId) != kIdleGenCount); *idToCount(threadId) = kIdleGenCount; // After finishing a request, check to see if we've allowed any triggers // to fire. PendingTriggers::iterator it = s_tq.begin(); PendingTriggers::iterator end = s_tq.end(); if (it != end) { GenCount gen = (*it)->m_gen; GenCount limit = s_gen + 1; for (int i = 0; i < s_maxThreadID; ++i) { if (s_inflightRequests[i] != kIdleGenCount && s_inflightRequests[i] < limit) { limit = s_inflightRequests[i]; if (limit <= gen) break; } } do { TRACE(2, "considering delendum %d\n", int((*it)->m_gen)); if ((*it)->m_gen >= limit) { TRACE(2, "not unreachable! %d\n", int((*it)->m_gen)); break; } toFire.push_back(*it); it = s_tq.erase(it); } while (it != end); } } for (unsigned i = 0; i < toFire.size(); ++i) { (*toFire[i])(); delete toFire[i]; } }