Module: ThreadSafe::Util::Volatile

Included in:
AtomicReferenceCacheBackend, AtomicReferenceCacheBackend::Node, CheapLockable, Striped64
Defined in:
lib/thread_safe/util/volatile.rb

Instance Method Summary collapse

Instance Method Details

#attr_volatile(*attr_names) ⇒ Object

Provides +volatile+ (in the JVM's sense) attribute accessors implemented atop of the +AtomicReference+s.

Usage: class Foo extend ThreadSafe::Util::Volatile attr_volatile :foo, :bar

def initialize(bar)
  super() # must super() into parent initializers before using the volatile attribute accessors
  self.bar = bar
end

def hello
  my_foo = foo # volatile read
  self.foo = 1 # volatile write
  cas_foo(1, 2) # => true | a strong CAS
end

end

[View source]

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/thread_safe/util/volatile.rb', line 23

def attr_volatile(*attr_names)
  return if attr_names.empty?
  include(Module.new do
    atomic_ref_setup = attr_names.map {|attr_name| "@__#{attr_name} = ThreadSafe::Util::AtomicReference.new"}
    initialize_copy_setup = attr_names.zip(atomic_ref_setup).map do |attr_name, ref_setup|
      "#{ref_setup}(other.instance_variable_get(:@__#{attr_name}).get)"
    end
    class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
      def initialize(*)
        super
        #{atomic_ref_setup.join('; ')}
      end

      def initialize_copy(other)
        super
        #{initialize_copy_setup.join('; ')}
      end
    RUBY_EVAL

    attr_names.each do |attr_name|
      class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
        def #{attr_name}
          @__#{attr_name}.get
        end

        def #{attr_name}=(value)
          @__#{attr_name}.set(value)
        end

        def compare_and_set_#{attr_name}(old_value, new_value)
          @__#{attr_name}.compare_and_set(old_value, new_value)
        end
      RUBY_EVAL

      alias_method :"cas_#{attr_name}", :"compare_and_set_#{attr_name}"
      alias_method :"lazy_set_#{attr_name}", :"#{attr_name}="
    end
  end)
end