|
from __future__ import annotations |
|
|
|
import threading |
|
|
|
|
|
class _HTTP2ProbeCache: |
|
__slots__ = ( |
|
"_lock", |
|
"_cache_locks", |
|
"_cache_values", |
|
) |
|
|
|
def __init__(self) -> None: |
|
self._lock = threading.Lock() |
|
self._cache_locks: dict[tuple[str, int], threading.RLock] = {} |
|
self._cache_values: dict[tuple[str, int], bool | None] = {} |
|
|
|
def acquire_and_get(self, host: str, port: int) -> bool | None: |
|
|
|
|
|
value = None |
|
with self._lock: |
|
key = (host, port) |
|
try: |
|
value = self._cache_values[key] |
|
|
|
if value is not None: |
|
return value |
|
except KeyError: |
|
self._cache_locks[key] = threading.RLock() |
|
self._cache_values[key] = None |
|
|
|
|
|
|
|
|
|
key_lock = self._cache_locks[key] |
|
key_lock.acquire() |
|
try: |
|
|
|
|
|
value = self._cache_values[key] |
|
|
|
|
|
except BaseException as e: |
|
assert not isinstance(e, KeyError) |
|
key_lock.release() |
|
raise |
|
|
|
return value |
|
|
|
def set_and_release( |
|
self, host: str, port: int, supports_http2: bool | None |
|
) -> None: |
|
key = (host, port) |
|
key_lock = self._cache_locks[key] |
|
with key_lock: |
|
if supports_http2 is None and self._cache_values[key] is not None: |
|
raise ValueError( |
|
"Cannot reset HTTP/2 support for origin after value has been set." |
|
) |
|
|
|
self._cache_values[key] = supports_http2 |
|
key_lock.release() |
|
|
|
def _values(self) -> dict[tuple[str, int], bool | None]: |
|
"""This function is for testing purposes only. Gets the current state of the probe cache""" |
|
with self._lock: |
|
return {k: v for k, v in self._cache_values.items()} |
|
|
|
def _reset(self) -> None: |
|
"""This function is for testing purposes only. Reset the cache values""" |
|
with self._lock: |
|
self._cache_locks = {} |
|
self._cache_values = {} |
|
|
|
|
|
_HTTP2_PROBE_CACHE = _HTTP2ProbeCache() |
|
|
|
set_and_release = _HTTP2_PROBE_CACHE.set_and_release |
|
acquire_and_get = _HTTP2_PROBE_CACHE.acquire_and_get |
|
_values = _HTTP2_PROBE_CACHE._values |
|
_reset = _HTTP2_PROBE_CACHE._reset |
|
|
|
__all__ = [ |
|
"set_and_release", |
|
"acquire_and_get", |
|
] |
|
|