import threading


def _link_coordinators(inner_coord, outer_coord, start=True, wait_time=5):
  """Returns a thread which stops `inner_coord` whenever `outer_coord` stops.

  The thread is also registered with `inner_coord`.

  Args:
    inner_coord: The `Coordinator` to stop.
    outer_coord: The `Coordinator` to watch for stopping.
    start: Whether to start the thread before returning.
    wait_time: The number of seconds for each `outer_coord.wait_for_stop` call.
  Returns:
    A `Thread` which links the coordinators.
  """
  def _link_thread():
    while True:
      if inner_coord.should_stop():
        # The inner coordinator is stopping, so this thread's done.
        return

      if outer_coord.wait_for_stop(wait_time):
        # The outer coordinator stopped; we should stop the inner.
        with inner_coord.stop_on_exception():
          # Causes a re-raise, but without waiting for registered threads
          outer_coord.raise_requested_exception()
          inner_coord.request_stop()
          return

  result = threading.Thread(target=_link_thread)
  inner_coord.register_thread(result)
  if start:
    result.start()
  return result