/** * @brief Implementation of visit() for for loops. */ void RecursiveCFGBuilder::visitForOrUForLoop(ShPtr<Statement> loop, ShPtr<Statement> body) { ShPtr<CFG::Node> beforeLoopNode(currNode); // Create a node for the loop. ShPtr<CFG::Node> loopNode(new CFG::Node()); firstStmtNodeMapping[loop] = loopNode; cfg->stmtNodeMapping[loop] = loopNode; loopNode->stmts.push_back(loop); cfg->addNode(loopNode); cfg->addEdge(beforeLoopNode, loopNode); // Generate the loop's condition. // TODO // ShPtr<Expression> loopCond; // Create a node for the loop's body. ShPtr<CFG::Node> loopBody(addNode(body)); cfg->addEdge(loopNode, loopBody); // Create a node (an edge) for the loop's successor. if (ShPtr<Statement> loopSucc = loop->getSuccessor()) { ShPtr<CFG::Node> afterLoopNode(addNode(loopSucc)); cfg->addEdge(loopNode, afterLoopNode); } else { currNode = loopNode; addForwardOrBackwardEdge(loop); } }
void RecursiveCFGBuilder::visit(ShPtr<WhileLoopStmt> stmt) { ShPtr<CFG::Node> beforeLoopNode(currNode); // Create a node for the loop. ShPtr<CFG::Node> loopNode(new CFG::Node()); firstStmtNodeMapping[stmt] = loopNode; cfg->stmtNodeMapping[stmt] = loopNode; loopNode->stmts.push_back(stmt); cfg->addNode(loopNode); cfg->addEdge(beforeLoopNode, loopNode); // Create a node for the loop's body. ShPtr<CFG::Node> loopBody(addNode(stmt->getBody())); cfg->addEdge(loopNode, loopBody, stmt->getCondition()); // Create a node (an edge) for the loop's successor. However, do this only // if it is not a "while True" loop (the "False" edge is never taken). if (!isWhileTrueLoop(stmt)) { ShPtr<Expression> edgeCond(ExpressionNegater::negate(ucast<Expression>( stmt->getCondition()->clone()))); if (ShPtr<Statement> stmtSucc = stmt->getSuccessor()) { ShPtr<CFG::Node> afterLoopNode(addNode(stmtSucc)); cfg->addEdge(loopNode, afterLoopNode, edgeCond); } else { currNode = loopNode; addForwardOrBackwardEdge(stmt, edgeCond); } } }
void parfor(std::size_t idx_start, std::size_t idx_end, Lambda &&loopBody, TaskScheduler &scheduler, std::size_t blockSize = 32) { static_assert(std::is_same<void, typename std::result_of<Lambda(std::size_t)>::type>::value, "Loop body must return void"); auto loopLen = (idx_end - idx_start); //Execute short loops in serial if(loopLen < 10*blockSize) { for(std::size_t i=idx_start; i<idx_end; ++i) { loopBody(i); } return; } auto full_blocks = loopLen / blockSize; auto cleanup_start = full_blocks * blockSize + idx_start; auto Nblocks = full_blocks + ((cleanup_start < idx_end) ? 1 : 0); std::vector<std::future<void>> futs; futs.reserve(Nblocks); for (std::size_t iblock = 0; iblock < Nblocks; ++iblock) { std::size_t i_start = idx_start + iblock * blockSize; std::size_t i_end = i_start + blockSize; i_end = (i_end < idx_end) ? i_end : idx_end; auto [task, fut] = scheduler.createTask([&loopBody, i_start, i_end]() { for (auto i = i_start; i < i_end; ++i) { loopBody(i); } }); scheduler.enqueue(task); futs.push_back(std::move(fut)); } wait_all(futs); //return futs; }
bool EventBase::loopIgnoreKeepAlive() { if (loopKeepAliveActive_) { // Make sure NotificationQueue is not counted as one of the readers // (otherwise loopBody won't return until terminateLoopSoon is called). fnRunner_->stopConsuming(); fnRunner_->startConsumingInternal(this, queue_.get()); loopKeepAliveActive_ = false; } return loopBody(0, true); }
bool EventBase::loopOnce(int flags) { return loopBody(flags | EVLOOP_ONCE); }
// enters the event_base loop -- will only exit when forced to bool EventBase::loop() { return loopBody(); }
bool EventBase::loopOnce() { return loopBody(true); }