code: def engine(func):
      
      func = _make_coroutine_wrapper(func, replace_callback=False)
  
      @functools.wraps(func)
      def wrapper(*args, **kwargs):
          future = func(*args, **kwargs)
  
          def final_callback(future):
              if future.result() is not None:
                  raise ReturnValueIgnoredError(
                      "@gen.engine functions cannot return values: %r" %
                      (future.result(),))
          # The engine interface doesn't give us any way to return
          # errors but to raise them into the stack context.
          # Save the stack context here to use when the Future has resolved.
          future.add_done_callback(stack_context.wrap(final_callback))
      return wrapper
docs: Callback-oriented decorator for asynchronous generators.
  
      This is an older interface; for new code that does not need to be
      compatible with versions of Tornado older than 3.0 the
      `coroutine` decorator is recommended instead.
  
      This decorator is similar to `coroutine`, except it does not
      return a `.Future` and the ``callback`` argument is not treated
      specially.
  
      In most cases, functions decorated with `engine` should take
      a ``callback`` argument and invoke it with their result when
      they are finished.  One notable exception is the
      `~tornado.web.RequestHandler` :ref:`HTTP verb methods <verbs>`,
      which use ``self.finish()`` in place of a callback argument.