celluloid-zmq 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES.md ADDED
@@ -0,0 +1,7 @@
1
+ 0.0.2
2
+ -----
3
+ * Pure blocking 0MQ reactor using a ZMQ::PAIR socket as the waker
4
+
5
+ 0.0.1
6
+ -----
7
+ * Initial release
@@ -19,7 +19,7 @@ Gem::Specification.new do |gem|
19
19
 
20
20
  gem.add_development_dependency "rake"
21
21
  gem.add_development_dependency "rspec", ">= 2.7.0"
22
-
22
+
23
23
  # Files
24
24
  ignores = File.read(".gitignore").split(/\r?\n/).reject{ |f| f =~ /^(#.+|\s*)$/ }.map {|f| Dir[f] }.flatten
25
25
  gem.files = (Dir['**/*','.gitignore'] - ignores).reject {|f| !File.file?(f) }
data/lib/celluloid/zmq.rb CHANGED
@@ -4,13 +4,24 @@ require 'celluloid'
4
4
  require 'celluloid/zmq/mailbox'
5
5
  require 'celluloid/zmq/reactor'
6
6
  require 'celluloid/zmq/version'
7
+ require 'celluloid/zmq/waker'
7
8
 
8
9
  module Celluloid
9
10
  # Actors which run alongside 0MQ sockets
10
11
  module ZMQ
11
- def self.included(klass)
12
- klass.send :include, ::Celluloid
13
- klass.use_mailbox Celluloid::ZMQ::Mailbox
12
+ class << self
13
+ attr_writer :context
14
+
15
+ # Included hook to pull in Celluloid
16
+ def included(klass)
17
+ klass.send :include, ::Celluloid
18
+ klass.use_mailbox Celluloid::ZMQ::Mailbox
19
+ end
20
+
21
+ # Obtain a 0MQ context (or lazily initialize it)
22
+ def context
23
+ @context ||= ::ZMQ::Context.new(1)
24
+ end
14
25
  end
15
26
 
16
27
  # Wait for the given IO object to become readable
@@ -5,9 +5,9 @@ module Celluloid
5
5
  def initialize
6
6
  @messages = []
7
7
  @lock = Mutex.new
8
- @waker = Celluloid::IO::Waker.new
8
+ @waker = Celluloid::ZMQ::Waker.new
9
9
  @reactor = Reactor.new(@waker)
10
10
  end
11
11
  end
12
12
  end
13
- end
13
+ end
@@ -9,14 +9,10 @@ module Celluloid
9
9
  @readers = {}
10
10
  @writers = {}
11
11
 
12
- # FIXME: The way things are presently implemented is super ghetto
13
- # The ZMQ::Poller should be able to wait on the waker somehow
14
- # but I can't get it to work :(
15
- #result = @poller.register(nil, ::ZMQ::POLLIN, @waker.io.fileno)
16
- #
17
- #unless ::ZMQ::Util.resultcode_ok?(result)
18
- # raise "couldn't register waker with 0MQ poller"
19
- #end
12
+ rc = @poller.register @waker.socket, ::ZMQ::POLLIN
13
+ unless ::ZMQ::Util.resultcode_ok? rc
14
+ raise "0MQ poll error: #{::ZMQ::Util.error_string}"
15
+ end
20
16
  end
21
17
 
22
18
  # Wait for the given ZMQ socket to become readable
@@ -47,26 +43,25 @@ module Celluloid
47
43
  # Run the reactor, waiting for events, and calling the given block if
48
44
  # the reactor is awoken by the waker
49
45
  def run_once(timeout = nil)
50
- # FIXME: This approach is super ghetto. Find some way to make the
51
- # ZMQ::Poller wait on the waker's file descriptor
52
- if @poller.size == 0
53
- readable, _ = select [@waker.io], [], [], timeout
54
- yield if readable and readable.include? @waker.io
55
- else
56
- if ::ZMQ::Util.resultcode_ok? @poller.poll(100)
57
- @poller.readables.each do |sock|
58
- fiber = @readers.delete sock
59
- fiber.resume if fiber
60
- end
46
+ timeout ||= :blocking
47
+ rc = @poller.poll(timeout)
61
48
 
62
- @poller.writables.each do |sock|
63
- fiber = @writers.delete sock
64
- fiber.resume if fiber
65
- end
49
+ unless ::ZMQ::Util.resultcode_ok? rc
50
+ raise IOError, "0MQ poll error: #{::ZMQ::Util.error_string}"
51
+ end
52
+
53
+ @poller.readables.each do |sock|
54
+ if sock == @waker.socket
55
+ yield
56
+ else
57
+ fiber = @readers.delete sock
58
+ fiber.resume if fiber
66
59
  end
60
+ end
67
61
 
68
- readable, _ = select [@waker.io], [], [], 0
69
- yield if readable and readable.include? @waker.io
62
+ @poller.writables.each do |sock|
63
+ fiber = @writers.delete sock
64
+ fiber.resume if fiber
70
65
  end
71
66
  end
72
67
  end
@@ -1,5 +1,5 @@
1
1
  module Celluloid
2
2
  module ZMQ
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.2"
4
4
  end
5
5
  end
@@ -0,0 +1,54 @@
1
+ module Celluloid
2
+ module ZMQ
3
+ class DeadWakerError < Celluloid::IO::DeadWakerError; end # You can't wake the dead
4
+
5
+ # Wakes up sleepy threads so that they can check their mailbox
6
+ # Works like a ConditionVariable, except it's implemented as a ZMQ socket
7
+ # so that it can be multiplexed alongside other ZMQ sockets
8
+ class Waker
9
+ PAYLOAD = "\0" # the payload doesn't matter, it's just a signal
10
+
11
+ def initialize
12
+ @sender = ZMQ.context.socket(::ZMQ::PAIR)
13
+ @receiver = ZMQ.context.socket(::ZMQ::PAIR)
14
+
15
+ @addr = "inproc://waker-#{object_id}"
16
+ @sender.bind @addr
17
+ @receiver.connect @addr
18
+
19
+ @sender_lock = Mutex.new
20
+ end
21
+
22
+ # Wakes up the thread that is waiting for this Waker
23
+ def signal
24
+ @sender_lock.synchronize do
25
+ unless ::ZMQ::Util.resultcode_ok? @sender.send_string PAYLOAD
26
+ raise DeadWakerError, "error sending 0MQ message: #{::ZMQ::Util.error_string}"
27
+ end
28
+ end
29
+ end
30
+
31
+ # 0MQ socket to wait for messages on
32
+ def socket
33
+ @receiver
34
+ end
35
+
36
+ # Wait for another thread to signal this Waker
37
+ def wait
38
+ message = ''
39
+ rc = @receiver.recv_string message
40
+
41
+ unless ::ZMQ::Util.resultcode_ok? rc and message == PAYLOAD
42
+ raise DeadWakerError, "error receiving ZMQ string: #{::ZMQ::Util.error_string}"
43
+ end
44
+ end
45
+
46
+ # Clean up the IO objects associated with this waker
47
+ def cleanup
48
+ @sender_lock.synchronize { @sender.close rescue nil }
49
+ @receiver.close rescue nil
50
+ nil
51
+ end
52
+ end
53
+ end
54
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: celluloid-zmq
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-12-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: celluloid
16
- requirement: &70334545596400 !ruby/object:Gem::Requirement
16
+ requirement: &70257579473040 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 0.6.2
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70334545596400
24
+ version_requirements: *70257579473040
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: ffi
27
- requirement: &70334545595980 !ruby/object:Gem::Requirement
27
+ requirement: &70257579472580 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70334545595980
35
+ version_requirements: *70257579472580
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: ffi-rzmq
38
- requirement: &70334545595500 !ruby/object:Gem::Requirement
38
+ requirement: &70257579472120 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70334545595500
46
+ version_requirements: *70257579472120
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: redis
49
- requirement: &70334545595000 !ruby/object:Gem::Requirement
49
+ requirement: &70257579471700 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70334545595000
57
+ version_requirements: *70257579471700
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: redis-namespace
60
- requirement: &70334545594480 !ruby/object:Gem::Requirement
60
+ requirement: &70257579471260 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70334545594480
68
+ version_requirements: *70257579471260
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
- requirement: &70334545593840 !ruby/object:Gem::Requirement
71
+ requirement: &70257579470560 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70334545593840
79
+ version_requirements: *70257579470560
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: rspec
82
- requirement: &70334545592940 !ruby/object:Gem::Requirement
82
+ requirement: &70257579469580 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: 2.7.0
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70334545592940
90
+ version_requirements: *70257579469580
91
91
  description: Celluloid bindings to the ffi-rzmq library
92
92
  email:
93
93
  - tony.arcieri@gmail.com
@@ -96,10 +96,12 @@ extensions: []
96
96
  extra_rdoc_files: []
97
97
  files:
98
98
  - celluloid-zmq.gemspec
99
+ - CHANGES.md
99
100
  - Gemfile
100
101
  - lib/celluloid/zmq/mailbox.rb
101
102
  - lib/celluloid/zmq/reactor.rb
102
103
  - lib/celluloid/zmq/version.rb
104
+ - lib/celluloid/zmq/waker.rb
103
105
  - lib/celluloid/zmq.rb
104
106
  - Rakefile
105
107
  - README.md