26
26
27
27
"""
28
28
import random
29
+ import threading
29
30
30
31
from jmespath import lexer
31
32
from jmespath .compat import with_repr_method
@@ -74,6 +75,7 @@ class Parser(object):
74
75
# _CACHE dict.
75
76
_CACHE = {}
76
77
_MAX_SIZE = 128
78
+ _CACHE_LOCK = threading .Lock ()
77
79
78
80
def __init__ (self , lookahead = 2 ):
79
81
self .tokenizer = None
@@ -87,7 +89,7 @@ def parse(self, expression):
87
89
return cached
88
90
parsed_result = self ._do_parse (expression )
89
91
self ._CACHE [expression ] = parsed_result
90
- if len ( self ._CACHE ) > self . _MAX_SIZE :
92
+ if self ._is_cache_full () :
91
93
self ._free_cache_entries ()
92
94
return parsed_result
93
95
@@ -488,9 +490,15 @@ def _raise_parse_error_maybe_eof(self, expected_type, token):
488
490
raise exceptions .ParseError (
489
491
lex_position , actual_value , actual_type , message )
490
492
493
+ def _is_cache_full (self ):
494
+ return len (self ._CACHE ) > self ._MAX_SIZE
495
+
491
496
def _free_cache_entries (self ):
492
- for key in random .sample (list (self ._CACHE .keys ()), int (self ._MAX_SIZE / 2 )):
493
- self ._CACHE .pop (key , None )
497
+ with self ._CACHE_LOCK :
498
+ if self ._is_cache_full ():
499
+ cache_keys = list (self ._CACHE .keys ())
500
+ for key in random .sample (cache_keys , int (len (self ._CACHE )/ 2 )):
501
+ self ._CACHE .pop (key , None )
494
502
495
503
@classmethod
496
504
def purge (cls ):
0 commit comments