smparkes-eventmachine 0.12.10
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +15 -0
- data/README +81 -0
- data/Rakefile +374 -0
- data/docs/COPYING +60 -0
- data/docs/ChangeLog +211 -0
- data/docs/DEFERRABLES +133 -0
- data/docs/EPOLL +141 -0
- data/docs/GNU +281 -0
- data/docs/INSTALL +13 -0
- data/docs/KEYBOARD +38 -0
- data/docs/LEGAL +25 -0
- data/docs/LIGHTWEIGHT_CONCURRENCY +70 -0
- data/docs/PURE_RUBY +75 -0
- data/docs/RELEASE_NOTES +94 -0
- data/docs/SMTP +2 -0
- data/docs/SPAWNED_PROCESSES +89 -0
- data/docs/TODO +8 -0
- data/eventmachine.gemspec +40 -0
- data/examples/ex_channel.rb +43 -0
- data/examples/ex_queue.rb +2 -0
- data/examples/helper.rb +2 -0
- data/ext/binder.cpp +125 -0
- data/ext/binder.h +46 -0
- data/ext/cmain.cpp +827 -0
- data/ext/cplusplus.cpp +202 -0
- data/ext/ed.cpp +1901 -0
- data/ext/ed.h +424 -0
- data/ext/em.cpp +2288 -0
- data/ext/em.h +229 -0
- data/ext/emwin.cpp +300 -0
- data/ext/emwin.h +94 -0
- data/ext/epoll.cpp +26 -0
- data/ext/epoll.h +25 -0
- data/ext/eventmachine.h +122 -0
- data/ext/eventmachine_cpp.h +96 -0
- data/ext/extconf.rb +150 -0
- data/ext/fastfilereader/extconf.rb +85 -0
- data/ext/fastfilereader/mapper.cpp +214 -0
- data/ext/fastfilereader/mapper.h +59 -0
- data/ext/fastfilereader/rubymain.cpp +127 -0
- data/ext/files.cpp +94 -0
- data/ext/files.h +65 -0
- data/ext/kb.cpp +81 -0
- data/ext/page.cpp +107 -0
- data/ext/page.h +51 -0
- data/ext/pipe.cpp +349 -0
- data/ext/project.h +156 -0
- data/ext/rubymain.cpp +1194 -0
- data/ext/sigs.cpp +89 -0
- data/ext/sigs.h +32 -0
- data/ext/ssl.cpp +460 -0
- data/ext/ssl.h +94 -0
- data/java/.classpath +8 -0
- data/java/.project +17 -0
- data/java/src/com/rubyeventmachine/EmReactor.java +570 -0
- data/java/src/com/rubyeventmachine/EmReactorException.java +40 -0
- data/java/src/com/rubyeventmachine/EventableChannel.java +69 -0
- data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +189 -0
- data/java/src/com/rubyeventmachine/EventableSocketChannel.java +364 -0
- data/java/src/com/rubyeventmachine/application/Application.java +194 -0
- data/java/src/com/rubyeventmachine/application/Connection.java +74 -0
- data/java/src/com/rubyeventmachine/application/ConnectionFactory.java +37 -0
- data/java/src/com/rubyeventmachine/application/DefaultConnectionFactory.java +46 -0
- data/java/src/com/rubyeventmachine/application/PeriodicTimer.java +38 -0
- data/java/src/com/rubyeventmachine/application/Timer.java +54 -0
- data/java/src/com/rubyeventmachine/tests/ApplicationTest.java +109 -0
- data/java/src/com/rubyeventmachine/tests/ConnectTest.java +148 -0
- data/java/src/com/rubyeventmachine/tests/EMTest.java +80 -0
- data/java/src/com/rubyeventmachine/tests/TestDatagrams.java +53 -0
- data/java/src/com/rubyeventmachine/tests/TestServers.java +75 -0
- data/java/src/com/rubyeventmachine/tests/TestTimers.java +90 -0
- data/lib/em/buftok.rb +138 -0
- data/lib/em/callback.rb +26 -0
- data/lib/em/channel.rb +57 -0
- data/lib/em/connection.rb +564 -0
- data/lib/em/deferrable.rb +192 -0
- data/lib/em/file_watch.rb +54 -0
- data/lib/em/future.rb +61 -0
- data/lib/em/messages.rb +66 -0
- data/lib/em/process_watch.rb +44 -0
- data/lib/em/processes.rb +119 -0
- data/lib/em/protocols/header_and_content.rb +138 -0
- data/lib/em/protocols/httpclient.rb +263 -0
- data/lib/em/protocols/httpclient2.rb +590 -0
- data/lib/em/protocols/line_and_text.rb +125 -0
- data/lib/em/protocols/linetext2.rb +161 -0
- data/lib/em/protocols/memcache.rb +323 -0
- data/lib/em/protocols/object_protocol.rb +45 -0
- data/lib/em/protocols/postgres3.rb +247 -0
- data/lib/em/protocols/saslauth.rb +175 -0
- data/lib/em/protocols/smtpclient.rb +357 -0
- data/lib/em/protocols/smtpserver.rb +547 -0
- data/lib/em/protocols/socks4.rb +66 -0
- data/lib/em/protocols/stomp.rb +200 -0
- data/lib/em/protocols/tcptest.rb +53 -0
- data/lib/em/protocols.rb +36 -0
- data/lib/em/queue.rb +61 -0
- data/lib/em/spawnable.rb +85 -0
- data/lib/em/streamer.rb +130 -0
- data/lib/em/timers.rb +56 -0
- data/lib/em/version.rb +3 -0
- data/lib/eventmachine.rb +1592 -0
- data/lib/evma/callback.rb +32 -0
- data/lib/evma/container.rb +75 -0
- data/lib/evma/factory.rb +77 -0
- data/lib/evma/protocol.rb +87 -0
- data/lib/evma/reactor.rb +48 -0
- data/lib/evma.rb +32 -0
- data/lib/jeventmachine.rb +257 -0
- data/lib/pr_eventmachine.rb +1022 -0
- data/setup.rb +1585 -0
- data/tasks/cpp.rake_example +77 -0
- data/tests/client.crt +31 -0
- data/tests/client.key +51 -0
- data/tests/test_attach.rb +126 -0
- data/tests/test_basic.rb +284 -0
- data/tests/test_channel.rb +63 -0
- data/tests/test_connection_count.rb +35 -0
- data/tests/test_defer.rb +47 -0
- data/tests/test_epoll.rb +160 -0
- data/tests/test_error_handler.rb +35 -0
- data/tests/test_errors.rb +82 -0
- data/tests/test_exc.rb +55 -0
- data/tests/test_file_watch.rb +49 -0
- data/tests/test_futures.rb +198 -0
- data/tests/test_get_sock_opt.rb +30 -0
- data/tests/test_handler_check.rb +37 -0
- data/tests/test_hc.rb +218 -0
- data/tests/test_httpclient.rb +218 -0
- data/tests/test_httpclient2.rb +153 -0
- data/tests/test_inactivity_timeout.rb +50 -0
- data/tests/test_kb.rb +60 -0
- data/tests/test_ltp.rb +182 -0
- data/tests/test_ltp2.rb +317 -0
- data/tests/test_next_tick.rb +133 -0
- data/tests/test_object_protocol.rb +37 -0
- data/tests/test_pause.rb +70 -0
- data/tests/test_pending_connect_timeout.rb +48 -0
- data/tests/test_process_watch.rb +48 -0
- data/tests/test_processes.rb +128 -0
- data/tests/test_proxy_connection.rb +92 -0
- data/tests/test_pure.rb +125 -0
- data/tests/test_queue.rb +44 -0
- data/tests/test_running.rb +42 -0
- data/tests/test_sasl.rb +72 -0
- data/tests/test_send_file.rb +242 -0
- data/tests/test_servers.rb +76 -0
- data/tests/test_smtpclient.rb +83 -0
- data/tests/test_smtpserver.rb +85 -0
- data/tests/test_spawn.rb +322 -0
- data/tests/test_ssl_args.rb +79 -0
- data/tests/test_ssl_methods.rb +50 -0
- data/tests/test_ssl_verify.rb +82 -0
- data/tests/test_timers.rb +162 -0
- data/tests/test_ud.rb +36 -0
- data/tests/testem.rb +31 -0
- data/web/whatis +7 -0
- metadata +237 -0
@@ -0,0 +1,89 @@
|
|
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.
|
2
|
+
|
3
|
+
|
4
|
+
=== What are Spawned Processes?
|
5
|
+
|
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.
|
7
|
+
|
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:
|
9
|
+
|
10
|
+
|
11
|
+
require 'eventmachine'
|
12
|
+
|
13
|
+
EM.run {
|
14
|
+
pong = EM.spawn {|x, ping|
|
15
|
+
puts "Pong received #{x}"
|
16
|
+
ping.notify( x-1 )
|
17
|
+
}
|
18
|
+
|
19
|
+
ping = EM.spawn {|x|
|
20
|
+
if x > 0
|
21
|
+
puts "Pinging #{x}"
|
22
|
+
pong.notify x, self
|
23
|
+
else
|
24
|
+
EM.stop
|
25
|
+
end
|
26
|
+
}
|
27
|
+
|
28
|
+
ping.notify 3
|
29
|
+
}
|
30
|
+
|
31
|
+
If you run this program, you'll see the following output:
|
32
|
+
|
33
|
+
Pinging 3
|
34
|
+
Pong received 3
|
35
|
+
Pinging 2
|
36
|
+
Pong received 2
|
37
|
+
Pinging 1
|
38
|
+
Pong received 1
|
39
|
+
|
40
|
+
Let's take it step by step.
|
41
|
+
|
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.
|
53
|
+
|
54
|
+
Back to our code sample:
|
55
|
+
|
56
|
+
pong = EM.spawn {|x, ping|
|
57
|
+
puts "Pong received #{x}"
|
58
|
+
ping.notify( x-1 )
|
59
|
+
}
|
60
|
+
|
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.
|
62
|
+
|
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.)
|
64
|
+
|
65
|
+
On to the next bit of the code sample:
|
66
|
+
|
67
|
+
ping = EM.spawn {|x|
|
68
|
+
if x > 0
|
69
|
+
puts "Pinging #{x}"
|
70
|
+
pong.notify x, self
|
71
|
+
else
|
72
|
+
EM.stop
|
73
|
+
end
|
74
|
+
}
|
75
|
+
|
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.
|
77
|
+
|
78
|
+
If the ping process receives a zero value, it will stop the reactor loop and end the program.
|
79
|
+
|
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.
|
81
|
+
|
82
|
+
But look at the next line in the code sample:
|
83
|
+
|
84
|
+
ping.notify 3
|
85
|
+
|
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"]
|
89
|
+
|
data/docs/TODO
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
TODO List:
|
2
|
+
|
3
|
+
12Aug06: Noticed by Don Stocks. A TCP connect-request that results
|
4
|
+
in a failed DNS resolution fires a fatal error back to user code.
|
5
|
+
Uuuuuugly. We should probably cause an unbind event to get fired
|
6
|
+
instead, and add some parameterization so the caller can detect
|
7
|
+
the nature of the failure.
|
8
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{smparkes-eventmachine}
|
5
|
+
s.version = "0.12.10"
|
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
|
11
|
+
communications. It's extremely easy to use in Ruby. EventMachine wraps all
|
12
|
+
interactions with IP sockets, allowing programs to concentrate on the
|
13
|
+
implementation of network protocols. It can be used to create both network
|
14
|
+
servers and clients. To create a server or client, a Ruby program only needs
|
15
|
+
to specify the IP address and port, and provide a Module that implements the
|
16
|
+
communications protocol. Implementations of several standard network protocols
|
17
|
+
are provided with the package, primarily to serve as examples. The real goal
|
18
|
+
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
|
34
|
+
|
35
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
36
|
+
else
|
37
|
+
end
|
38
|
+
else
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
EM.run do
|
4
|
+
|
5
|
+
# Create a channel to push data to, this could be stocks...
|
6
|
+
RandChannel = EM::Channel.new
|
7
|
+
|
8
|
+
# The server simply subscribes client connections to the channel on connect,
|
9
|
+
# and unsubscribes them on disconnect.
|
10
|
+
class Server < EM::Connection
|
11
|
+
def self.start(host = '127.0.0.1', port = 8000)
|
12
|
+
EM.start_server(host, port, self)
|
13
|
+
end
|
14
|
+
|
15
|
+
def post_init
|
16
|
+
@sid = RandChannel.subscribe { |m| send_data "#{m.inspect}\n" }
|
17
|
+
end
|
18
|
+
|
19
|
+
def unbind
|
20
|
+
RandChannel.unsubscribe @sid
|
21
|
+
end
|
22
|
+
end
|
23
|
+
Server.start
|
24
|
+
|
25
|
+
# Two client connections, that just print what they receive.
|
26
|
+
2.times do
|
27
|
+
EM.connect('127.0.0.1', 8000) do |c|
|
28
|
+
c.extend EM::P::LineText2
|
29
|
+
def c.receive_line(line)
|
30
|
+
puts "Subscriber: #{signature} got #{line}"
|
31
|
+
end
|
32
|
+
EM.add_timer(2) { c.close_connection }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# This part of the example is more fake, but imagine sleep was in fact a
|
37
|
+
# long running calculation to achieve the value.
|
38
|
+
40.times do
|
39
|
+
EM.defer lambda { v = sleep(rand * 2); RandChannel << [Time.now, v] }
|
40
|
+
end
|
41
|
+
|
42
|
+
EM.add_timer(5) { EM.stop }
|
43
|
+
end
|
data/examples/helper.rb
ADDED
data/ext/binder.cpp
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
/*****************************************************************************
|
2
|
+
|
3
|
+
$Id$
|
4
|
+
|
5
|
+
File: binder.cpp
|
6
|
+
Date: 07Apr06
|
7
|
+
|
8
|
+
Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
|
9
|
+
Gmail: blackhedd
|
10
|
+
|
11
|
+
This program is free software; you can redistribute it and/or modify
|
12
|
+
it under the terms of either: 1) the GNU General Public License
|
13
|
+
as published by the Free Software Foundation; either version 2 of the
|
14
|
+
License, or (at your option) any later version; or 2) Ruby's License.
|
15
|
+
|
16
|
+
See the file COPYING for complete licensing information.
|
17
|
+
|
18
|
+
*****************************************************************************/
|
19
|
+
|
20
|
+
#include "project.h"
|
21
|
+
|
22
|
+
#define DEV_URANDOM "/dev/urandom"
|
23
|
+
|
24
|
+
|
25
|
+
map<unsigned long, Bindable_t*> Bindable_t::BindingBag;
|
26
|
+
|
27
|
+
|
28
|
+
/********************************
|
29
|
+
STATIC Bindable_t::CreateBinding
|
30
|
+
********************************/
|
31
|
+
|
32
|
+
unsigned long Bindable_t::CreateBinding()
|
33
|
+
{
|
34
|
+
// XXX use atomic_t to prevent thread-safety issues
|
35
|
+
static unsigned long num = 0;
|
36
|
+
while(BindingBag[++num]);
|
37
|
+
return num;
|
38
|
+
}
|
39
|
+
|
40
|
+
#if 0
|
41
|
+
string Bindable_t::CreateBinding()
|
42
|
+
{
|
43
|
+
static int index = 0;
|
44
|
+
static string seed;
|
45
|
+
|
46
|
+
if ((index >= 1000000) || (seed.length() == 0)) {
|
47
|
+
#ifdef OS_UNIX
|
48
|
+
int fd = open (DEV_URANDOM, O_RDONLY);
|
49
|
+
if (fd < 0)
|
50
|
+
throw std::runtime_error ("No entropy device");
|
51
|
+
|
52
|
+
unsigned char u[16];
|
53
|
+
size_t r = read (fd, u, sizeof(u));
|
54
|
+
if (r < sizeof(u))
|
55
|
+
throw std::runtime_error ("Unable to read entropy device");
|
56
|
+
|
57
|
+
unsigned char *u1 = (unsigned char*)u;
|
58
|
+
char u2 [sizeof(u) * 2 + 1];
|
59
|
+
|
60
|
+
for (size_t i=0; i < sizeof(u); i++)
|
61
|
+
sprintf (u2 + (i * 2), "%02x", u1[i]);
|
62
|
+
|
63
|
+
seed = string (u2);
|
64
|
+
#endif
|
65
|
+
|
66
|
+
|
67
|
+
#ifdef OS_WIN32
|
68
|
+
UUID uuid;
|
69
|
+
UuidCreate (&uuid);
|
70
|
+
unsigned char *uuidstring = NULL;
|
71
|
+
UuidToString (&uuid, &uuidstring);
|
72
|
+
if (!uuidstring)
|
73
|
+
throw std::runtime_error ("Unable to read uuid");
|
74
|
+
seed = string ((const char*)uuidstring);
|
75
|
+
|
76
|
+
RpcStringFree (&uuidstring);
|
77
|
+
#endif
|
78
|
+
|
79
|
+
index = 0;
|
80
|
+
|
81
|
+
|
82
|
+
}
|
83
|
+
|
84
|
+
stringstream ss;
|
85
|
+
ss << seed << (++index);
|
86
|
+
return ss.str();
|
87
|
+
}
|
88
|
+
#endif
|
89
|
+
|
90
|
+
/*****************************
|
91
|
+
STATIC: Bindable_t::GetObject
|
92
|
+
*****************************/
|
93
|
+
|
94
|
+
Bindable_t *Bindable_t::GetObject (const unsigned long binding)
|
95
|
+
{
|
96
|
+
map<unsigned long, Bindable_t*>::const_iterator i = BindingBag.find (binding);
|
97
|
+
if (i != BindingBag.end())
|
98
|
+
return i->second;
|
99
|
+
else
|
100
|
+
return NULL;
|
101
|
+
}
|
102
|
+
|
103
|
+
|
104
|
+
/**********************
|
105
|
+
Bindable_t::Bindable_t
|
106
|
+
**********************/
|
107
|
+
|
108
|
+
Bindable_t::Bindable_t()
|
109
|
+
{
|
110
|
+
Binding = Bindable_t::CreateBinding();
|
111
|
+
BindingBag [Binding] = this;
|
112
|
+
}
|
113
|
+
|
114
|
+
|
115
|
+
|
116
|
+
/***********************
|
117
|
+
Bindable_t::~Bindable_t
|
118
|
+
***********************/
|
119
|
+
|
120
|
+
Bindable_t::~Bindable_t()
|
121
|
+
{
|
122
|
+
BindingBag.erase (Binding);
|
123
|
+
}
|
124
|
+
|
125
|
+
|
data/ext/binder.h
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
/*****************************************************************************
|
2
|
+
|
3
|
+
$Id$
|
4
|
+
|
5
|
+
File: binder.h
|
6
|
+
Date: 07Apr06
|
7
|
+
|
8
|
+
Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
|
9
|
+
Gmail: blackhedd
|
10
|
+
|
11
|
+
This program is free software; you can redistribute it and/or modify
|
12
|
+
it under the terms of either: 1) the GNU General Public License
|
13
|
+
as published by the Free Software Foundation; either version 2 of the
|
14
|
+
License, or (at your option) any later version; or 2) Ruby's License.
|
15
|
+
|
16
|
+
See the file COPYING for complete licensing information.
|
17
|
+
|
18
|
+
*****************************************************************************/
|
19
|
+
|
20
|
+
#ifndef __ObjectBindings__H_
|
21
|
+
#define __ObjectBindings__H_
|
22
|
+
|
23
|
+
|
24
|
+
class Bindable_t
|
25
|
+
{
|
26
|
+
public:
|
27
|
+
static unsigned long CreateBinding();
|
28
|
+
static Bindable_t *GetObject (const unsigned long);
|
29
|
+
static map<unsigned long, Bindable_t*> BindingBag;
|
30
|
+
|
31
|
+
public:
|
32
|
+
Bindable_t();
|
33
|
+
virtual ~Bindable_t();
|
34
|
+
|
35
|
+
const unsigned long GetBinding() {return Binding;}
|
36
|
+
|
37
|
+
private:
|
38
|
+
unsigned long Binding;
|
39
|
+
};
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
#endif // __ObjectBindings__H_
|
46
|
+
|