TODO(skyewm): make nodes in while loop unfetchable like in Python version
| 1971 | |
| 1972 | // TODO(skyewm): make nodes in while loop unfetchable like in Python version |
| 1973 | void TF_FinishWhileHelper(const TF_WhileParams* params, TF_Status* status, |
| 1974 | TF_Output* outputs) { |
| 1975 | if (!ValidateInputWhileParams(*params, status)) return; |
| 1976 | |
| 1977 | TF_Graph* parent = params->cond_graph->parent; |
| 1978 | TF_Output* parent_inputs = params->cond_graph->parent_inputs; |
| 1979 | int num_loop_vars = params->ninputs; |
| 1980 | |
| 1981 | mutex_lock l(parent->mu); |
| 1982 | |
| 1983 | // 'cond_fn' copies the cond graph into the parent graph. |
| 1984 | tensorflow::ops::CondGraphBuilderFn cond_fn = |
| 1985 | [params, parent](const tensorflow::Scope& scope, |
| 1986 | const std::vector<tensorflow::Output>& inputs, |
| 1987 | tensorflow::Output* output) { |
| 1988 | DCHECK_EQ(scope.graph(), &parent->graph); |
| 1989 | std::vector<tensorflow::Output> cond_output; |
| 1990 | TF_RETURN_IF_ERROR(CopyGraph( |
| 1991 | ¶ms->cond_graph->graph, &parent->graph, &parent->refiner, |
| 1992 | params->cond_inputs, inputs, scope.impl()->name(), |
| 1993 | scope.impl()->control_deps(), ¶ms->cond_output, |
| 1994 | /* nreturn_nodes */ 1, &cond_output)); |
| 1995 | *output = cond_output[0]; |
| 1996 | return Status::OK(); |
| 1997 | }; |
| 1998 | |
| 1999 | // 'body_fn' copies the body graph into the parent graph. |
| 2000 | tensorflow::ops::BodyGraphBuilderFn body_fn = |
| 2001 | [params, parent, num_loop_vars]( |
| 2002 | const tensorflow::Scope& scope, |
| 2003 | const std::vector<tensorflow::Output>& inputs, |
| 2004 | std::vector<tensorflow::Output>* outputs) { |
| 2005 | DCHECK_EQ(scope.graph(), &parent->graph); |
| 2006 | TF_RETURN_IF_ERROR( |
| 2007 | CopyGraph(¶ms->body_graph->graph, &parent->graph, |
| 2008 | &parent->refiner, params->body_inputs, inputs, |
| 2009 | scope.impl()->name(), scope.impl()->control_deps(), |
| 2010 | params->body_outputs, num_loop_vars, outputs)); |
| 2011 | return Status::OK(); |
| 2012 | }; |
| 2013 | |
| 2014 | // Create the while loop using an internal scope. |
| 2015 | tensorflow::Scope scope = |
| 2016 | NewInternalScope(&parent->graph, &status->status, &parent->refiner) |
| 2017 | .NewSubScope(params->name); |
| 2018 | |
| 2019 | const int first_new_node_id = parent->graph.num_node_ids(); |
| 2020 | |
| 2021 | tensorflow::OutputList loop_outputs; |
| 2022 | status->status = tensorflow::ops::BuildWhileLoop( |
| 2023 | scope, OutputsFromTFOutputs(parent_inputs, num_loop_vars), cond_fn, |
| 2024 | body_fn, params->name, &loop_outputs); |
| 2025 | |
| 2026 | // Update name_map with newly-created ops. |
| 2027 | // TODO(skyewm): right now BuildWhileLoop() may alter the graph if it returns |
| 2028 | // a bad status. Once we fix this, we may want to return early instead of |
| 2029 | // executing the following code. |
| 2030 | for (int i = first_new_node_id; i < parent->graph.num_node_ids(); ++i) { |
no test coverage detected