eventmachine 0.12.10 → 1.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +1 -0
  3. data/README +1 -2
  4. data/Rakefile +4 -76
  5. data/docs/DEFERRABLES +183 -70
  6. data/docs/KEYBOARD +15 -11
  7. data/docs/LIGHTWEIGHT_CONCURRENCY +84 -24
  8. data/docs/SMTP +3 -1
  9. data/docs/SPAWNED_PROCESSES +84 -25
  10. data/eventmachine.gemspec +19 -26
  11. data/examples/ex_tick_loop_array.rb +15 -0
  12. data/examples/ex_tick_loop_counter.rb +32 -0
  13. data/ext/binder.cpp +0 -1
  14. data/ext/cmain.cpp +36 -11
  15. data/ext/cplusplus.cpp +1 -1
  16. data/ext/ed.cpp +104 -113
  17. data/ext/ed.h +24 -30
  18. data/ext/em.cpp +347 -248
  19. data/ext/em.h +23 -16
  20. data/ext/eventmachine.h +5 -3
  21. data/ext/extconf.rb +5 -3
  22. data/ext/fastfilereader/extconf.rb +5 -3
  23. data/ext/fastfilereader/mapper.cpp +1 -1
  24. data/ext/kb.cpp +1 -3
  25. data/ext/pipe.cpp +9 -11
  26. data/ext/project.h +12 -4
  27. data/ext/rubymain.cpp +138 -89
  28. data/java/src/com/rubyeventmachine/EmReactor.java +1 -0
  29. data/lib/em/channel.rb +1 -1
  30. data/lib/em/connection.rb +6 -1
  31. data/lib/em/deferrable.rb +16 -2
  32. data/lib/em/iterator.rb +270 -0
  33. data/lib/em/protocols.rb +1 -1
  34. data/lib/em/protocols/httpclient.rb +5 -0
  35. data/lib/em/protocols/line_protocol.rb +28 -0
  36. data/lib/em/protocols/smtpserver.rb +101 -8
  37. data/lib/em/protocols/stomp.rb +1 -1
  38. data/lib/{pr_eventmachine.rb → em/pure_ruby.rb} +1 -11
  39. data/lib/em/queue.rb +1 -0
  40. data/lib/em/streamer.rb +1 -1
  41. data/lib/em/tick_loop.rb +85 -0
  42. data/lib/em/timers.rb +2 -1
  43. data/lib/em/version.rb +1 -1
  44. data/lib/eventmachine.rb +38 -84
  45. data/lib/jeventmachine.rb +1 -0
  46. data/tests/test_attach.rb +13 -3
  47. data/tests/test_basic.rb +60 -95
  48. data/tests/test_channel.rb +3 -2
  49. data/tests/test_defer.rb +14 -12
  50. data/tests/test_deferrable.rb +35 -0
  51. data/tests/test_file_watch.rb +1 -1
  52. data/tests/test_futures.rb +1 -1
  53. data/tests/test_hc.rb +40 -68
  54. data/tests/test_httpclient.rb +15 -6
  55. data/tests/test_httpclient2.rb +3 -2
  56. data/tests/test_inactivity_timeout.rb +3 -3
  57. data/tests/test_ltp.rb +13 -5
  58. data/tests/test_next_tick.rb +1 -1
  59. data/tests/test_pending_connect_timeout.rb +2 -2
  60. data/tests/test_process_watch.rb +36 -34
  61. data/tests/test_proxy_connection.rb +52 -0
  62. data/tests/test_pure.rb +10 -1
  63. data/tests/test_sasl.rb +1 -1
  64. data/tests/test_send_file.rb +16 -7
  65. data/tests/test_servers.rb +1 -1
  66. data/tests/test_tick_loop.rb +59 -0
  67. data/tests/test_timers.rb +13 -15
  68. metadata +45 -17
  69. data/web/whatis +0 -7
@@ -1,38 +1,42 @@
1
- EventMachine (EM) can respond to keyboard events. This gives your event-driven programs the ability to respond to input from local users.
1
+ EventMachine (EM) can respond to keyboard events. This gives your event-driven
2
+ programs the ability to respond to input from local users.
2
3
 
3
- Programming EM to handle keyboard input in Ruby is simplicity itself. Just use EventMachine#open_keyboard, and supply the name of a Ruby module or class that will receive the input:
4
+ Programming EM to handle keyboard input in Ruby is simplicity itself. Just use
5
+ EventMachine#open_keyboard, and supply the name of a Ruby module or class that
6
+ will receive the input:
4
7
 
5
8
  require 'rubygems'
6
9
  require 'eventmachine'
7
-
10
+
8
11
  module MyKeyboardHandler
9
12
  def receive_data keystrokes
10
13
  puts "I received the following data from the keyboard: #{keystrokes}"
11
14
  end
12
15
  end
13
-
16
+
14
17
  EM.run {
15
18
  EM.open_keyboard(MyKeyboardHandler)
16
19
  }
17
20
 
18
-
19
- If you want EM to send line-buffered keyboard input to your program, just include the LineText2 protocol module in your handler class or module:
20
-
21
-
21
+ If you want EM to send line-buffered keyboard input to your program, just
22
+ include the LineText2 protocol module in your handler class or module:
22
23
 
23
24
  require 'rubygems'
24
25
  require 'eventmachine'
25
-
26
+
26
27
  module MyKeyboardHandler
27
28
  include EM::Protocols::LineText2
28
29
  def receive_line data
29
30
  puts "I received the following line from the keyboard: #{data}"
30
31
  end
31
32
  end
32
-
33
+
33
34
  EM.run {
34
35
  EM.open_keyboard(MyKeyboardHandler)
35
36
  }
36
37
 
37
- As we said, simplicity itself. You can call EventMachine#open_keyboard at any time while the EM reactor loop is running. In other words, the method invocation may appear anywhere in an EventMachine#run block, or in any code invoked in the #run block.
38
+ As we said, simplicity itself. You can call EventMachine#open_keyboard at any
39
+ time while the EM reactor loop is running. In other words, the method
40
+ invocation may appear anywhere in an EventMachine#run block, or in any code
41
+ invoked in the #run block.
38
42
 
@@ -1,24 +1,43 @@
1
- EventMachine (EM) adds two different formalisms for lightweight concurrency to the Ruby programmer's toolbox: spawned processes and deferrables. This note will show you how to use them.
1
+ EventMachine (EM) adds two different formalisms for lightweight concurrency to
2
+ the Ruby programmer's toolbox: spawned processes and deferrables. This note
3
+ will show you how to use them.
2
4
 
3
5
 
4
6
  === What is Lightweight Concurrency?
5
7
 
6
- We use the term "Lightweight Concurrency" (LC) to refer to concurrency mechanisms that are lighter than Ruby threads. By "lighter," we mean: less resource-intensive in one or more dimensions, usually including memory and CPU usage. In general, you turn to LC in the hope of improving the performance and scalability of your programs.
8
+ We use the term "Lightweight Concurrency" (LC) to refer to concurrency
9
+ mechanisms that are lighter than Ruby threads. By "lighter," we mean: less
10
+ resource-intensive in one or more dimensions, usually including memory and
11
+ CPU usage. In general, you turn to LC in the hope of improving the
12
+ performance and scalability of your programs.
7
13
 
8
- In addition to the two EventMachine mechanisms we will discuss here, Ruby has at least one other LC construct: Fibers, which are currently under development in Ruby 1.9.
14
+ In addition to the two EventMachine mechanisms we will discuss here, Ruby
15
+ has at least one other LC construct: Fibers, which are currently under
16
+ development in Ruby 1.9.
9
17
 
10
- The technical feature that makes all of these LC mechanisms different from standard Ruby threads is that they are not scheduled automatically.
18
+ The technical feature that makes all of these LC mechanisms different from
19
+ standard Ruby threads is that they are not scheduled automatically.
11
20
 
12
- When you create and run Ruby threads, you can assume (within certain constraints) that your threads will all be scheduled fairly by Ruby's runtime. Ruby itself is responsible for giving each of your threads its own share of the total runtime.
21
+ When you create and run Ruby threads, you can assume (within certain
22
+ constraints) that your threads will all be scheduled fairly by Ruby's runtime.
23
+ Ruby itself is responsible for giving each of your threads its own share of
24
+ the total runtime.
13
25
 
14
- But with LC, your program is responsible for causing different execution paths to run. In effect, your program has to act as a "thread scheduler." Scheduled entities in LC run to completion and are never preempted. The runtime system has far less work to do since it has no need to interrupt threads or to schedule them fairly. This is what makes LC lighter and faster.
26
+ But with LC, your program is responsible for causing different execution
27
+ paths to run. In effect, your program has to act as a "thread scheduler."
28
+ Scheduled entities in LC run to completion and are never preempted. The
29
+ runtime system has far less work to do since it has no need to interrupt
30
+ threads or to schedule them fairly. This is what makes LC lighter and faster.
15
31
 
16
- You'll learn exactly how LC scheduling works in practice as we work through specific examples.
32
+ You'll learn exactly how LC scheduling works in practice as we work through
33
+ specific examples.
17
34
 
18
35
 
19
36
  === EventMachine Lightweight Concurrency
20
37
 
21
- Recall that EM provides a reactor loop that must be running in order for your programs to perform event-driven logic. An EM program typically has a structure like this:
38
+ Recall that EM provides a reactor loop that must be running in order for
39
+ your programs to perform event-driven logic. An EM program typically has a
40
+ structure like this:
22
41
 
23
42
  require 'eventmachine'
24
43
 
@@ -33,38 +52,79 @@ Recall that EM provides a reactor loop that must be running in order for your pr
33
52
  # end of the program
34
53
 
35
54
 
36
- EventMachine#run executes the reactor loop, which causes your code to be called as events of interest to your program occur. The block you pass to EventMachine#run is executed right after the reactor loop starts, and is the right place to start socket acceptors, etc.
55
+ EventMachine#run executes the reactor loop, which causes your code to be
56
+ called as events of interest to your program occur. The block you pass to
57
+ EventMachine#run is executed right after the reactor loop starts, and is
58
+ the right place to start socket acceptors, etc.
37
59
 
38
- Because the reactor loop runs constantly in an EM program (until it is stopped by a call to EventMachine#stop), it has the ability to schedule blocks of code for asynchronous execution. Unlike a pre-emptive thread scheduler, it's NOT able to interrupt code blocks while they execute. But the scheduling capability it does have is enough to enable lightweight concurrency.
60
+ Because the reactor loop runs constantly in an EM program (until it is
61
+ stopped by a call to EventMachine#stop), it has the ability to schedule
62
+ blocks of code for asynchronous execution. Unlike a pre-emptive thread
63
+ scheduler, it's NOT able to interrupt code blocks while they execute. But
64
+ the scheduling capability it does have is enough to enable lightweight
65
+ concurrency.
39
66
 
40
67
 
41
- For information on Spawned Processes, see the separate document SPAWNED_PROCESSES.
68
+ For information on Spawned Processes, see the separate document
69
+ SPAWNED_PROCESSES.
42
70
 
43
71
  For information on Deferrables, see the separate document DEFERRABLES.
44
72
 
45
73
 
46
74
  === [SIDEBAR]: I Heard That EventMachine Doesn't Work With Ruby Threads.
47
75
 
48
- This is incorrect. EM is fully interoperable with all versions of Ruby threads, and has been since its earliest releases.
76
+ This is incorrect. EM is fully interoperable with all versions of Ruby
77
+ threads, and has been since its earliest releases.
49
78
 
50
- It's very true that EM encourages an "evented" (non-threaded) programming style. The specific benefits of event-driven programming are far better performance and scalabiity for well-written programs, and far easier debugging.
79
+ It's very true that EM encourages an "evented" (non-threaded) programming
80
+ style. The specific benefits of event-driven programming are far better
81
+ performance and scalability for well-written programs, and far easier
82
+ debugging.
51
83
 
52
- The benefit of using threads for similar applications is a possibly more intuitive programming model, as well as the fact that threads are already familiar to most programmers. Also, bugs in threaded programs often fail to show up until programs go into production. These factors create the illusion that threaded programs are easier to write.
84
+ The benefit of using threads for similar applications is a possibly more
85
+ intuitive programming model, as well as the fact that threads are already
86
+ familiar to most programmers. Also, bugs in threaded programs often fail
87
+ to show up until programs go into production. These factors create the
88
+ illusion that threaded programs are easier to write.
53
89
 
54
- However, some operations that occur frequently in professional-caliber applications simply can't be done without threads. (The classic example is making calls to database client-libraries that block on network I/O until they complete.)
90
+ However, some operations that occur frequently in professional-caliber
91
+ applications simply can't be done without threads. (The classic example
92
+ is making calls to database client-libraries that block on network I/O
93
+ until they complete.)
55
94
 
56
- EventMachine not only allows the use of Ruby threads in these cases, but it even provides a built-in thread-pool object to make them easier to work with.
95
+ EventMachine not only allows the use of Ruby threads in these cases, but
96
+ it even provides a built-in thread-pool object to make them easier to
97
+ work with.
57
98
 
58
- You may have heard a persistent criticism that evented I/O is fundamentally incompatible with Ruby threads. It is true that some well-publicized attempts to incorporate event-handling libraries into Ruby were not successful. But EventMachine was designed from the ground up with Ruby compatibility in mind, so EM never suffered from the problems that defeated the earlier attempts.
99
+ You may have heard a persistent criticism that evented I/O is fundamentally
100
+ incompatible with Ruby threads. It is true that some well-publicized attempts
101
+ to incorporate event-handling libraries into Ruby were not successful. But
102
+ EventMachine was designed from the ground up with Ruby compatibility in mind,
103
+ so EM never suffered from the problems that defeated the earlier attempts.
59
104
 
60
105
 
61
106
  === [SIDEBAR]: I Heard That EventMachine Doesn't Work Very Well On Windows.
62
107
 
63
- This too is incorrect. EventMachine is an extension written in C++ and Java, and therefore it requires compilation. Many Windows computers (and some Unix computers, especially in production environments) don't have a build stack. Attempting to install EventMachine on a machine without a compiler usually produces a confusing error.
64
-
65
- In addition, Ruby has a much-debated issue with Windows compiler versions. Ruby on Windows works best with Visual Studio 6, a compiler version that is long out-of-print, no longer supported by Microsoft, and difficult to obtain. (This problem is not specific to EventMachine.)
66
-
67
- Shortly after EventMachine was first released, the compiler issues led to criticism that EM was incompatible with Windows. Since that time, every EventMachine release has been supplied in a precompiled binary form for Windows users, that does not require you to compile the code yourself. EM binary Gems for Windows are compiled using Visual Studio 6.
68
-
69
- EventMachine does supply some advanced features (such as Linux EPOLL support, reduced-privilege operation, UNIX-domain sockets, etc.) that have no meaningful implementation on Windows. Apart from these special cases, all EM functionality (including lightweight concurrency) works perfectly well on Windows.
108
+ This too is incorrect. EventMachine is an extension written in C++ and Java,
109
+ and therefore it requires compilation. Many Windows computers (and some Unix
110
+ computers, especially in production environments) don't have a build stack.
111
+ Attempting to install EventMachine on a machine without a compiler usually
112
+ produces a confusing error.
113
+
114
+ In addition, Ruby has a much-debated issue with Windows compiler versions.
115
+ Ruby on Windows works best with Visual Studio 6, a compiler version that is
116
+ long out-of-print, no longer supported by Microsoft, and difficult to obtain.
117
+ (This problem is not specific to EventMachine.)
118
+
119
+ Shortly after EventMachine was first released, the compiler issues led to
120
+ criticism that EM was incompatible with Windows. Since that time, every
121
+ EventMachine release has been supplied in a precompiled binary form for
122
+ Windows users, that does not require you to compile the code yourself. EM
123
+ binary Gems for Windows are compiled using Visual Studio 6.
124
+
125
+ EventMachine does supply some advanced features (such as Linux EPOLL support,
126
+ reduced-privilege operation, UNIX-domain sockets, etc.) that have no
127
+ meaningful implementation on Windows. Apart from these special cases, all EM
128
+ functionality (including lightweight concurrency) works perfectly well on
129
+ Windows.
70
130
 
data/docs/SMTP CHANGED
@@ -1,2 +1,4 @@
1
- This note details the usage of EventMachine's built-in support for SMTP. EM supports both client and server connections, which will be described in separate sections.
1
+ This note details the usage of EventMachine's built-in support for SMTP. EM
2
+ supports both client and server connections, which will be described in
3
+ separate sections.
2
4
 
@@ -1,21 +1,30 @@
1
- EventMachine (EM) adds two different formalisms for lightweight concurrency to the Ruby programmer's toolbox: spawned processes and deferrables. This note will show you how to use spawned processes. For more information, see the separate document LIGHTWEIGHT_CONCURRENCY.
1
+ EventMachine (EM) adds two different formalisms for lightweight concurrency
2
+ to the Ruby programmer's toolbox: spawned processes and deferrables. This
3
+ note will show you how to use spawned processes. For more information, see
4
+ the separate document LIGHTWEIGHT_CONCURRENCY.
2
5
 
3
6
 
4
7
  === What are Spawned Processes?
5
8
 
6
- Spawned Processes in EventMachine are inspired directly by the "processes" found in the Erlang programming language. EM deliberately borrows much (but not all) of Erlang's terminology. However, EM's spawned processes differ from Erlang's in ways that reflect not only Ruby style, but also the fact that Ruby is not a functional language like Erlang.
9
+ Spawned Processes in EventMachine are inspired directly by the "processes"
10
+ found in the Erlang programming language. EM deliberately borrows much (but
11
+ not all) of Erlang's terminology. However, EM's spawned processes differ from
12
+ Erlang's in ways that reflect not only Ruby style, but also the fact that
13
+ Ruby is not a functional language like Erlang.
7
14
 
8
- Let's proceed with a complete, working code sample that we will analyze line by line. Here's an EM implementation of the "ping-pong" program that also appears in the Erlang tutorial:
15
+ Let's proceed with a complete, working code sample that we will analyze line
16
+ by line. Here's an EM implementation of the "ping-pong" program that also
17
+ appears in the Erlang tutorial:
9
18
 
10
19
 
11
20
  require 'eventmachine'
12
-
21
+
13
22
  EM.run {
14
23
  pong = EM.spawn {|x, ping|
15
24
  puts "Pong received #{x}"
16
25
  ping.notify( x-1 )
17
26
  }
18
-
27
+
19
28
  ping = EM.spawn {|x|
20
29
  if x > 0
21
30
  puts "Pinging #{x}"
@@ -24,7 +33,7 @@ Let's proceed with a complete, working code sample that we will analyze line by
24
33
  EM.stop
25
34
  end
26
35
  }
27
-
36
+
28
37
  ping.notify 3
29
38
  }
30
39
 
@@ -39,17 +48,43 @@ If you run this program, you'll see the following output:
39
48
 
40
49
  Let's take it step by step.
41
50
 
42
- EventMachine#spawn works very much like the built-in function spawn in Erlang. It returns a reference to a Ruby object of class EventMachine::SpawnedProcess, which is actually a schedulable entity. In Erlang, the value returned from spawn is called a "process identifier" or "pid." But we'll refer to the Ruby object returned from EM#spawn simply as a "spawned process."
43
-
44
- You pass a Ruby block with zero or more parameters to EventMachine#spawn. Like all Ruby blocks, this one is a closure, so it can refer to variables defined in the local context when you call EM#spawn.
45
-
46
- However, the code block passed to EM#spawn does NOT execute immediately by default. Rather, it will execute only when the Spawned Object is "notified." In Erlang, this process is called "message passing," and is done with the operator !, but in Ruby it's done simply by calling the #notify method of a spawned-process object. The parameters you pass to #notify must match those defined in the block that was originally passed to EM#spawn.
47
-
48
- When you call the #notify method of a spawned-process object, EM's reactor core will execute the code block originally passed to EM#spawn, at some point in the future. (#notify itself merely adds a notification to the object's message queue and ALWAYS returns immediately.)
49
-
50
- When a SpawnedProcess object executes a notification, it does so in the context of the SpawnedProcess object itself. The notified code block can see local context from the point at which EM#spawn was called. However, the value of "self" inside the notified code block is a reference to the SpawnedProcesss object itself.
51
-
52
- An EM spawned process is nothing more than a Ruby object with a message queue attached to it. You can have any number of spawned processes in your program without compromising scalability. You can notify a spawned process any number of times, and each notification will cause a "message" to be placed in the queue of the spawned process. Spawned processes with non-empty message queues are scheduled for execution automatically by the EM reactor. Spawned processes with no visible references are garbage-collected like any other Ruby object.
51
+ EventMachine#spawn works very much like the built-in function spawn in
52
+ Erlang. It returns a reference to a Ruby object of class
53
+ EventMachine::SpawnedProcess, which is actually a schedulable entity. In
54
+ Erlang, the value returned from spawn is called a "process identifier" or
55
+ "pid." But we'll refer to the Ruby object returned from EM#spawn simply as a
56
+ "spawned process."
57
+
58
+ You pass a Ruby block with zero or more parameters to EventMachine#spawn.
59
+ Like all Ruby blocks, this one is a closure, so it can refer to variables
60
+ defined in the local context when you call EM#spawn.
61
+
62
+ However, the code block passed to EM#spawn does NOT execute immediately by
63
+ default. Rather, it will execute only when the Spawned Object is "notified."
64
+ In Erlang, this process is called "message passing," and is done with the
65
+ operator !, but in Ruby it's done simply by calling the #notify method of a
66
+ spawned-process object. The parameters you pass to #notify must match those
67
+ defined in the block that was originally passed to EM#spawn.
68
+
69
+ When you call the #notify method of a spawned-process object, EM's reactor
70
+ core will execute the code block originally passed to EM#spawn, at some point
71
+ in the future. (#notify itself merely adds a notification to the object's
72
+ message queue and ALWAYS returns immediately.)
73
+
74
+ When a SpawnedProcess object executes a notification, it does so in the
75
+ context of the SpawnedProcess object itself. The notified code block can see
76
+ local context from the point at which EM#spawn was called. However, the value
77
+ of "self" inside the notified code block is a reference to the SpawnedProcesss
78
+ object itself.
79
+
80
+ An EM spawned process is nothing more than a Ruby object with a message
81
+ queue attached to it. You can have any number of spawned processes in your
82
+ program without compromising scalability. You can notify a spawned process
83
+ any number of times, and each notification will cause a "message" to be
84
+ placed in the queue of the spawned process. Spawned processes with non-empty
85
+ message queues are scheduled for execution automatically by the EM reactor.
86
+ Spawned processes with no visible references are garbage-collected like any
87
+ other Ruby object.
53
88
 
54
89
  Back to our code sample:
55
90
 
@@ -58,9 +93,17 @@ Back to our code sample:
58
93
  ping.notify( x-1 )
59
94
  }
60
95
 
61
- This simply creates a spawned process and assigns it to the local variable pong. You can see that the spawned code block takes a numeric parameter and a reference to another spawned process. When pong is notified, it expects to receive arguments corresponding to these two parameters. It simply prints out the number it receives as the first argument. Then it notifies the spawned process referenced by the second argument, passing it the first argument minus 1.
96
+ This simply creates a spawned process and assigns it to the local variable
97
+ pong. You can see that the spawned code block takes a numeric parameter and a
98
+ reference to another spawned process. When pong is notified, it expects to
99
+ receive arguments corresponding to these two parameters. It simply prints out
100
+ the number it receives as the first argument. Then it notifies the spawned
101
+ process referenced by the second argument, passing it the first argument
102
+ minus 1.
62
103
 
63
- And then the block ends, which is crucial because otherwise nothing else can run. (Remember that in LC, scheduled entities run to completion and are never preempted.)
104
+ And then the block ends, which is crucial because otherwise nothing else
105
+ can run. (Remember that in LC, scheduled entities run to completion and are
106
+ never preempted.)
64
107
 
65
108
  On to the next bit of the code sample:
66
109
 
@@ -73,17 +116,33 @@ On to the next bit of the code sample:
73
116
  end
74
117
  }
75
118
 
76
- Here, we're spawning a process that takes a single (numeric) parameter. If the parameter is greater than zero, the block writes it to the console. It then notifies the spawned process referenced by the pong local variable, passing as arguments its number argument, and a reference to itself. The latter reference, as you saw above, is used by pong to send a return notification.
119
+ Here, we're spawning a process that takes a single (numeric) parameter. If
120
+ the parameter is greater than zero, the block writes it to the console. It
121
+ then notifies the spawned process referenced by the pong local variable,
122
+ passing as arguments its number argument, and a reference to itself. The
123
+ latter reference, as you saw above, is used by pong to send a return
124
+ notification.
77
125
 
78
- If the ping process receives a zero value, it will stop the reactor loop and end the program.
126
+ If the ping process receives a zero value, it will stop the reactor loop and
127
+ end the program.
79
128
 
80
- Now we've created a pair of spawned processes, but nothing else has happened. If we stop now, the program will spin in the EM reactor loop, doing nothing at all. Our spawned processes will never be scheduled for execution.
129
+ Now we've created a pair of spawned processes, but nothing else has happened.
130
+ If we stop now, the program will spin in the EM reactor loop, doing nothing
131
+ at all. Our spawned processes will never be scheduled for execution.
81
132
 
82
133
  But look at the next line in the code sample:
83
134
 
84
135
  ping.notify 3
85
136
 
86
- This line gets the ping-pong ball rolling. We call ping's #notify method, passing the argument 3. This causes a message to be sent to the ping spawned process. The message contains the single argument, and it causes the EM reactor to schedule the ping process. And this in turn results in the execution of the Ruby code block passed to EM#spawn when ping was created. Everything else proceeds as a result of the messages that are subsequently passed to each other by the spawned processes.
87
-
88
- [TODO, present the outbound network i/o use case, and clarify that spawned processes are interleaved with normal i/o operations and don't interfere with them at all. Also, blame Erlang for the confusing term "process"]
137
+ This line gets the ping-pong ball rolling. We call ping's #notify method,
138
+ passing the argument 3. This causes a message to be sent to the ping spawned
139
+ process. The message contains the single argument, and it causes the EM
140
+ reactor to schedule the ping process. And this in turn results in the
141
+ execution of the Ruby code block passed to EM#spawn when ping was created.
142
+ Everything else proceeds as a result of the messages that are subsequently
143
+ passed to each other by the spawned processes.
144
+
145
+ [TODO, present the outbound network i/o use case, and clarify that spawned
146
+ processes are interleaved with normal i/o operations and don't interfere
147
+ with them at all. Also, blame Erlang for the confusing term "process"]
89
148
 
@@ -1,13 +1,24 @@
1
1
  # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/em/version', __FILE__)
2
3
 
3
4
  Gem::Specification.new do |s|
4
- s.name = %q{eventmachine}
5
- s.version = "0.12.10"
5
+ s.date = "2010-11-13"
6
6
 
7
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
- s.authors = ["Francis Cianfrocca"]
9
- s.date = %q{2009-10-24}
10
- s.description = %q{EventMachine implements a fast, single-threaded engine for arbitrary network
7
+ s.name = 'eventmachine'
8
+ s.version = EventMachine::VERSION
9
+ s.homepage = 'http://rubyeventmachine.com'
10
+ s.rubyforge_project = 'eventmachine'
11
+
12
+ s.authors = ["Francis Cianfrocca", "Aman Gupta"]
13
+ s.email = ["garbagecat10@gmail.com", "aman@tmm1.net"]
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.extensions = ["ext/extconf.rb", "ext/fastfilereader/extconf.rb"]
17
+
18
+ s.add_development_dependency 'rake-compiler'
19
+
20
+ s.summary = 'Ruby/EventMachine library'
21
+ s.description = "EventMachine implements a fast, single-threaded engine for arbitrary network
11
22
  communications. It's extremely easy to use in Ruby. EventMachine wraps all
12
23
  interactions with IP sockets, allowing programs to concentrate on the
13
24
  implementation of network protocols. It can be used to create both network
@@ -16,25 +27,7 @@ to specify the IP address and port, and provide a Module that implements the
16
27
  communications protocol. Implementations of several standard network protocols
17
28
  are provided with the package, primarily to serve as examples. The real goal
18
29
  of EventMachine is to enable programs to easily interface with other programs
19
- using TCP/IP, especially if custom protocols are required.
20
- }
21
- s.email = %q{garbagecat10@gmail.com}
22
- s.extensions = ["ext/extconf.rb", "ext/fastfilereader/extconf.rb"]
23
- s.files = [".gitignore", "README", "Rakefile", "docs/COPYING", "docs/ChangeLog", "docs/DEFERRABLES", "docs/EPOLL", "docs/GNU", "docs/INSTALL", "docs/KEYBOARD", "docs/LEGAL", "docs/LIGHTWEIGHT_CONCURRENCY", "docs/PURE_RUBY", "docs/RELEASE_NOTES", "docs/SMTP", "docs/SPAWNED_PROCESSES", "docs/TODO", "eventmachine.gemspec", "examples/ex_channel.rb", "examples/ex_queue.rb", "examples/helper.rb", "ext/binder.cpp", "ext/binder.h", "ext/cmain.cpp", "ext/cplusplus.cpp", "ext/ed.cpp", "ext/ed.h", "ext/em.cpp", "ext/em.h", "ext/emwin.cpp", "ext/emwin.h", "ext/epoll.cpp", "ext/epoll.h", "ext/eventmachine.h", "ext/eventmachine_cpp.h", "ext/extconf.rb", "ext/fastfilereader/extconf.rb", "ext/fastfilereader/mapper.cpp", "ext/fastfilereader/mapper.h", "ext/fastfilereader/rubymain.cpp", "ext/files.cpp", "ext/files.h", "ext/kb.cpp", "ext/page.cpp", "ext/page.h", "ext/pipe.cpp", "ext/project.h", "ext/rubymain.cpp", "ext/sigs.cpp", "ext/sigs.h", "ext/ssl.cpp", "ext/ssl.h", "java/.classpath", "java/.project", "java/src/com/rubyeventmachine/EmReactor.java", "java/src/com/rubyeventmachine/EmReactorException.java", "java/src/com/rubyeventmachine/EventableChannel.java", "java/src/com/rubyeventmachine/EventableDatagramChannel.java", "java/src/com/rubyeventmachine/EventableSocketChannel.java", "java/src/com/rubyeventmachine/application/Application.java", "java/src/com/rubyeventmachine/application/Connection.java", "java/src/com/rubyeventmachine/application/ConnectionFactory.java", "java/src/com/rubyeventmachine/application/DefaultConnectionFactory.java", "java/src/com/rubyeventmachine/application/PeriodicTimer.java", "java/src/com/rubyeventmachine/application/Timer.java", "java/src/com/rubyeventmachine/tests/ApplicationTest.java", "java/src/com/rubyeventmachine/tests/ConnectTest.java", "java/src/com/rubyeventmachine/tests/EMTest.java", "java/src/com/rubyeventmachine/tests/TestDatagrams.java", "java/src/com/rubyeventmachine/tests/TestServers.java", "java/src/com/rubyeventmachine/tests/TestTimers.java", "lib/em/buftok.rb", "lib/em/callback.rb", "lib/em/channel.rb", "lib/em/connection.rb", "lib/em/deferrable.rb", "lib/em/file_watch.rb", "lib/em/future.rb", "lib/em/messages.rb", "lib/em/process_watch.rb", "lib/em/processes.rb", "lib/em/protocols.rb", "lib/em/protocols/header_and_content.rb", "lib/em/protocols/httpclient.rb", "lib/em/protocols/httpclient2.rb", "lib/em/protocols/line_and_text.rb", "lib/em/protocols/linetext2.rb", "lib/em/protocols/memcache.rb", "lib/em/protocols/object_protocol.rb", "lib/em/protocols/postgres3.rb", "lib/em/protocols/saslauth.rb", "lib/em/protocols/smtpclient.rb", "lib/em/protocols/smtpserver.rb", "lib/em/protocols/socks4.rb", "lib/em/protocols/stomp.rb", "lib/em/protocols/tcptest.rb", "lib/em/queue.rb", "lib/em/spawnable.rb", "lib/em/streamer.rb", "lib/em/timers.rb", "lib/em/version.rb", "lib/eventmachine.rb", "lib/evma.rb", "lib/evma/callback.rb", "lib/evma/container.rb", "lib/evma/factory.rb", "lib/evma/protocol.rb", "lib/evma/reactor.rb", "lib/jeventmachine.rb", "lib/pr_eventmachine.rb", "setup.rb", "tasks/cpp.rake_example", "tests/client.crt", "tests/client.key", "tests/test_attach.rb", "tests/test_basic.rb", "tests/test_channel.rb", "tests/test_connection_count.rb", "tests/test_defer.rb", "tests/test_epoll.rb", "tests/test_error_handler.rb", "tests/test_errors.rb", "tests/test_exc.rb", "tests/test_file_watch.rb", "tests/test_futures.rb", "tests/test_get_sock_opt.rb", "tests/test_handler_check.rb", "tests/test_hc.rb", "tests/test_httpclient.rb", "tests/test_httpclient2.rb", "tests/test_inactivity_timeout.rb", "tests/test_kb.rb", "tests/test_ltp.rb", "tests/test_ltp2.rb", "tests/test_next_tick.rb", "tests/test_object_protocol.rb", "tests/test_pause.rb", "tests/test_pending_connect_timeout.rb", "tests/test_process_watch.rb", "tests/test_processes.rb", "tests/test_proxy_connection.rb", "tests/test_pure.rb", "tests/test_queue.rb", "tests/test_running.rb", "tests/test_sasl.rb", "tests/test_send_file.rb", "tests/test_servers.rb", "tests/test_smtpclient.rb", "tests/test_smtpserver.rb", "tests/test_spawn.rb", "tests/test_ssl_args.rb", "tests/test_ssl_methods.rb", "tests/test_ssl_verify.rb", "tests/test_timers.rb", "tests/test_ud.rb", "tests/testem.rb", "web/whatis"]
24
- s.homepage = %q{http://rubyeventmachine.com}
25
- s.rdoc_options = ["--title", "EventMachine", "--main", "README", "--line-numbers", "-x", "lib/em/version", "-x", "lib/emva", "-x", "lib/evma/", "-x", "lib/pr_eventmachine", "-x", "lib/jeventmachine"]
26
- s.require_paths = ["lib"]
27
- s.rubyforge_project = %q{eventmachine}
28
- s.rubygems_version = %q{1.3.5}
29
- s.summary = %q{Ruby/EventMachine library}
30
-
31
- if s.respond_to? :specification_version then
32
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
33
- s.specification_version = 3
30
+ using TCP/IP, especially if custom protocols are required."
34
31
 
35
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
36
- else
37
- end
38
- else
39
- end
32
+ s.rdoc_options = ["--title", "EventMachine", "--main", "README", "-x", "lib/em/version", "-x", "lib/emva", "-x", "lib/evma/", "-x", "lib/jeventmachine"]
40
33
  end
@@ -0,0 +1,15 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ EM.run do
4
+ array = (1..100).to_a
5
+
6
+ tickloop = EM.tick_loop do
7
+ if array.empty?
8
+ :stop
9
+ else
10
+ puts array.shift
11
+ end
12
+ end
13
+
14
+ tickloop.on_stop { EM.stop }
15
+ end
@@ -0,0 +1,32 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TickCounter
4
+ attr_reader :start_time, :count
5
+
6
+ def initialize
7
+ reset
8
+ @tick_loop = EM.tick_loop(method(:tick))
9
+ end
10
+
11
+ def reset
12
+ @count = 0
13
+ @start_time = EM.current_time
14
+ end
15
+
16
+ def tick
17
+ @count += 1
18
+ end
19
+
20
+ def rate
21
+ @count / (EM.current_time - @start_time)
22
+ end
23
+ end
24
+
25
+ period = 5
26
+ EM.run do
27
+ counter = TickCounter.new
28
+ EM.add_periodic_timer(period) do
29
+ puts "Ticks per second: #{counter.rate} (mean of last #{period}s)"
30
+ counter.reset
31
+ end
32
+ end