empathy 0.0.1.RC0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.rdoc +135 -0
  5. data/Rakefile +33 -0
  6. data/TESTING.rdoc +11 -0
  7. data/empathy.gemspec +23 -0
  8. data/empathy.mspec +34 -0
  9. data/lib/empathy.rb +162 -0
  10. data/lib/empathy/em/condition_variable.rb +57 -0
  11. data/lib/empathy/em/mutex.rb +70 -0
  12. data/lib/empathy/em/queue.rb +84 -0
  13. data/lib/empathy/em/thread.rb +363 -0
  14. data/lib/empathy/object.rb +19 -0
  15. data/lib/empathy/thread.rb +8 -0
  16. data/lib/empathy/version.rb +3 -0
  17. data/mspec/lib/mspec/empathy.rb +19 -0
  18. data/mspec/lib/mspec/guards/empathy.rb +10 -0
  19. data/rubyspec/core/kernel/fixtures/__method__.rb +25 -0
  20. data/rubyspec/core/kernel/fixtures/autoload_b.rb +5 -0
  21. data/rubyspec/core/kernel/fixtures/autoload_c.rb +5 -0
  22. data/rubyspec/core/kernel/fixtures/autoload_d.rb +5 -0
  23. data/rubyspec/core/kernel/fixtures/caller_fixture1.rb +42 -0
  24. data/rubyspec/core/kernel/fixtures/caller_fixture2.rb +26 -0
  25. data/rubyspec/core/kernel/fixtures/chomp.rb +4 -0
  26. data/rubyspec/core/kernel/fixtures/chomp_f.rb +4 -0
  27. data/rubyspec/core/kernel/fixtures/chop.rb +4 -0
  28. data/rubyspec/core/kernel/fixtures/chop_f.rb +4 -0
  29. data/rubyspec/core/kernel/fixtures/classes.rb +410 -0
  30. data/rubyspec/core/kernel/fixtures/eval_locals.rb +6 -0
  31. data/rubyspec/core/kernel/fixtures/eval_return_with_lambda.rb +12 -0
  32. data/rubyspec/core/kernel/fixtures/eval_return_without_lambda.rb +14 -0
  33. data/rubyspec/core/kernel/fixtures/test.rb +362 -0
  34. data/rubyspec/core/kernel/sleep_spec.rb +43 -0
  35. data/rubyspec/core/mutex/lock_spec.rb +8 -0
  36. data/rubyspec/core/mutex/locked_spec.rb +8 -0
  37. data/rubyspec/core/mutex/sleep_spec.rb +56 -0
  38. data/rubyspec/core/mutex/synchronize_spec.rb +8 -0
  39. data/rubyspec/core/mutex/try_lock_spec.rb +8 -0
  40. data/rubyspec/core/mutex/unlock_spec.rb +8 -0
  41. data/rubyspec/core/thread/abort_on_exception_spec.rb +126 -0
  42. data/rubyspec/core/thread/add_trace_func_spec.rb +7 -0
  43. data/rubyspec/core/thread/alive_spec.rb +60 -0
  44. data/rubyspec/core/thread/allocate_spec.rb +9 -0
  45. data/rubyspec/core/thread/backtrace_spec.rb +7 -0
  46. data/rubyspec/core/thread/critical_spec.rb +96 -0
  47. data/rubyspec/core/thread/current_spec.rb +15 -0
  48. data/rubyspec/core/thread/element_reference_spec.rb +53 -0
  49. data/rubyspec/core/thread/element_set_spec.rb +46 -0
  50. data/rubyspec/core/thread/exclusive_spec.rb +20 -0
  51. data/rubyspec/core/thread/exit_spec.rb +21 -0
  52. data/rubyspec/core/thread/fixtures/classes.rb +291 -0
  53. data/rubyspec/core/thread/fork_spec.rb +9 -0
  54. data/rubyspec/core/thread/group_spec.rb +5 -0
  55. data/rubyspec/core/thread/initialize_spec.rb +26 -0
  56. data/rubyspec/core/thread/inspect_spec.rb +48 -0
  57. data/rubyspec/core/thread/join_spec.rb +63 -0
  58. data/rubyspec/core/thread/key_spec.rb +64 -0
  59. data/rubyspec/core/thread/keys_spec.rb +47 -0
  60. data/rubyspec/core/thread/kill_spec.rb +21 -0
  61. data/rubyspec/core/thread/list_spec.rb +38 -0
  62. data/rubyspec/core/thread/main_spec.rb +10 -0
  63. data/rubyspec/core/thread/new_spec.rb +56 -0
  64. data/rubyspec/core/thread/pass_spec.rb +8 -0
  65. data/rubyspec/core/thread/priority_spec.rb +9 -0
  66. data/rubyspec/core/thread/raise_spec.rb +225 -0
  67. data/rubyspec/core/thread/run_spec.rb +9 -0
  68. data/rubyspec/core/thread/safe_level_spec.rb +6 -0
  69. data/rubyspec/core/thread/set_trace_func_spec.rb +7 -0
  70. data/rubyspec/core/thread/shared/exit.rb +173 -0
  71. data/rubyspec/core/thread/shared/start.rb +51 -0
  72. data/rubyspec/core/thread/shared/wakeup.rb +59 -0
  73. data/rubyspec/core/thread/start_spec.rb +9 -0
  74. data/rubyspec/core/thread/status_spec.rb +48 -0
  75. data/rubyspec/core/thread/stop_spec.rb +66 -0
  76. data/rubyspec/core/thread/terminate_spec.rb +11 -0
  77. data/rubyspec/core/thread/value_spec.rb +36 -0
  78. data/rubyspec/core/thread/wakeup_spec.rb +7 -0
  79. data/rubyspec/empathy_spec.rb +26 -0
  80. data/rubyspec/library/conditionvariable/broadcast_spec.rb +62 -0
  81. data/rubyspec/library/conditionvariable/signal_spec.rb +64 -0
  82. data/rubyspec/library/conditionvariable/wait_spec.rb +21 -0
  83. data/rubyspec/library/mutex/lock_spec.rb +10 -0
  84. data/rubyspec/library/mutex/locked_spec.rb +10 -0
  85. data/rubyspec/library/mutex/synchronize_spec.rb +10 -0
  86. data/rubyspec/library/mutex/try_lock_spec.rb +10 -0
  87. data/rubyspec/library/mutex/unlock_spec.rb +10 -0
  88. data/rubyspec/library/queue/append_spec.rb +7 -0
  89. data/rubyspec/library/queue/clear_spec.rb +15 -0
  90. data/rubyspec/library/queue/deq_spec.rb +7 -0
  91. data/rubyspec/library/queue/empty_spec.rb +15 -0
  92. data/rubyspec/library/queue/enq_spec.rb +7 -0
  93. data/rubyspec/library/queue/length_spec.rb +7 -0
  94. data/rubyspec/library/queue/num_waiting_spec.rb +19 -0
  95. data/rubyspec/library/queue/pop_spec.rb +7 -0
  96. data/rubyspec/library/queue/push_spec.rb +7 -0
  97. data/rubyspec/library/queue/shared/deque.rb +37 -0
  98. data/rubyspec/library/queue/shared/enque.rb +10 -0
  99. data/rubyspec/library/queue/shared/length.rb +9 -0
  100. data/rubyspec/library/queue/shift_spec.rb +7 -0
  101. data/rubyspec/library/queue/size_spec.rb +7 -0
  102. data/rubyspec/shared/kernel/raise.rb +68 -0
  103. data/rubyspec/shared/mutex/lock.rb +52 -0
  104. data/rubyspec/shared/mutex/locked.rb +31 -0
  105. data/rubyspec/shared/mutex/synchronize.rb +23 -0
  106. data/rubyspec/shared/mutex/try_lock.rb +30 -0
  107. data/rubyspec/shared/mutex/unlock.rb +35 -0
  108. data/rubyspec/spec_helper.rb +48 -0
  109. data/spec/empathy_spec.rb +129 -0
  110. data/spec/library_spec.rb +79 -0
  111. data/spec/spec_helper.rb +6 -0
  112. metadata +222 -0
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in empathy.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Grant Gardner
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,135 @@
1
+ = empathy
2
+
3
+ Empathy
4
+
5
+ http://rubygems.org/gems/empathy
6
+
7
+ Make EventMachine behave like standard Ruby
8
+
9
+ == Empathic Threads
10
+
11
+ Empathy::EM module uses Fibers to provide Thread, Queue, Mutex, ConditionVariable and MonitorMixin classes that behave like the native ruby ones.
12
+
13
+ require 'eventmachine'
14
+ require 'empathy'
15
+
16
+ # start eventmachine and a main EM::Thread
17
+ Empathy.run do
18
+ thread = Empathy::EM::Thread.new do
19
+ my_thread = Empathy::EM::Thread.current
20
+
21
+ #local storage
22
+ Empathy::EM::Thread.current[:my_key] = "some value"
23
+
24
+ #pass control elsewhere
25
+ Empathy::EM::Thread.pass
26
+
27
+ Empathy::EM::Kernel.sleep(1)
28
+
29
+ 1 + 2
30
+ end
31
+
32
+ thread.join
33
+ thread.value # => 3
34
+ end
35
+
36
+ Almost all Thread behaviour is provided except that one thread will never see another as "running". Where ruby's thread API raises ThreadError, Empathy::EM will raise FiberError.
37
+
38
+ == Empathic code outside of the EventMachine reactor
39
+
40
+ If your code may run inside or outside the reactor the Empathy module itself provides a set of submodules that delegate to either the native ruby class when called outside of the reactor, or to the Empathy:EM class when called inside the reactor.
41
+
42
+ require 'eventmachine'
43
+ require 'empathy'
44
+ Empathy::Thread.current.inspect # => "Thread<...>"
45
+
46
+ # normal Kernel.sleep
47
+ Empathy::Thread.sleep(1)
48
+
49
+ Empathy.event_machine? # => false
50
+
51
+ Empathy.run do
52
+
53
+ Empathy.event_machine? # => true
54
+
55
+ Empathy::Thread.new do
56
+
57
+ Empathy::Thread.current.inspect #=> "Empathy::EM::Thread<...>"
58
+
59
+ Empathy::Kernel.sleep(1)
60
+
61
+ begin
62
+ #...do something with threads...
63
+ rescue Empathy::ThreadError
64
+ # ...
65
+ end
66
+ end
67
+ end
68
+
69
+ Note that since Empathy::Thread and friends are modules, you cannot subclass them
70
+
71
+ == Empathise with all ruby code
72
+
73
+ Seamlessly Replace Ruby's native classes with the Empathy:EM ones (redefines constants), plus monkey patching of
74
+ Object#sleep and Object#at_exit
75
+
76
+ require 'empathy/thread'
77
+ # do not run any code that uses threads outside of the reactor after the above require
78
+
79
+ Empathy.run do
80
+ t = Thread.new { 1 + 2 }
81
+
82
+ t.inspect # => "Empathy::EM::Thread<.....>"
83
+
84
+ # this will be a Fiber+EM sleep, not Kernel.sleep
85
+ sleep(4)
86
+
87
+ t.join
88
+ end
89
+
90
+ Caveat: Take care with code that subclasses Thread. This can work as long as the classes are defined after
91
+ 'empathy/thread' is required.
92
+
93
+ Q: But doesn't eventmachine need to use normal threads?
94
+ A: Indeed, 'empathy/thread' also defines constants in the EventMachine namespace that refer to the original Ruby classes
95
+
96
+ == Empathise a library module
97
+
98
+ module MyLibary
99
+ def create_thread
100
+ Thread.new { Thread.current.inspect }
101
+ end
102
+ end
103
+
104
+ # If library will only be used inside the reactor
105
+ Empathy::EM::empathise(MyLibrary)
106
+
107
+ # If library is used both inside and outside the reactor
108
+ Empathy.empathise((MyLibrary)
109
+
110
+ In both cases constants are defined in the MyLibrary namespace so that Thread, Queue etc, refer to either Empathy modules
111
+ or Empathy:EM classes. Note that any call to empathise will have the side-effect of monkey patching Object to provide EM
112
+ safe #sleep and #at_exit.
113
+
114
+ Caveat: MyLibrary must not subclass Thread etc...
115
+
116
+ == Empathy::EM::IO - Implement Ruby's Socket API over EventMachine
117
+
118
+ Work in progress - see experimental socket-io branch
119
+
120
+ == Contributing to empathy
121
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
122
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
123
+ * Fork the project
124
+ * Start a feature/bugfix branch
125
+ * Commit and push until you are happy with your contribution
126
+ * Make sure to add specs, preferably based on ruby-spec
127
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
128
+
129
+ == Copyright
130
+
131
+ Copyright (c) 2011 Christopher J. Bottaro. (Original fiber+EM concept in "strand" library)
132
+ Copyright (c) 2012,2013 Grant Gardner.
133
+
134
+ See LICENSE.txt for further details.
135
+
@@ -0,0 +1,33 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core'
4
+ require 'rspec/core/rake_task'
5
+ require 'rdoc/task'
6
+ require 'rake/clean'
7
+
8
+ RSpec::Core::RakeTask.new(:spec)
9
+
10
+ RDoc::Task.new do |rdoc|
11
+ rdoc.main = "README.rdoc"
12
+ rdoc.rdoc_files.include("README.rdoc", "CHANGELOG","lib/**/*.rb")
13
+ rdoc.title = "Empathy"
14
+ end
15
+
16
+ # Create the test task.
17
+ desc 'Run mspec'
18
+ task :mspec do
19
+ sh "mspec -B empathy.mspec -r 'mspec/empathy' -f spec"
20
+ end
21
+
22
+ # Run specs against ruby
23
+ desc "Run tests on native ruby"
24
+ task :mspec_ruby do
25
+ sh "mspec -B empathy.mspec"
26
+ end
27
+
28
+ desc "Run tests"
29
+ task :test => [ :spec, :mspec ]
30
+
31
+ task :default => [ :test, :build ]
32
+ CLOBBER.include [ "pkg/" ]
33
+
@@ -0,0 +1,11 @@
1
+ = Empathy Testing
2
+
3
+ == Empathy::EM
4
+
5
+ Classes in Empathy::EM module are tested using the fully empathic method - replacing Ruby's ::Thread constant with one that points to Empathy::EM::Thread etc, and then running against the subset of rubyspec to do with threads. The rubyspecs are not changed at all. Some tests are skipped (see *.mspec)
6
+
7
+ This also tests Empathy.run and the class replacement approach (including subclassing)
8
+
9
+ == Empathy module - reactor aware
10
+
11
+ We just test that the delegation works as expected, with explicit specs run under rspec
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'empathy/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "empathy"
8
+ gem.version = Empathy::VERSION
9
+ gem.authors = ["Grant Gardner","Christopher J. Bottaro"]
10
+ gem.email = ["grant@lastweekend.com.au"]
11
+ gem.description = %q{Empathic Eventmachine}
12
+ gem.summary = %q{Make EventMachine behave like ruby}
13
+ gem.homepage = "http://rubygems.org/gems/empathy"
14
+ gem.files = `git ls-files`.split($/)
15
+ gem.test_files = `git ls-files -- {spec,rubyspec}/*`.split($/)
16
+ gem.require_paths = ["lib"]
17
+ gem.licenses = %q{MIT}
18
+
19
+ gem.add_development_dependency 'mspec', '>= 1.5.18'
20
+ gem.add_development_dependency 'rspec'
21
+ gem.add_development_dependency 'rr'
22
+ gem.add_development_dependency 'eventmachine', '~> 1.0.0'
23
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'mspec/runner/formatters'
4
+
5
+ class MSpecScript
6
+ # An ordered list of the directories containing specs to run
7
+ set :files, ['rubyspec']
8
+
9
+ # The default implementation to run the specs.
10
+ set :target, 'ruby'
11
+
12
+ irrelevant_class_methods = [
13
+ "Thread.fork","Thread.allocate","Thread.abort_on_exception","Thread.exclusive"
14
+ ]
15
+
16
+ irrelevant_instance_methods = [
17
+ "Thread#abort_on_exception"
18
+ ]
19
+
20
+ # and some intentionally not compliant
21
+ non_compliant = [
22
+ "running","interrupt Kernel#sleep","thread group","Mutex#lock raises a ThreadError when used recursively",
23
+ ]
24
+
25
+ # Exclude IO specs not relevant to IO::Like
26
+ set :excludes, irrelevant_class_methods + irrelevant_instance_methods + non_compliant
27
+
28
+ # These are options that are passed to the ruby interpreter running the tests
29
+ # to test io like "-r io/like" must be passed on the command line to mspec
30
+ set :requires, [
31
+ "-I", File.expand_path("../lib", __FILE__),
32
+ "-I", File.expand_path("../mspec/lib", __FILE__),
33
+ ]
34
+ end
@@ -0,0 +1,162 @@
1
+ require 'empathy/version'
2
+ require 'thread'
3
+ require 'fiber'
4
+
5
+ # This module provides a shim between using standard ruby Threads
6
+ # and the thread-like behaviour for Fibers provided by classes in
7
+ # the Empathy::EM module
8
+ #
9
+ # # For the Empathy::EM classes to be available
10
+ # # you must first load EventMachine
11
+ # 'require eventmachine'
12
+ #
13
+ # 'require empathy'
14
+ #
15
+ # t = Empathy::Thread.new() do
16
+ # begin
17
+ # # "t" is a standard ::Thread
18
+ # ...something...
19
+ # end
20
+ #
21
+ # EventMachine.run do
22
+ # t = Empathy::Thread.new() do
23
+ # # "t" is a ::Empathy::EM::Thread
24
+ # # which wraps a ::Fiber
25
+ # end
26
+ # end
27
+ #
28
+ # # Outside of event machine
29
+ # t = Empathy::Thread.new() do
30
+ # # "t" is a raw ::Thread
31
+ # end
32
+ #
33
+ # Code using Empathy that may be used in both Fiber or Thread contexts
34
+ # should take care to rescue *Empathy::Errors which is shorthand for
35
+ # *[FiberError,ThreadError]
36
+ #
37
+ # def maybe_em_method
38
+ # # some code
39
+ # rescue *Empathy::Errors
40
+ #
41
+ # end
42
+ #
43
+ # {::Thread} methods not implemented by Empathy
44
+ # * #exclusive - not implemented
45
+ # * #critical - not implemented
46
+ # * #set_trace_func - not implemented
47
+ # * #safe_level - not implemented
48
+ # * #priority - not implemented
49
+ module Empathy
50
+
51
+ class ThreadError < StandardError
52
+ def self.===(other)
53
+ super || ::FiberError === other || ::ThreadError === other
54
+ end
55
+ end
56
+
57
+ # Start EventMachine and run reactor block within a surrounding Empathy::EM::Thread (Fiber).
58
+ # The reactor loop is terminated when the supplied block finishes
59
+ def self.run
60
+ reload()
61
+ exception = nil
62
+ value = nil
63
+ EventMachine.run do
64
+ EM::Thread.new do
65
+ begin
66
+ value = yield
67
+ rescue Exception => ex
68
+ exception = ex
69
+ ensure
70
+ EventMachine.stop
71
+ end
72
+ end
73
+ end
74
+ raise exception if exception
75
+ value
76
+ end
77
+
78
+ def self.empathise(*modules)
79
+ modules.each do |m|
80
+ map_classes(m, self, "Thread","Queue","Mutex","ConditionVariable", "ThreadError")
81
+ end
82
+ end
83
+
84
+ #@api private
85
+ def self.map_classes(into,from,*class_names)
86
+ # Make Object reactor aware
87
+ require 'empathy/object'
88
+ class_names.each do |cname|
89
+ case cname
90
+ when Hash
91
+ cname.each { |cn,replace_class| replace_class_constant(into,cn,replace_class) }
92
+ else
93
+ replace_class_constant(into,cname,from.const_get(cname))
94
+ end
95
+ end
96
+ end
97
+
98
+ def self.replace_class_constant(into,cname,replace_class)
99
+ if into != Object && into.const_defined?(cname,false)
100
+ existing_const = into.const_get(cname)
101
+ if !existing_const.is_a?(Module) || existing_const.name.start_with?(into.name)
102
+ warn "mmpathy: Skipping replacement of #{into.name}::#{cname}"
103
+ return nil
104
+ end
105
+ end
106
+
107
+ warn "empathy: Defined fake class constant #{into}::#{cname} => #{replace_class.name}"
108
+ into.const_set(cname,replace_class)
109
+ end
110
+
111
+ # Test whether we have real fibers or a thread based fiber implmentation
112
+ t = Thread.current
113
+ ft = nil
114
+ Fiber.new { ft = Thread.current }.resume
115
+
116
+ ROOT_FIBER = Fiber.current
117
+ REAL_FIBERS = ( t == ft )
118
+
119
+ # Specifically try to enable use of Eventmachine if it is now available
120
+ def self.reload()
121
+ @loaded ||= false
122
+ if !@loaded && defined?(EventMachine)
123
+ require 'empathy/em/thread.rb'
124
+ require 'empathy/em/queue.rb'
125
+ @loaded = true
126
+ end
127
+ return @loaded
128
+ end
129
+
130
+ # If EM already required then enable it, otherwise defer until first use
131
+ reload()
132
+
133
+ # Are we running in the EventMachine reactor thread
134
+ #
135
+ # For JRuby or other interpreters where fibers are implemented with threads
136
+ # this will return true if the reactor is running and the code is called from
137
+ # *any* fiber other than the root fiber
138
+ def self.event_machine?
139
+ @loaded ||= false
140
+ @loaded && EventMachine.reactor_running? &&
141
+ ( EventMachine.reactor_thread? || (!REAL_FIBERS && ROOT_FIBER != Fiber.current))
142
+ end
143
+
144
+ private
145
+ def self.create_delegate_module(cname,*methods)
146
+ mod = Module.new
147
+ self.const_set(cname,mod)
148
+ methods.each do |m|
149
+ mod.define_singleton_method(m) do |*args,&block|
150
+ parent = Empathy.event_machine? ? Empathy::EM : Object
151
+ delegate = parent.const_get(cname)
152
+ delegate.send(m,*args,&block)
153
+ end
154
+ end
155
+ end
156
+
157
+ create_delegate_module('Kernel',:sleep,:at_exit)
158
+ create_delegate_module('Thread',:new, :list, :current, :stop, :pass, :main)
159
+ create_delegate_module('Queue',:new)
160
+ create_delegate_module('ConditionVariable',:new)
161
+ create_delegate_module('Mutex',:new)
162
+ end