Skip to content

Commit 760f530

Browse files
committed
docs(core.utils): steer callers away from the racy contains+get idiom
Add a note to ``ProgramCacheResource``'s class docstring telling callers to use ``cache.get(key)`` (or a try/except around ``cache[key]``) rather than the two-call ``if key in cache: data = cache[key]`` pattern. The two-call pattern is racy across processes: another writer's ``os.replace`` or an evictor's ``unlink`` can land between the membership check and the read. ``get`` answers both questions in one filesystem operation, so a successful return always carries the bytes. Documents the contract rather than building locks or reservations to "fix" the race -- the right fix is the recommended idiom. ``__contains__`` stays around for diagnostics and tests.
1 parent 4687a17 commit 760f530

1 file changed

Lines changed: 12 additions & 0 deletions

File tree

cuda_core/cuda/core/utils/_program_cache.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,18 @@ class ProgramCacheResource(abc.ABC):
135135
the binary alone is stored. Callers that need ``symbol_mapping``
136136
for ``get_kernel(name_expression)`` should compile fresh, or look
137137
the mangled symbol up by hand.
138+
139+
.. note:: **Concurrent-access idiom.**
140+
141+
Use :meth:`get` (or ``data = cache[key]`` inside a ``try /
142+
except KeyError``) rather than the two-call pattern ``if key
143+
in cache: data = cache[key]``. The two-call pattern is racy
144+
across processes: another writer can ``os.replace`` over the
145+
entry, or eviction can unlink it, between the membership
146+
check and the read. ``get`` answers both questions in a
147+
single filesystem-level operation, so a successful return
148+
always carries the bytes. ``__contains__`` is provided for
149+
diagnostics and tests, not for guarding reads.
138150
"""
139151

140152
@abc.abstractmethod

0 commit comments

Comments
 (0)