producer_consumer 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2011 Kyle Kingsbury
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,5 @@
1
+ ProducerConsumer.produce 4 do |p|
2
+ some_item or p.finish
3
+ end.consume 10 do |item|
4
+ puts item
5
+ end.run
@@ -0,0 +1,115 @@
1
+ class ProducerConsumer
2
+ require 'thread'
3
+
4
+ class Finished < Exception
5
+ end
6
+
7
+ class NoConsumer < RuntimeError
8
+ end
9
+
10
+ class NoProducer < RuntimeError
11
+ end
12
+
13
+ class Producer
14
+ def finish
15
+ raise ProducerConsumer::Finished
16
+ end
17
+ end
18
+
19
+ def self.consume(*a, &b)
20
+ new.consume(*a, &b)
21
+ end
22
+
23
+ def self.produce(*a, &b)
24
+ new.produce(*a, &b)
25
+ end
26
+
27
+ # Oh god. It's a PATTERN.
28
+ def initialize
29
+ @queue = Queue.new
30
+ @state = :free
31
+ @producers = []
32
+ @consumers = []
33
+ end
34
+
35
+ # Registers n producers
36
+ def produce(n = 1, &block)
37
+ @producers += (0...n).map do |i|
38
+ block
39
+ end
40
+
41
+ self
42
+ end
43
+
44
+ def producer(block)
45
+ Thread.new do
46
+ p = Producer.new
47
+ begin
48
+ loop do
49
+ @queue << block.call(p)
50
+ end
51
+ rescue Finished
52
+ end
53
+ end
54
+ end
55
+
56
+ # Registers n consumers
57
+ def consume(n = 1, &block)
58
+ @consumers += (0...n).map do |c|
59
+ block
60
+ end
61
+
62
+ self
63
+ end
64
+
65
+ def consumer(block)
66
+ Thread.new do
67
+ begin
68
+ loop do
69
+ x = @queue.pop
70
+
71
+ if x == Finished
72
+ raise Finished
73
+ end
74
+
75
+ block.call x
76
+ end
77
+ rescue Finished
78
+ end
79
+ end
80
+ end
81
+
82
+ # Run!
83
+ def run
84
+ # Can't run this more than once.
85
+ unless @state == :free
86
+ raise RuntimeError, "Already running"
87
+ end
88
+
89
+ # Validate we will actually do something.
90
+ raise NoConsumer if @consumers.empty?
91
+ raise NoProducer if @producers.empty?
92
+
93
+ # Start producers and consumers
94
+ @state = :starting
95
+ consumers = @consumers.map do |block|
96
+ consumer block
97
+ end
98
+ producers = @producers.map do |block|
99
+ producer block
100
+ end
101
+
102
+ # Wait for producers to finish
103
+ @state = :waiting_for_producers
104
+ producers.each { |t| t.join }
105
+
106
+ # Signal consumers to finish...
107
+ @state = :waiting_for_consumers
108
+ consumers.size.times do
109
+ @queue << Finished
110
+ end
111
+ consumers.each { |t| t.join }
112
+
113
+ @state = :free
114
+ end
115
+ end
@@ -0,0 +1,3 @@
1
+ class ProducerConsumer
2
+ VERSION = '0.1'
3
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: producer_consumer
3
+ version: !ruby/object:Gem::Version
4
+ hash: 9
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ version: "0.1"
10
+ platform: ruby
11
+ authors:
12
+ - Kyle Kingsbury
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-06-28 00:00:00 -07:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description:
22
+ email: aphyr@aphyr.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - lib/producer_consumer.rb
31
+ - lib/producer_consumer/version.rb
32
+ - LICENSE
33
+ - README.markdown
34
+ has_rdoc: true
35
+ homepage: https://github.com/aphyr/producer_consumer
36
+ licenses: []
37
+
38
+ post_install_message:
39
+ rdoc_options: []
40
+
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ hash: 57
49
+ segments:
50
+ - 1
51
+ - 8
52
+ - 7
53
+ version: 1.8.7
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ requirements: []
64
+
65
+ rubyforge_project: producer_consumer
66
+ rubygems_version: 1.3.7
67
+ signing_key:
68
+ specification_version: 3
69
+ summary: A tiny threaded queue-backed producer-consumer.
70
+ test_files: []
71
+