Class: RuboCop::Cop::ThreadSafety::LazySynchronizationPrimitive

Inherits:
Base
  • Object
show all
Defined in:
lib/rubocop/cop/thread_safety/lazy_synchronization_primitive.rb

Overview

Avoid lazily initializing synchronization primitives with ||=.

The check-then-set performed by ||= is not atomic, so concurrent threads can observe an uninitialized primitive or create more than one instance. Eagerly assign the primitive (for example in initialize) or use a constant.

Examples:

# bad
def mutex
  @mutex ||= Mutex.new
end

# bad
def mutex = @mutex ||= Mutex.new

# good
def initialize
  @mutex = Mutex.new
end

Constant Summary collapse

MSG =
'Do not lazily initialize synchronization primitives with `||=`.'

Instance Method Summary collapse

Instance Method Details

#lazy_shared_variable_assignment?(node) ⇒ Object



30
31
32
# File 'lib/rubocop/cop/thread_safety/lazy_synchronization_primitive.rb', line 30

def_node_matcher :lazy_shared_variable_assignment?, "(or_asgn ${ivasgn cvasgn} _)\n"

#on_or_asgn(node) ⇒ Object



42
43
44
45
46
47
48
49
# File 'lib/rubocop/cop/thread_safety/lazy_synchronization_primitive.rb', line 42

def on_or_asgn(node)
  return unless lazy_shared_variable_assignment?(node)
  return unless synchronization_primitive?(node.rhs)
  return unless method_definition?(node)
  return if synchronized?(node)

  add_offense(node)
end

#synchronization_primitive?(node) ⇒ Object



35
36
37
38
39
40
# File 'lib/rubocop/cop/thread_safety/lazy_synchronization_primitive.rb', line 35

def_node_matcher :synchronization_primitive?, "{\n  (send (const {nil? cbase} {:Mutex :Monitor}) :new ...)\n  (send (const (const nil? :Thread) :Mutex) :new ...)\n}\n"