const std::shared_ptr& graph_task,
    std::shared_ptr graph_root,
    InputBuffer&& input_buffer) {
initialize_device_threads_pool();
  // Lock mutex for GraphTask.
  std::unique_lock lock(graph_task->mutex_);
auto queue = ready_queue(graph_task->cpu_ready_queue_, input_buffer.device());
if (worker_device == NO_DEVICE) {
    //Regular case
  } else {
    // If worker_device is any devices (i.e. CPU, CUDA): this is a re-entrant
    //    backward call from that device.
    graph_task->owner_ = worker_device;
// Now that all the non-thread safe fields of the graph_task have been populated,
// we can enqueue it.
queue->push(NodeTask(graph_task, std::move(graph_root), std::move(input_buffer)));

if (current_depth >= max_recursion_depth_) {
  // If reached the max depth, switch to a different thread
  add_thread_pool_task(graph_task);
} else {
  ++total_depth;
  ++current_depth;
  lock.unlock();
  thread_main(graph_task);
