Module: Empathy

Defined in:
lib/empathy.rb,
lib/empathy/version.rb,
lib/empathy/em/mutex.rb,
lib/empathy/em/queue.rb,
lib/empathy/em/thread.rb,
lib/empathy/with_all_of_ruby.rb,
lib/empathy/em/condition_variable.rb

Overview

This module provides a shim between using standard ruby Threads and the thread-like behaviour for Fibers provided by classes in the EM namespace.

# For the Empathy::EM classes to be available
# you must first load EventMachine
'require eventmachine'

'require empathy'

t = Empathy::Thread.new() do
    # "t" is a standard ::Thread
    # ...something...
end

EventMachine.run do
   t = Empathy::Thread.new() do
        # "t" is a ::Empathy::EM::Thread
        # which wraps a ::Fiber
   end
end

# Outside of event machine
t = Empathy::Thread.new() do
    # "t" is a raw ::Thread
end

#Code using Empathy that may be used in both Fiber or Thread contexts
#should take care to rescue Empathy::ThreadError

def maybe_em_method
   # ...
rescue Empathy::ThreadError
   # ... will rescue either ::FiberError or ::ThreadError
end

Defined Under Namespace

Modules: ConditionVariable, EM, Kernel, Monitor, Mutex, Queue, Thread Classes: ThreadError

Constant Summary collapse

ROOT_FIBER =
Fiber.current
REAL_FIBERS =
( t == ft )
VERSION =
"0.1.0"

Class Method Summary collapse

Class Method Details

.create_delegate_module(cname, *methods) ⇒ Object

Create a module under the Empathy namespace that delegates class methods (potentially including #new) to either the top level class, or to its equivalent under the EM namespace based on being in/out of the reactor

Library authors can use this to define an eventmachine aware replacement class for their own purposes

Examples:


class MyBinding
  #...code that does not use event machine
end

module Empathy
  module EM
    class MyBinding
      # ... code that uses event machine ...
    end
  end

  create_delegate_module('MyBinding',:new, :my_class_method)
end

Parameters:

  • cname (String)

    name of the top level class or module to delegate, there must also be a class with the same name in the Empathy::EM namespace

  • methods (Array<Sumbol>)

    names of class/module methods to delegate



178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/empathy.rb', line 178

def self.create_delegate_module(cname,*methods)
  mod = Module.new
  native_mod = Object.const_get(cname)
  em_mod = Empathy::EM.const_get(cname)
  self.const_set(cname,mod)
  methods.each do |m|
    mod.define_singleton_method(m) do |*args,&block|
      delegate = Empathy.event_machine? ? em_mod : native_mod
      delegate.send(m,*args,&block)
    end
  end
  @empathic_classes << cname unless cname == 'Kernel'
end

.empathise(*modules) ⇒ void

This method returns an undefined value.

Create alias constants in each of the supplied modules so that code witin those modules will use modules from the Empathy namespace instaad of the native ruby ones

Also monkey patches Object to provide EM safe Kernel methods

Parameters:

  • modules (Array<Module>)


85
86
87
# File 'lib/empathy.rb', line 85

def self.empathise(*modules)
  modules.each { |m| map_classes(m, self) }
end

.event_machine?Boolean

Are we running in the EventMachine reactor thread

For JRuby or other interpreters where fibers are implemented with threads this will return true if the reactor is running and the code is called from any fiber other than the root fiber

Returns:

  • (Boolean)


145
146
147
148
149
# File 'lib/empathy.rb', line 145

def self.event_machine?
  @loaded ||= false
  @loaded && EventMachine.reactor_running? &&
    ( EventMachine.reactor_thread? || (!REAL_FIBERS && ROOT_FIBER != Fiber.current))
end

.reloadObject

Specifically try to enable use of Eventmachine if it is now available



127
128
129
130
131
132
133
134
135
# File 'lib/empathy.rb', line 127

def self.reload()
  @loaded ||= false
  if !@loaded && defined?(EventMachine)
    require 'empathy/em/thread.rb'
    require 'empathy/em/monitor.rb'
    @loaded = true
  end
  return @loaded
end

.runObject

Start EventMachine and run reactor block within a surrounding Empathy::EM::Thread (Fiber). The reactor loop is terminated when the supplied block finishes

Returns:

  • the value of the block



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/empathy.rb', line 60

def self.run
  reload()
  exception = nil
  value = nil
  EventMachine.run do
    EM::Thread.new do
      begin
        value = yield
      rescue Exception => ex
        exception = ex
      ensure
        EventMachine.stop
      end
    end
  end
  raise exception if exception
  value
end