lib/finite_machine/threadable.rb in finite_machine-0.2.0 vs lib/finite_machine/threadable.rb in finite_machine-0.3.0

- old
+ new

@@ -5,36 +5,69 @@ # A mixin to allow instance methods to be synchronized module Threadable module InstanceMethods @@sync = Sync.new + # Exclusive lock + # + # @return [nil] + # + # @api public def sync_exclusive(&block) @@sync.synchronize(:EX, &block) end + # Shared lock + # + # @return [nil] + # + # @api public def sync_shared(&block) @@sync.synchronize(:SH, &block) end end + # Module hook + # + # @return [nil] + # + # @api private def self.included(base) base.extend ClassMethods base.module_eval do include InstanceMethods end end + private_class_method :included + module ClassMethods include InstanceMethods + # Defines threadsafe attributes for a class + # + # @example + # attr_threadable :errors, :events + # + # @example + # attr_threadable :errors, default: [] + # + # @return [nil] + # + # @api public def attr_threadsafe(*attrs) + opts = attrs.last.is_a?(::Hash) ? attrs.pop : {} + default = opts.fetch(:default, nil) attrs.flatten.each do |attr| class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 def #{attr}(*args) - if args.empty? + value = args.shift + if value + self.#{attr} = value + elsif instance_variables.include?(:@#{attr}) sync_shared { @#{attr} } - else - self.#{attr} = args.shift + elsif #{!default.nil?} + sync_shared { instance_variable_set(:@#{attr}, #{default}) } end end alias_method '#{attr}?', '#{attr}' def #{attr}=(value)