concurrent-selectable 0.1 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|