module Asynchronize
Include this module to allow a declarative syntax for defining asynch methods
Defines only one method on the including class: `asynchronize`
Public Class Methods
asynchronize(*methods)
click to toggle source
Call to asynchronize a method.
This does two things 1. Creates and prepends a module <BaseName>::Asynchronized. 2. Defines each of the passed methods on that module. Additional notes: - The new methods wrap the old method within Thread.new. - Subsequent calls only add methods to the existing Module. - Will silently fail if the method has already been asynchronized
@param methods [Symbol] The methods to be asynchronized. @example To add any number of methods to be asynchronized.
asynchronize :method1, :method2, :methodn
# File lib/asynchronize.rb, line 26 def self.asynchronize(*methods) return if methods.empty? async_container = Asynchronize._get_container_for(self) Asynchronize._define_methods_on_object(methods, async_container) end
included(base)
click to toggle source
Defines the asynchronize method
# File lib/asynchronize.rb, line 8 def self.included(base) base.class_eval do ## # Call to asynchronize a method. # # This does two things # 1. Creates and prepends a module <BaseName>::Asynchronized. # 2. Defines each of the passed methods on that module. # # Additional notes: # - The new methods wrap the old method within Thread.new. # - Subsequent calls only add methods to the existing Module. # - Will silently fail if the method has already been asynchronized # # @param methods [Symbol] The methods to be asynchronized. # @example To add any number of methods to be asynchronized. # asynchronize :method1, :method2, :methodn # def self.asynchronize(*methods) return if methods.empty? async_container = Asynchronize._get_container_for(self) Asynchronize._define_methods_on_object(methods, async_container) end end end
Private Class Methods
_build_method()
click to toggle source
Build Method
This always returns the same Proc object. In it's own method for clarity.
@return [Proc] The actual asynchronous method defined.
Calls superclass method
# File lib/asynchronize.rb, line 60 def self._build_method return Proc.new do |*args, &block| return Thread.new(args, block) do |thread_args, thread_block| Thread.current[:return_value] = super(*thread_args) next thread_block.call(Thread.current[:return_value]) if thread_block Thread.current[:return_value] end end end
_define_methods_on_object(methods, obj)
click to toggle source
Define methods on object
For each method in the methods array - If method already defined, go to the next. - If method does not exist, create it and go to the next.
@param methods [Array<Symbol>] The methods to be bound. @param obj [Object] The object for the methods to be defined on.
# File lib/asynchronize.rb, line 46 def self._define_methods_on_object(methods, obj) methods.each do |method| next if obj.methods.include?(method) obj.send(:define_method, method, _build_method) end end
_get_container_for(obj)
click to toggle source
Container setup
Creates the container module that will hold our asynchronous wrappers. - If the container module is defined, return it. - If the container module is not defined, create, prepend, and return it.
@param obj [Class] The class the module should belong to. @return [Module] The already prepended module to define our methods on.
# File lib/asynchronize.rb, line 81 def self._get_container_for(obj) if obj.const_defined?('Asynchronized') return obj.const_get('Asynchronized') else async_container = obj.const_set('Asynchronized', Module.new) obj.prepend async_container return async_container end end