concurrent-selectable 0.1 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/concurrent/selectable/channel.rb +1 -0
- data/lib/concurrent/selectable/common.rb +10 -0
- data/lib/concurrent/selectable/semaphore.rb +24 -7
- data/spec/selectable/channel_spec.rb +45 -0
- data/spec/selectable/latch_spec.rb +28 -0
- data/spec/selectable/semaphore_spec.rb +28 -0
- metadata +12 -13
- data/Rakefile +0 -42
- data/test/test_all.rb +0 -3
- data/test/test_channel.rb +0 -23
- data/test/test_latch.rb +0 -23
- data/test/test_semaphore.rb +0 -23
@@ -62,6 +62,16 @@ class Base
|
|
62
62
|
@read
|
63
63
|
end
|
64
64
|
|
65
|
+
# Manually releases the IO resources associated with the primitive
|
66
|
+
def close
|
67
|
+
[ @read, @write ].each do |port|
|
68
|
+
begin
|
69
|
+
port.close
|
70
|
+
rescue Exception
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
65
75
|
private
|
66
76
|
def internal_set
|
67
77
|
@write.write 'x'
|
@@ -48,9 +48,21 @@ class Semaphore < Base
|
|
48
48
|
@count = count
|
49
49
|
end
|
50
50
|
|
51
|
+
# Increments the semaphore
|
52
|
+
def signal
|
53
|
+
@lock.synchronize do
|
54
|
+
internal_set if @count.zero?
|
55
|
+
@count += 1
|
56
|
+
end
|
57
|
+
self
|
58
|
+
end
|
59
|
+
alias_method :put, :signal
|
60
|
+
alias_method :up, :signal
|
61
|
+
alias_method :v, :signal
|
62
|
+
|
51
63
|
# Decrements the semaphore, blocking if its count is already zero and
|
52
64
|
# +blocking+ is true.
|
53
|
-
def
|
65
|
+
def wait(blocking=true)
|
54
66
|
loop do
|
55
67
|
@lock.synchronize do
|
56
68
|
if @count.nonzero?
|
@@ -60,17 +72,22 @@ class Semaphore < Base
|
|
60
72
|
end
|
61
73
|
end
|
62
74
|
return nil unless blocking
|
63
|
-
|
75
|
+
super()
|
64
76
|
end
|
65
77
|
end
|
78
|
+
alias_method :get, :wait
|
79
|
+
alias_method :down, :wait
|
80
|
+
alias_method :p, :wait
|
66
81
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
82
|
+
def exclusive
|
83
|
+
wait
|
84
|
+
begin
|
85
|
+
yield
|
86
|
+
ensure
|
87
|
+
signal
|
72
88
|
end
|
73
89
|
end
|
90
|
+
alias_method :synchronize, :exclusive
|
74
91
|
|
75
92
|
# Returns true if the count is currently zero (additional external
|
76
93
|
# synchronization is usually required if other threads can modify the
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'concurrent/selectable/channel'
|
2
|
+
|
3
|
+
SChannel = Concurrent::Selectable::Channel
|
4
|
+
|
5
|
+
describe SChannel do
|
6
|
+
before :each do
|
7
|
+
@channel = SChannel.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should be convertable to an IO object" do
|
11
|
+
@channel.to_io.should be_an_instance_of(IO)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should allow values to be written with << and received with receive" do
|
15
|
+
@channel << :blah
|
16
|
+
t = Thread.new { sleep 2 ; @channel << nil }
|
17
|
+
@channel.receive.should == :blah
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should allow values to be written with put and received with get" do
|
21
|
+
@channel.put :blah
|
22
|
+
t = Thread.new { sleep 2 ; @channel.put nil }
|
23
|
+
@channel.get.should == :blah
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should block while a value is not available" do
|
27
|
+
t = Thread.new { sleep 2 ; @channel << :foo }
|
28
|
+
@channel.receive.should == :foo
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should not be readable when empty empty" do
|
32
|
+
IO.select([@channel], nil, nil, 0).should be_nil
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should be readable while it has values" do
|
36
|
+
@channel << :blah
|
37
|
+
IO.select([@channel], nil, nil, 0).should == [[@channel], [], []]
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should not be readable after it has been emptied" do
|
41
|
+
@channel << :blah
|
42
|
+
@channel.receive
|
43
|
+
IO.select([@channel], nil, nil, 0).should be_nil
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'concurrent/selectable/latch'
|
2
|
+
|
3
|
+
Latch = Concurrent::Selectable::Latch
|
4
|
+
|
5
|
+
describe Latch do
|
6
|
+
before :each do
|
7
|
+
@latch = Latch.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should be convertable to an IO object" do
|
11
|
+
@latch.to_io.should be_an_instance_of(IO)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should not be readable when it is not set" do
|
15
|
+
IO.select([@latch], nil, nil, 0).should be_nil
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should be readable when it is set" do
|
19
|
+
@latch.set
|
20
|
+
IO.select([@latch], nil, nil, 0).should == [[@latch], [], []]
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should not be readable after it is reset" do
|
24
|
+
@latch.set
|
25
|
+
@latch.reset
|
26
|
+
IO.select([@latch], nil, nil, 0).should be_nil
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'concurrent/selectable/semaphore'
|
2
|
+
|
3
|
+
CSemaphore = Concurrent::Selectable::Semaphore
|
4
|
+
|
5
|
+
describe CSemaphore do
|
6
|
+
before :each do
|
7
|
+
@semaphore = CSemaphore.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should be convertable to an IO object" do
|
11
|
+
@semaphore.to_io.should be_an_instance_of(IO)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should not be readable when it has a zero count" do
|
15
|
+
IO.select([@semaphore], nil, nil, 0).should be_nil
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should be readable after it has been incremented" do
|
19
|
+
@semaphore.put
|
20
|
+
IO.select([@semaphore], nil, nil, 0).should == [[@semaphore], [], []]
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should not be readable after it has been decremented again" do
|
24
|
+
@semaphore.put
|
25
|
+
@semaphore.get
|
26
|
+
IO.select([@semaphore], nil, nil, 0).should be_nil
|
27
|
+
end
|
28
|
+
end
|
metadata
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.
|
2
|
+
rubygems_version: 0.9.4
|
3
3
|
specification_version: 1
|
4
4
|
name: concurrent-selectable
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version:
|
7
|
-
date: 2008-
|
8
|
-
summary: Synchronization primitives
|
6
|
+
version: 0.1.1
|
7
|
+
date: 2008-06-03 00:00:00 -04:00
|
8
|
+
summary: Synchronization primitives for event-driven IO
|
9
9
|
require_paths:
|
10
10
|
- lib
|
11
11
|
email:
|
@@ -25,21 +25,20 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
|
|
25
25
|
platform: ruby
|
26
26
|
signing_key:
|
27
27
|
cert_chain:
|
28
|
+
post_install_message:
|
28
29
|
authors:
|
29
30
|
- MenTaLguY <mental@rydia.net>
|
30
31
|
files:
|
31
|
-
-
|
32
|
-
-
|
33
|
-
-
|
34
|
-
- test/test_semaphore.rb
|
35
|
-
- test/test_channel.rb
|
32
|
+
- spec/selectable/channel_spec.rb
|
33
|
+
- spec/selectable/latch_spec.rb
|
34
|
+
- spec/selectable/semaphore_spec.rb
|
36
35
|
- lib/concurrent/selectable.rb
|
37
|
-
- lib/concurrent/selectable/
|
36
|
+
- lib/concurrent/selectable/channel.rb
|
38
37
|
- lib/concurrent/selectable/common.rb
|
38
|
+
- lib/concurrent/selectable/latch.rb
|
39
39
|
- lib/concurrent/selectable/semaphore.rb
|
40
|
-
|
41
|
-
|
42
|
-
- test/test_all.rb
|
40
|
+
test_files: []
|
41
|
+
|
43
42
|
rdoc_options: []
|
44
43
|
|
45
44
|
extra_rdoc_files: []
|
data/Rakefile
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'rake'
|
2
|
-
require 'rake/testtask'
|
3
|
-
require 'rake/rdoctask'
|
4
|
-
require 'rake/gempackagetask'
|
5
|
-
require 'rake/clean'
|
6
|
-
|
7
|
-
GEM_VERSION = "0.1"
|
8
|
-
|
9
|
-
Rake::RDocTask.new do |task|
|
10
|
-
task.rdoc_files.add [ 'lib/**/*.rb' ]
|
11
|
-
end
|
12
|
-
|
13
|
-
task :clobber => [ :clean ]
|
14
|
-
|
15
|
-
Rake::TestTask.new do |task|
|
16
|
-
task.ruby_opts << '-rrubygems'
|
17
|
-
task.libs << 'lib'
|
18
|
-
task.libs << 'test'
|
19
|
-
task.test_files = [ "test/test_all.rb" ]
|
20
|
-
task.verbose = true
|
21
|
-
end
|
22
|
-
|
23
|
-
gemspec = Gem::Specification.new do |gemspec|
|
24
|
-
gemspec.name = "concurrent-selectable"
|
25
|
-
gemspec.version = GEM_VERSION
|
26
|
-
gemspec.author = "MenTaLguY <mental@rydia.net>"
|
27
|
-
gemspec.summary = "Synchronization primitives with selectable IO channels"
|
28
|
-
gemspec.test_file = 'test/test_all.rb'
|
29
|
-
gemspec.files = FileList[ 'Rakefile', 'test/*.rb', 'lib/**/*.rb' ]
|
30
|
-
gemspec.require_paths = [ 'lib' ]
|
31
|
-
gemspec.has_rdoc = true
|
32
|
-
gemspec.platform = Gem::Platform::RUBY
|
33
|
-
end
|
34
|
-
|
35
|
-
task :package => [ :clean, :test ]
|
36
|
-
Rake::GemPackageTask.new( gemspec ) do |task|
|
37
|
-
task.gem_spec = gemspec
|
38
|
-
task.need_tar = true
|
39
|
-
end
|
40
|
-
|
41
|
-
task :default => [ :clean, :test ]
|
42
|
-
|
data/test/test_all.rb
DELETED
data/test/test_channel.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require 'concurrent/selectable/channel'
|
3
|
-
|
4
|
-
SChannel = Concurrent::Selectable::Channel
|
5
|
-
|
6
|
-
class TestChannel < Test::Unit::TestCase
|
7
|
-
def test_to_io
|
8
|
-
channel = SChannel.new
|
9
|
-
assert_instance_of IO, channel.to_io
|
10
|
-
end
|
11
|
-
|
12
|
-
def test_select
|
13
|
-
channel = SChannel.new
|
14
|
-
ready = IO.select([channel], nil, nil, 0.01)
|
15
|
-
assert !ready
|
16
|
-
channel.put :blah
|
17
|
-
ready = IO.select([channel], nil, nil, 0.01)
|
18
|
-
assert ready
|
19
|
-
channel.get
|
20
|
-
ready = IO.select([channel], nil, nil, 0.01)
|
21
|
-
assert !ready
|
22
|
-
end
|
23
|
-
end
|
data/test/test_latch.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require 'concurrent/selectable/latch'
|
3
|
-
|
4
|
-
Latch = Concurrent::Selectable::Latch
|
5
|
-
|
6
|
-
class TestLatch < Test::Unit::TestCase
|
7
|
-
def test_to_io
|
8
|
-
latch = Latch.new
|
9
|
-
assert_instance_of IO, latch.to_io
|
10
|
-
end
|
11
|
-
|
12
|
-
def test_select
|
13
|
-
latch = Latch.new
|
14
|
-
ready = IO.select([latch], nil, nil, 0.01)
|
15
|
-
assert !ready
|
16
|
-
latch.set
|
17
|
-
ready = IO.select([latch], nil, nil, 0.01)
|
18
|
-
assert ready
|
19
|
-
latch.reset
|
20
|
-
ready = IO.select([latch], nil, nil, 0.01)
|
21
|
-
assert !ready
|
22
|
-
end
|
23
|
-
end
|
data/test/test_semaphore.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require 'concurrent/selectable/semaphore'
|
3
|
-
|
4
|
-
Semaphore = Concurrent::Selectable::Semaphore
|
5
|
-
|
6
|
-
class TestSemaphore < Test::Unit::TestCase
|
7
|
-
def test_to_io
|
8
|
-
semaphore = Semaphore.new
|
9
|
-
assert_instance_of IO, semaphore.to_io
|
10
|
-
end
|
11
|
-
|
12
|
-
def test_select
|
13
|
-
semaphore = Semaphore.new
|
14
|
-
ready = IO.select([semaphore], nil, nil, 0.01)
|
15
|
-
assert !ready
|
16
|
-
semaphore.put
|
17
|
-
ready = IO.select([semaphore], nil, nil, 0.01)
|
18
|
-
assert ready
|
19
|
-
semaphore.get
|
20
|
-
ready = IO.select([semaphore], nil, nil, 0.01)
|
21
|
-
assert !ready
|
22
|
-
end
|
23
|
-
end
|