Allow cachedproperty to avoid locking
Under some cirumstances it is ok to recompute a value when raced to by multiple threads, for these cases allow the cachedproperty to avoid needing and using a lock. Change-Id: Icb71cb5ea280185cfb120671be900435dabcd50b
This commit is contained in:
@@ -350,8 +350,11 @@ class cachedproperty(object):
|
||||
cached property would be stored under '_get_thing' in the self object
|
||||
after the first call to 'get_thing' occurs.
|
||||
"""
|
||||
def __init__(self, fget):
|
||||
self._lock = threading.RLock()
|
||||
def __init__(self, fget=None, require_lock=True):
|
||||
if require_lock:
|
||||
self._lock = threading.RLock()
|
||||
else:
|
||||
self._lock = None
|
||||
# If a name is provided (as an argument) then this will be the string
|
||||
# to place the cached attribute under if not then it will be the
|
||||
# function itself to be wrapped into a property.
|
||||
@@ -365,10 +368,12 @@ class cachedproperty(object):
|
||||
self.__doc__ = None
|
||||
|
||||
def __call__(self, fget):
|
||||
# If __init__ received a string then this will be the function to be
|
||||
# wrapped as a property (if __init__ got a function then this will not
|
||||
# be called).
|
||||
# If __init__ received a string or a lock boolean then this will be
|
||||
# the function to be wrapped as a property (if __init__ got a
|
||||
# function then this will not be called).
|
||||
self._fget = fget
|
||||
if not self._attr_name:
|
||||
self._attr_name = "_%s" % (fget.__name__)
|
||||
self.__doc__ = getattr(fget, '__doc__', None)
|
||||
return self
|
||||
|
||||
@@ -387,13 +392,17 @@ class cachedproperty(object):
|
||||
if hasattr(instance, self._attr_name):
|
||||
return getattr(instance, self._attr_name)
|
||||
else:
|
||||
with self._lock:
|
||||
try:
|
||||
return getattr(instance, self._attr_name)
|
||||
except AttributeError:
|
||||
value = self._fget(instance)
|
||||
setattr(instance, self._attr_name, value)
|
||||
return value
|
||||
if self._lock is not None:
|
||||
self._lock.acquire()
|
||||
try:
|
||||
return getattr(instance, self._attr_name)
|
||||
except AttributeError:
|
||||
value = self._fget(instance)
|
||||
setattr(instance, self._attr_name, value)
|
||||
return value
|
||||
finally:
|
||||
if self._lock is not None:
|
||||
self._lock.release()
|
||||
|
||||
|
||||
def millis_to_datetime(milliseconds):
|
||||
|
||||
Reference in New Issue
Block a user