code: def read_locked(*args, **kwargs):
      
  
      def decorator(f):
          attr_name = kwargs.get('lock', '_lock')
  
          @six.wraps(f)
          def wrapper(self, *args, **kwargs):
              rw_lock = getattr(self, attr_name)
              with rw_lock.read_lock():
                  return f(self, *args, **kwargs)
  
          return wrapper
  
      # This is needed to handle when the decorator has args or the decorator
      # doesn't have args, python is rather weird here...
      if kwargs or not args:
          return decorator
      else:
          if len(args) == 1:
              return decorator(args[0])
          else:
              return decorator
docs: Acquires & releases a read lock around call into decorated method.
  
      NOTE(harlowja): if no attribute name is provided then by default the
      attribute named '_lock' is looked for (this attribute is expected to be
      a :py:class:`.ReaderWriterLock`) in the instance object this decorator
      is attached to.