/**
* @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);
		}
	}
}
Example #3
0
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;
}
Example #4
0
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);
}
Example #5
0
bool EventBase::loopOnce(int flags) {
    return loopBody(flags | EVLOOP_ONCE);
}
Example #6
0
// enters the event_base loop -- will only exit when forced to
bool EventBase::loop() {
    return loopBody();
}
Example #7
0
bool EventBase::loopOnce() {
  return loopBody(true);
}