class_docstr: Decorator and context to set spill lock automatically.
  
  All calls to `get_spill_lock()` within the decorated function or context
  will return a spill lock with a lifetime bound to the function or context.
  
  Developer Notes
  ---------------
  We use the global variable `_thread_spill_locks` to track the global spill
  lock state. To support concurrency, each thread tracks its own state by
  pushing and popping from `_thread_spill_locks` using its thread ID.
class_docstr_tok: ["Decorator","and","context","to","set","spill","lock","automatically",".","All","calls","to","`","get_spill_lock","(",")","`","within","the","decorated","function","or","context","will","return","a","spill","lock","with","a","lifetime","bound","to","the","function","or","context",".","Developer","Notes","--","--","--","--","--","--","--","-","We","use","the","global","variable","`","_thread_spill_locks","`","to","track","the","global","spill","lock","state",".","To","support","concurrency",",","each","thread","tracks","its","own","state","by","pushing","and","popping","from","`","_thread_spill_locks","`","using","its","thread","ID","."]
code: def __exit__(self, *exc):
      _pop_thread_spill_lock()
  
file_path: cudf/python/cudf/cudf/core/buffer/utils.py
imports: from __future__ import annotations
  import threading
  from contextlib import ContextDecorator
  from typing import Any, Dict, Optional, Tuple, Type, Union
  from cudf.core.buffer.buffer import Buffer, BufferOwner, cuda_array_interface_wrapper, get_ptr_and_size
  from cudf.core.buffer.exposure_tracked_buffer import ExposureTrackedBuffer
  from cudf.core.buffer.spill_manager import get_global_manager
  from cudf.core.buffer.spillable_buffer import SpillableBuffer, SpillableBufferOwner, SpillLock
  from cudf.options import get_option
label_desc: Use image node_id 2 for calling the acquire_spill_lock obj's underlying member method code with example usage: obj.__exit__() without return types