code: def _needs_document_lock(func: F) -> F:
      """Decorator that adds the necessary locking and post-processing
      to manipulate the session's document. Expects to decorate a
      method on ServerSession and transforms it into a coroutine
      if it wasn't already.
      """
  
      @wraps(func)
      async def _needs_document_lock_wrapper(
          self: ServerSession, *args, **kwargs
      ):
          # while we wait for and hold the lock, prevent the session
          # from being discarded. This avoids potential weirdness
          # with the session vanishing in the middle of some async
          # task.
          if self.destroyed:
              log.debug(
                  "Ignoring locked callback on already-destroyed session."
              )
              return None
          self.block_expiration()
          try:
              with await self._lock.acquire():
                  if self._pending_writes is not None:
                      raise RuntimeError(
                          "internal class invariant violated: _pending_writes "
                          + "should be None if lock is not held"
                      )
                  self._pending_writes = []
                  try:
                      result = func(self, *args, **kwargs)
                      if inspect.isawaitable(result):
                          # Note that this must not be outside of the critical section.
                          # Otherwise, the async callback will be ran without document locking.
                          result = await result
                  finally:
                      # we want to be very sure we reset this or we'll
                      # keep hitting the RuntimeError above as soon as
                      # any callback goes wrong
                      pending_writes = self._pending_writes
                      self._pending_writes = None
                  for p in pending_writes:
                      await p
              return result
          finally:
              self.unblock_expiration()
  
      return _needs_document_lock_wrapper
  
imports: from __future__ import annotations
  import logging
  import inspect
  import time
  from copy import copy
  from functools import wraps
  from typing import TYPE_CHECKING, Any, Awaitable, Callable, TypeVar
  from tornado import locks
  from ..events import ConnectionLost
  from ..util.token import generate_jwt_token
  from .callbacks import DocumentCallbackGroup
label_desc: Use image node_id 1 for calling a global function with example usage: _needs_document_lock(func) and returns: _needs_document_lock_wrapper, None, result