eventmachine 1.0.0.beta.3-x86-mingw32 → 1.0.0.beta.4.1-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. data/.gitignore +5 -0
  2. data/.yardopts +5 -1
  3. data/{docs/GNU → GNU} +0 -0
  4. data/Gemfile +1 -0
  5. data/{docs/COPYING → LICENSE} +0 -0
  6. data/README.md +109 -0
  7. data/Rakefile +8 -0
  8. data/docs/DocumentationGuidesIndex.md +27 -0
  9. data/docs/GettingStarted.md +521 -0
  10. data/docs/{ChangeLog → old/ChangeLog} +0 -0
  11. data/docs/{DEFERRABLES → old/DEFERRABLES} +0 -0
  12. data/docs/{EPOLL → old/EPOLL} +0 -0
  13. data/docs/{INSTALL → old/INSTALL} +0 -0
  14. data/docs/{KEYBOARD → old/KEYBOARD} +0 -0
  15. data/docs/{LEGAL → old/LEGAL} +0 -0
  16. data/docs/{LIGHTWEIGHT_CONCURRENCY → old/LIGHTWEIGHT_CONCURRENCY} +0 -0
  17. data/docs/{PURE_RUBY → old/PURE_RUBY} +0 -0
  18. data/docs/{RELEASE_NOTES → old/RELEASE_NOTES} +0 -0
  19. data/docs/{SMTP → old/SMTP} +0 -0
  20. data/docs/{SPAWNED_PROCESSES → old/SPAWNED_PROCESSES} +0 -0
  21. data/docs/{TODO → old/TODO} +0 -0
  22. data/eventmachine.gemspec +5 -2
  23. data/examples/guides/getting_started/01_eventmachine_echo_server.rb +18 -0
  24. data/examples/guides/getting_started/02_eventmachine_echo_server_that_recognizes_exit_command.rb +22 -0
  25. data/examples/guides/getting_started/03_simple_chat_server.rb +149 -0
  26. data/examples/guides/getting_started/04_simple_chat_server_step_one.rb +27 -0
  27. data/examples/guides/getting_started/05_simple_chat_server_step_two.rb +43 -0
  28. data/examples/guides/getting_started/06_simple_chat_server_step_three.rb +98 -0
  29. data/examples/guides/getting_started/07_simple_chat_server_step_four.rb +121 -0
  30. data/examples/guides/getting_started/08_simple_chat_server_step_five.rb +141 -0
  31. data/examples/{ex_channel.rb → old/ex_channel.rb} +3 -3
  32. data/examples/{ex_queue.rb → old/ex_queue.rb} +0 -0
  33. data/examples/{ex_tick_loop_array.rb → old/ex_tick_loop_array.rb} +0 -0
  34. data/examples/{ex_tick_loop_counter.rb → old/ex_tick_loop_counter.rb} +0 -0
  35. data/examples/{helper.rb → old/helper.rb} +0 -0
  36. data/ext/cmain.cpp +3 -3
  37. data/ext/ed.cpp +90 -15
  38. data/ext/ed.h +5 -5
  39. data/ext/em.cpp +48 -56
  40. data/ext/em.h +12 -2
  41. data/ext/extconf.rb +3 -3
  42. data/ext/fastfilereader/extconf.rb +1 -1
  43. data/ext/pipe.cpp +2 -2
  44. data/ext/project.h +1 -1
  45. data/ext/rubymain.cpp +48 -3
  46. data/ext/ssl.cpp +5 -0
  47. data/java/src/com/rubyeventmachine/EmReactor.java +2 -2
  48. data/lib/em/buftok.rb +35 -63
  49. data/lib/em/callback.rb +43 -11
  50. data/lib/em/channel.rb +21 -14
  51. data/lib/em/completion.rb +304 -0
  52. data/lib/em/connection.rb +339 -209
  53. data/lib/em/deferrable.rb +4 -0
  54. data/lib/em/deferrable/pool.rb +2 -0
  55. data/lib/em/file_watch.rb +37 -18
  56. data/lib/em/iterator.rb +42 -42
  57. data/lib/em/pool.rb +146 -0
  58. data/lib/em/process_watch.rb +5 -4
  59. data/lib/em/processes.rb +8 -4
  60. data/lib/em/protocols/httpclient.rb +22 -11
  61. data/lib/em/protocols/httpclient2.rb +15 -5
  62. data/lib/em/protocols/line_protocol.rb +2 -1
  63. data/lib/em/protocols/memcache.rb +17 -9
  64. data/lib/em/protocols/object_protocol.rb +2 -1
  65. data/lib/em/protocols/postgres3.rb +8 -9
  66. data/lib/em/protocols/smtpclient.rb +19 -11
  67. data/lib/em/protocols/smtpserver.rb +1 -1
  68. data/lib/em/protocols/stomp.rb +8 -6
  69. data/lib/em/protocols/tcptest.rb +3 -2
  70. data/lib/em/pure_ruby.rb +212 -208
  71. data/lib/em/queue.rb +22 -13
  72. data/lib/em/resolver.rb +70 -64
  73. data/lib/em/spawnable.rb +6 -3
  74. data/lib/em/streamer.rb +33 -45
  75. data/lib/em/threaded_resource.rb +90 -0
  76. data/lib/em/timers.rb +6 -2
  77. data/lib/em/version.rb +1 -1
  78. data/lib/eventmachine.rb +538 -602
  79. data/lib/jeventmachine.rb +22 -1
  80. data/tasks/package.rake +12 -2
  81. data/tasks/test.rake +1 -0
  82. data/tests/em_test_helper.rb +12 -3
  83. data/tests/test_completion.rb +177 -0
  84. data/tests/test_epoll.rb +2 -2
  85. data/tests/test_httpclient.rb +9 -9
  86. data/tests/test_httpclient2.rb +11 -9
  87. data/tests/test_ltp.rb +2 -10
  88. data/tests/test_pool.rb +128 -0
  89. data/tests/test_processes.rb +20 -2
  90. data/tests/test_queue.rb +8 -0
  91. data/tests/test_resolver.rb +1 -1
  92. data/tests/test_set_sock_opt.rb +37 -0
  93. data/tests/test_shutdown_hooks.rb +23 -0
  94. data/tests/test_threaded_resource.rb +53 -0
  95. data/tests/test_unbind_reason.rb +31 -0
  96. metadata +96 -32
  97. data/README +0 -81
  98. data/tasks/doc.rake +0 -30
@@ -25,6 +25,7 @@
25
25
 
26
26
  module EventMachine
27
27
  module Deferrable
28
+ autoload :Pool, 'em/deferrable/pool'
28
29
 
29
30
  # Specify a block to be executed if and when the Deferrable object receives
30
31
  # a status of :succeeded. See #set_deferred_status for more information.
@@ -49,6 +50,7 @@ module EventMachine
49
50
  @callbacks ||= []
50
51
  @callbacks.unshift block # << block
51
52
  end
53
+ self
52
54
  end
53
55
 
54
56
  # Cancels an outstanding callback to &block if any. Undoes the action of #callback.
@@ -74,6 +76,7 @@ module EventMachine
74
76
  @errbacks ||= []
75
77
  @errbacks.unshift block # << block
76
78
  end
79
+ self
77
80
  end
78
81
 
79
82
  # Cancels an outstanding errback to &block if any. Undoes the action of #errback.
@@ -168,6 +171,7 @@ module EventMachine
168
171
  cancel_timeout
169
172
  me = self
170
173
  @deferred_timeout = EventMachine::Timer.new(seconds) {me.fail(*args)}
174
+ self
171
175
  end
172
176
 
173
177
  # Cancels an outstanding timeout if any. Undoes the action of #timeout.
@@ -0,0 +1,2 @@
1
+ warn "EM::Deferrable::Pool is deprecated, please use EM::Pool"
2
+ EM::Deferrable::Pool = EM::Pool
@@ -1,15 +1,24 @@
1
1
  module EventMachine
2
-
3
- # This is subclassed from EventMachine::Connection for use with the file monitoring API. Read the
4
- # documentation on the instance methods of this class, and for a full explanation see EventMachine.watch_file.
2
+ # Utility class that is useful for file monitoring. Supported events are
3
+ #
4
+ # * File is modified
5
+ # * File is deleted
6
+ # * File is moved
7
+ #
8
+ # @note On Mac OS X, file watching only works when kqueue is enabled
9
+ #
10
+ # @see EventMachine.watch_file
5
11
  class FileWatch < Connection
6
- # :stopdoc:
12
+ # @private
7
13
  Cmodified = 'modified'.freeze
14
+ # @private
8
15
  Cdeleted = 'deleted'.freeze
16
+ # @private
9
17
  Cmoved = 'moved'.freeze
10
- # :startdoc:
11
18
 
12
- def receive_data(data) #:nodoc:
19
+
20
+ # @private
21
+ def receive_data(data)
13
22
  case data
14
23
  when Cmodified
15
24
  file_modified
@@ -20,35 +29,45 @@ module EventMachine
20
29
  end
21
30
  end
22
31
 
23
- # Returns the path that EventMachine::watch_file was originally called with. The current implementation
24
- # does not pick up on the new filename after a rename occurs.
32
+ # Returns the path that is being monitored.
33
+ #
34
+ # @note Current implementation does not pick up on the new filename after a rename occurs.
35
+ #
36
+ # @return [String]
37
+ # @see EventMachine.watch_file
25
38
  def path
26
39
  @path
27
40
  end
28
41
 
29
- # Should be redefined with the user's custom callback that will be fired when the file is modified.
42
+ # Will be called when the file is modified. Supposed to be redefined by subclasses.
43
+ #
44
+ # @abstract
30
45
  def file_modified
31
46
  end
32
47
 
33
- # Should be redefined with the user's custom callback that will be fired when the file is deleted.
48
+ # Will be called when the file is deleted. Supposed to be redefined by subclasses.
34
49
  # When the file is deleted, stop_watching will be called after this to make sure everything is
35
50
  # cleaned up correctly.
36
51
  #
37
- # Note that on linux (with inotify), file_deleted will not be called until all open file descriptors to
38
- # the file have been closed.
52
+ # @note On Linux (with {http://en.wikipedia.org/wiki/Inotify inotify}), this method will not be called until *all* open file descriptors to
53
+ # the file have been closed.
54
+ #
55
+ # @abstract
39
56
  def file_deleted
40
57
  end
41
58
 
42
- # Should be redefined with the user's custom callback that will be fired when the file is moved or renamed.
59
+ # Will be called when the file is moved or renamed. Supposed to be redefined by subclasses.
60
+ #
61
+ # @abstract
43
62
  def file_moved
44
63
  end
45
64
 
46
65
  # Discontinue monitoring of the file.
47
- # This involves cleaning up the underlying monitoring details with kqueue/inotify, and in turn firing unbind.
66
+ #
67
+ # This involves cleaning up the underlying monitoring details with kqueue/inotify, and in turn firing {EventMachine::Connection#unbind}.
48
68
  # This will be called automatically when a file is deleted. User code may call it as well.
49
69
  def stop_watching
50
70
  EventMachine::unwatch_filename(@signature)
51
- end
52
- end
53
-
54
- end
71
+ end # stop_watching
72
+ end # FileWatch
73
+ end # EventMachine
@@ -4,46 +4,46 @@ module EventMachine
4
4
  # Unlike ruby's built-in iterators, the end of the current iteration cycle is signaled manually,
5
5
  # instead of happening automatically after the yielded block finishes executing. For example:
6
6
  #
7
- # (0..10).each{ |num| }
7
+ # (0..10).each{ |num| }
8
8
  #
9
9
  # becomes:
10
10
  #
11
- # EM::Iterator.new(0..10).each{ |num,iter| iter.next }
11
+ # EM::Iterator.new(0..10).each{ |num,iter| iter.next }
12
12
  #
13
13
  # This is especially useful when doing asynchronous work via reactor libraries and
14
14
  # functions. For example, given a sync and async http api:
15
15
  #
16
- # response = sync_http_get(url); ...
17
- # async_http_get(url){ |response| ... }
16
+ # response = sync_http_get(url); ...
17
+ # async_http_get(url){ |response| ... }
18
18
  #
19
19
  # a synchronous iterator such as:
20
20
  #
21
- # responses = urls.map{ |url| sync_http_get(url) }
22
- # ...
23
- # puts 'all done!'
21
+ # responses = urls.map{ |url| sync_http_get(url) }
22
+ # ...
23
+ # puts 'all done!'
24
24
  #
25
25
  # could be written as:
26
26
  #
27
- # EM::Iterator.new(urls).map(proc{ |url,iter|
28
- # async_http_get(url){ |res|
29
- # iter.return(res)
30
- # }
31
- # }, proc{ |responses|
32
- # ...
33
- # puts 'all done!'
34
- # })
27
+ # EM::Iterator.new(urls).map(proc{ |url,iter|
28
+ # async_http_get(url){ |res|
29
+ # iter.return(res)
30
+ # }
31
+ # }, proc{ |responses|
32
+ # ...
33
+ # puts 'all done!'
34
+ # })
35
35
  #
36
36
  # Now, you can take advantage of the asynchronous api to issue requests in parallel. For example,
37
37
  # to fetch 10 urls at a time, simply pass in a concurrency of 10:
38
38
  #
39
- # EM::Iterator.new(urls, 10).each do |url,iter|
40
- # async_http_get(url){ iter.next }
41
- # end
39
+ # EM::Iterator.new(urls, 10).each do |url,iter|
40
+ # async_http_get(url){ iter.next }
41
+ # end
42
42
  #
43
43
  class Iterator
44
44
  # Create a new parallel async iterator with specified concurrency.
45
45
  #
46
- # i = EM::Iterator.new(1..100, 10)
46
+ # i = EM::Iterator.new(1..100, 10)
47
47
  #
48
48
  # will create an iterator over the range that processes 10 items at a time. Iteration
49
49
  # is started via #each, #map or #inject
@@ -70,17 +70,17 @@ module EventMachine
70
70
 
71
71
  # Iterate over a set of items using the specified block or proc.
72
72
  #
73
- # EM::Iterator.new(1..100).each do |num, iter|
74
- # puts num
75
- # iter.next
76
- # end
73
+ # EM::Iterator.new(1..100).each do |num, iter|
74
+ # puts num
75
+ # iter.next
76
+ # end
77
77
  #
78
78
  # An optional second proc is invoked after the iteration is complete.
79
79
  #
80
- # EM::Iterator.new(1..100).each(
81
- # proc{ |num,iter| iter.next },
82
- # proc{ puts 'all done' }
83
- # )
80
+ # EM::Iterator.new(1..100).each(
81
+ # proc{ |num,iter| iter.next },
82
+ # proc{ puts 'all done' }
83
+ # )
84
84
  #
85
85
  def each(foreach=nil, after=nil, &blk)
86
86
  raise ArgumentError, 'proc or block required for iteration' unless foreach ||= blk
@@ -136,13 +136,13 @@ module EventMachine
136
136
 
137
137
  # Collect the results of an asynchronous iteration into an array.
138
138
  #
139
- # EM::Iterator.new(%w[ pwd uptime uname date ], 2).map(proc{ |cmd,iter|
140
- # EM.system(cmd){ |output,status|
141
- # iter.return(output)
142
- # }
143
- # }, proc{ |results|
144
- # p results
145
- # })
139
+ # EM::Iterator.new(%w[ pwd uptime uname date ], 2).map(proc{ |cmd,iter|
140
+ # EM.system(cmd){ |output,status|
141
+ # iter.return(output)
142
+ # }
143
+ # }, proc{ |results|
144
+ # p results
145
+ # })
146
146
  #
147
147
  def map(foreach, after)
148
148
  index = 0
@@ -174,14 +174,14 @@ module EventMachine
174
174
 
175
175
  # Inject the results of an asynchronous iteration onto a given object.
176
176
  #
177
- # EM::Iterator.new(%w[ pwd uptime uname date ], 2).inject({}, proc{ |hash,cmd,iter|
178
- # EM.system(cmd){ |output,status|
179
- # hash[cmd] = status.exitstatus == 0 ? output.strip : nil
180
- # iter.return(hash)
181
- # }
182
- # }, proc{ |results|
183
- # p results
184
- # })
177
+ # EM::Iterator.new(%w[ pwd uptime uname date ], 2).inject({}, proc{ |hash,cmd,iter|
178
+ # EM.system(cmd){ |output,status|
179
+ # hash[cmd] = status.exitstatus == 0 ? output.strip : nil
180
+ # iter.return(hash)
181
+ # }
182
+ # }, proc{ |results|
183
+ # p results
184
+ # })
185
185
  #
186
186
  def inject(obj, foreach, after)
187
187
  each(proc{ |item,iter|
@@ -0,0 +1,146 @@
1
+ module EventMachine
2
+ # = EventMachine::Pool
3
+ #
4
+ # A simple async resource pool based on a resource and work queue. Resources
5
+ # are enqueued and work waits for resources to become available.
6
+ #
7
+ # Example:
8
+ #
9
+ # EM.run do
10
+ # pool = EM::Pool.new
11
+ # spawn = lambda { pool.add EM::HttpRequest.new('http://example.org') }
12
+ # 10.times { spawn[] }
13
+ # done, scheduled = 0, 0
14
+ #
15
+ # check = lambda do
16
+ # done += 1
17
+ # if done >= scheduled
18
+ # EM.stop
19
+ # end
20
+ # end
21
+ #
22
+ # pool.on_error { |conn| spawn[] }
23
+ #
24
+ # 100.times do
25
+ # pool.perform do |conn|
26
+ # req = conn.get :path => '/', :keepalive => true
27
+ #
28
+ # req.callback do
29
+ # p [:success, conn.object_id, i, req.response.size]
30
+ # check[]
31
+ # end
32
+ #
33
+ # req.errback { check[] }
34
+ #
35
+ # req
36
+ # end
37
+ # end
38
+ # end
39
+ #
40
+ # Resources are expected to be controlled by an object responding to a
41
+ # deferrable/completion style API with callback and errback blocks.
42
+ #
43
+ class Pool
44
+
45
+ def initialize
46
+ @resources = EM::Queue.new
47
+ @removed = []
48
+ @contents = []
49
+ @on_error = nil
50
+ end
51
+
52
+ def add resource
53
+ @contents << resource
54
+ requeue resource
55
+ end
56
+
57
+ def remove resource
58
+ @contents.delete resource
59
+ @removed << resource
60
+ end
61
+
62
+ # Returns a list for introspection purposes only. You should *NEVER* call
63
+ # modification or work oriented methods on objects in this list. A good
64
+ # example use case is periodic statistics collection against a set of
65
+ # connection resources.
66
+ #
67
+ # For example:
68
+ # pool.contents.inject(0) { |sum, connection| connection.num_bytes }
69
+ def contents
70
+ @contents.dup
71
+ end
72
+
73
+ # Define a default catch-all for when the deferrables returned by work
74
+ # blocks enter a failed state. By default all that happens is that the
75
+ # resource is returned to the pool. If on_error is defined, this block is
76
+ # responsible for re-adding the resource to the pool if it is still usable.
77
+ # In other words, it is generally assumed that on_error blocks explicitly
78
+ # handle the rest of the lifetime of the resource.
79
+ def on_error *a, &b
80
+ @on_error = EM::Callback(*a, &b)
81
+ end
82
+
83
+ # Perform a given #call-able object or block. The callable object will be
84
+ # called with a resource from the pool as soon as one is available, and is
85
+ # expected to return a deferrable.
86
+ #
87
+ # The deferrable will have callback and errback added such that when the
88
+ # deferrable enters a finished state, the object is returned to the pool.
89
+ #
90
+ # If on_error is defined, then objects are not automatically returned to the
91
+ # pool.
92
+ def perform(*a, &b)
93
+ work = EM::Callback(*a, &b)
94
+
95
+ @resources.pop do |resource|
96
+ if removed? resource
97
+ @removed.delete resource
98
+ reschedule work
99
+ else
100
+ process work, resource
101
+ end
102
+ end
103
+ end
104
+ alias reschedule perform
105
+
106
+ # A peek at the number of enqueued jobs waiting for resources
107
+ def num_waiting
108
+ @resources.num_waiting
109
+ end
110
+
111
+ # Removed will show resources in a partial pruned state. Resources in the
112
+ # removed list may not appear in the contents list if they are currently in
113
+ # use.
114
+ def removed? resource
115
+ @removed.include? resource
116
+ end
117
+
118
+ protected
119
+ def requeue resource
120
+ @resources.push resource
121
+ end
122
+
123
+ def failure resource
124
+ if @on_error
125
+ @on_error.call resource
126
+ else
127
+ requeue resource
128
+ end
129
+ end
130
+
131
+ def completion deferrable, resource
132
+ deferrable.callback { requeue resource }
133
+ deferrable.errback { failure resource }
134
+ end
135
+
136
+ def process work, resource
137
+ deferrable = work.call resource
138
+ if deferrable.kind_of?(EM::Deferrable)
139
+ completion deferrable, resource
140
+ else
141
+ raise ArgumentError, "deferrable expected from work"
142
+ end
143
+ end
144
+
145
+ end
146
+ end
@@ -3,12 +3,13 @@ module EventMachine
3
3
  # This is subclassed from EventMachine::Connection for use with the process monitoring API. Read the
4
4
  # documentation on the instance methods of this class, and for a full explanation see EventMachine.watch_process.
5
5
  class ProcessWatch < Connection
6
- # :stopdoc:
6
+ # @private
7
7
  Cfork = 'fork'.freeze
8
+ # @private
8
9
  Cexit = 'exit'.freeze
9
- # :startdoc:
10
10
 
11
- def receive_data(data) # :nodoc:
11
+ # @private
12
+ def receive_data(data)
12
13
  case data
13
14
  when Cfork
14
15
  process_forked
@@ -41,4 +42,4 @@ module EventMachine
41
42
  end
42
43
  end
43
44
 
44
- end
45
+ end
@@ -39,7 +39,8 @@ module EventMachine
39
39
  class DeferrableChildProcess < EventMachine::Connection
40
40
  include EventMachine::Deferrable
41
41
 
42
- def initialize # :nodoc:
42
+ # @private
43
+ def initialize
43
44
  super
44
45
  @data = []
45
46
  end
@@ -60,16 +61,19 @@ module EventMachine
60
61
  EventMachine.popen( cmd, DeferrableChildProcess )
61
62
  end
62
63
 
63
- def receive_data data # :nodoc:
64
+ # @private
65
+ def receive_data data
64
66
  @data << data
65
67
  end
66
68
 
67
- def unbind # :nodoc:
69
+ # @private
70
+ def unbind
68
71
  succeed( @data.join )
69
72
  end
70
73
  end
71
74
 
72
- class SystemCmd < EventMachine::Connection # :nodoc:
75
+ # @private
76
+ class SystemCmd < EventMachine::Connection
73
77
  def initialize cb
74
78
  @cb = cb
75
79
  @output = []