win32-semaphore 0.3.0
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/CHANGES +33 -0
- data/MANIFEST +8 -0
- data/README +58 -0
- data/Rakefile +26 -0
- data/lib/win32/semaphore.rb +135 -0
- data/test/tc_semaphore.rb +70 -0
- data/win32-semaphore.gemspec +24 -0
- metadata +68 -0
data/CHANGES
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
== 0.3.0 - 3-May-2007
|
2
|
+
* Now pure Ruby.
|
3
|
+
* Added a Rakefile, with test, install and example tasks.
|
4
|
+
* Both the Semaphore.new and Semaphore.open methods now accept a block, and
|
5
|
+
automatically close the associated handle at the end of the block.
|
6
|
+
* The Semaphore.new method now accepts an optional fourth argument that
|
7
|
+
controls whether the Event object can be inherited by other processes.
|
8
|
+
* Added a gemspec.
|
9
|
+
* Removed the doc/semaphore.txt file. The documentation is now inlined via
|
10
|
+
RDoc. There is also some documentation in the README file.
|
11
|
+
|
12
|
+
== 0.2.2 - 10-Jun-2005
|
13
|
+
* Now Unicode friendly.
|
14
|
+
* Inlined rdoc documentation into the C source code.
|
15
|
+
* Made the semaphore.txt file rdoc friendly.
|
16
|
+
* Removed the semaphore.rd file.
|
17
|
+
|
18
|
+
== 0.2.1 - 1-Mar-2005
|
19
|
+
* Added a VERSION constant (oops).
|
20
|
+
* Moved the 'examples' directory to the toplevel directory.
|
21
|
+
* Made the CHANGES and README files rdoc friendly.
|
22
|
+
* Removed an unused (and unnecessary) helper function in semaphore.h.
|
23
|
+
|
24
|
+
== 0.2.0 - 16-Jul-2004
|
25
|
+
* Modified to use the newer allocation framework. This means that as of this
|
26
|
+
release, this package requires Ruby 1.8.0 or later.
|
27
|
+
* Fixed a bug in the constructor where it was possible for the constructor to
|
28
|
+
fail, but have no error raised.
|
29
|
+
* Moved the test.rb file to the doc/examples directory.
|
30
|
+
* Added more tests.
|
31
|
+
|
32
|
+
== 0.1.0 - 14-May-2004
|
33
|
+
* Initial release
|
data/MANIFEST
ADDED
data/README
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
== Brief Description
|
2
|
+
An interface for MS Windows Semaphores.
|
3
|
+
|
4
|
+
== Prerequisites
|
5
|
+
win32-ipc 0.5.0 or later.
|
6
|
+
|
7
|
+
== Installation
|
8
|
+
rake test (optional)
|
9
|
+
rake install
|
10
|
+
|
11
|
+
== Synopsis
|
12
|
+
require "win32/semaphore"
|
13
|
+
include Win32
|
14
|
+
|
15
|
+
Semaphore.new(1, 5, 'test') do |sem|
|
16
|
+
puts 'uh, oh' unless sem.wait(10) > 0
|
17
|
+
sem.release(2) # 2
|
18
|
+
end
|
19
|
+
|
20
|
+
== Documentation
|
21
|
+
The event.rb file contains inline RDoc documentation. If you installed
|
22
|
+
this file as a gem, then you have the docs.
|
23
|
+
|
24
|
+
For more detailed documentation about Semaphores on MS Windows in general,
|
25
|
+
please visit http://www.msdn.com/library and lookup the CreateSemaphore(),
|
26
|
+
OpenSemaphore() and ReleaseSemaphore() functions.
|
27
|
+
|
28
|
+
== Notes
|
29
|
+
The Semaphore class is a subclass of Win32::Ipc (win32-ipc). This package
|
30
|
+
require's the win32-ipc package internally (you don't need to explicitly
|
31
|
+
call it).
|
32
|
+
|
33
|
+
== Acknowledgements
|
34
|
+
Adapted originally from the Win32::Semaphore Perl module by Christopher
|
35
|
+
J. Madsen.
|
36
|
+
|
37
|
+
== Known Bugs
|
38
|
+
None known. Any bugs should be reported on the project page at
|
39
|
+
http://rubyforge.org/projects/win32utils.
|
40
|
+
|
41
|
+
== Future Plans
|
42
|
+
Suggestions welcome.
|
43
|
+
|
44
|
+
== License
|
45
|
+
Ruby's
|
46
|
+
|
47
|
+
== Copyright
|
48
|
+
(C) 2003-2007 Daniel J. Berger
|
49
|
+
All Rights Reserved
|
50
|
+
|
51
|
+
== Warranty
|
52
|
+
This package is provided "as is" and without any express or
|
53
|
+
implied warranties, including, without limitation, the implied
|
54
|
+
warranties of merchantability and fitness for a particular purpose.
|
55
|
+
|
56
|
+
== Author(s)
|
57
|
+
Daniel J. Berger
|
58
|
+
Park Heesob
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rbconfig'
|
4
|
+
include Config
|
5
|
+
|
6
|
+
desc 'Install the win32-semaphore package (non-gem)'
|
7
|
+
task :install do
|
8
|
+
sitelibdir = CONFIG['sitelibdir']
|
9
|
+
installdir = File.join(sitelibdir, 'win32')
|
10
|
+
file = 'lib\win32\semaphore.rb'
|
11
|
+
|
12
|
+
Dir.mkdir(installdir) unless File.exists?(installdir)
|
13
|
+
FileUtils.cp(file, installdir, :verbose => true)
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Run the example program'
|
17
|
+
task :example do
|
18
|
+
ruby '-Ilib examples/semaphore_test.rb'
|
19
|
+
end
|
20
|
+
|
21
|
+
Rake::TestTask.new do |t|
|
22
|
+
t.libs << 'test'
|
23
|
+
t.verbose = true
|
24
|
+
t.warning = true
|
25
|
+
t.test_files = FileList['test/tc_semaphore.rb']
|
26
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'win32/ipc'
|
2
|
+
|
3
|
+
module Win32
|
4
|
+
class Semaphore < Ipc
|
5
|
+
|
6
|
+
# This is the error raised if any of the Semaphore methods fail.
|
7
|
+
class Error < StandardError; end
|
8
|
+
|
9
|
+
extend Windows::Synchronize
|
10
|
+
extend Windows::Error
|
11
|
+
extend Windows::Handle
|
12
|
+
|
13
|
+
VERSION = '0.3.0'
|
14
|
+
|
15
|
+
# The initial count for the semaphore object. This value must be greater
|
16
|
+
# than or equal to zero and less than or equal to +max_count+. The state
|
17
|
+
# of a semaphore is signaled when its count is greater than zero and
|
18
|
+
# nonsignaled when it is zero. The count is decreased by one whenever
|
19
|
+
# a wait function releases a thread that was waiting for the semaphore.
|
20
|
+
# The count is increased by a specified amount by calling
|
21
|
+
# Semaphore#release method.
|
22
|
+
#
|
23
|
+
attr_reader :initial_count
|
24
|
+
|
25
|
+
# The maximum count for the semaphore object. This value must be
|
26
|
+
# greater than zero.
|
27
|
+
#
|
28
|
+
attr_reader :max_count
|
29
|
+
|
30
|
+
# The name of the Semaphore object.
|
31
|
+
#
|
32
|
+
attr_reader :name
|
33
|
+
|
34
|
+
# Creates and returns new Semaphore object. If +name+ is omitted, the
|
35
|
+
# Semaphore object is created without a name, i.e. it's anonymous.
|
36
|
+
#
|
37
|
+
# If +name+ is provided and it already exists, then it is opened
|
38
|
+
# instead, and the +initial_count+ and +max_count+ parameters are
|
39
|
+
# ignored.
|
40
|
+
#
|
41
|
+
# The +initial_count+ and +max_count+ parameters set the initial count
|
42
|
+
# and maximum count for the Semaphore object, respectively. See the
|
43
|
+
# documentation for the corresponding accessor for more information.
|
44
|
+
#
|
45
|
+
# The +inherit+ attribute determines whether or not the semaphore can
|
46
|
+
# be inherited by child processes.
|
47
|
+
#
|
48
|
+
def initialize(initial_count, max_count, name=nil, inherit=true)
|
49
|
+
@initial_count = initial_count
|
50
|
+
@max_count = max_count
|
51
|
+
@name = name
|
52
|
+
@inherit = inherit
|
53
|
+
|
54
|
+
# Used to prevent potential segfaults.
|
55
|
+
if name && !name.is_a?(String)
|
56
|
+
raise TypeError, 'name must be a string'
|
57
|
+
end
|
58
|
+
|
59
|
+
if inherit
|
60
|
+
sec = 0.chr * 12 # sizeof(SECURITY_ATTRIBUTES)
|
61
|
+
sec[0,4] = [12].pack('L')
|
62
|
+
sec[8,4] = [1].pack('L') # 1 == TRUE
|
63
|
+
else
|
64
|
+
sec = 0
|
65
|
+
end
|
66
|
+
|
67
|
+
handle = CreateSemaphore(sec, initial_count, max_count, name)
|
68
|
+
|
69
|
+
if handle == 0 || handle == INVALID_HANDLE_VALUE
|
70
|
+
raise Error, get_last_error
|
71
|
+
end
|
72
|
+
|
73
|
+
super(handle)
|
74
|
+
|
75
|
+
if block_given?
|
76
|
+
begin
|
77
|
+
yield self
|
78
|
+
ensure
|
79
|
+
close
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Open an existing Semaphore by +name+. The +inherit+ argument sets
|
85
|
+
# whether or not the object was opened such that a process created by the
|
86
|
+
# CreateProcess() function (a Windows API function) can inherit the
|
87
|
+
# handle. The default is true.
|
88
|
+
#
|
89
|
+
# This method is essentially identical to Semaphore.new, except that the
|
90
|
+
# options for +initial_count+ and +max_count+ cannot be set (since they
|
91
|
+
# are already set). Also, this method will raise a Semaphore::Error if
|
92
|
+
# the semaphore doesn't already exist.
|
93
|
+
#
|
94
|
+
# If you want "open or create" semantics, then use Semaphore.new.
|
95
|
+
#--
|
96
|
+
# The OpenSemaphore() call here is strictly to force an error if the user
|
97
|
+
# tries to open a semaphore that doesn't already exist.
|
98
|
+
#
|
99
|
+
def self.open(name, inherit=true, &block)
|
100
|
+
if name && !name.is_a?(String)
|
101
|
+
raise TypeError, 'name must be a string'
|
102
|
+
end
|
103
|
+
|
104
|
+
bool = inherit ? 1 : 0
|
105
|
+
handle = OpenSemaphore(EVENT_ALL_ACCESS, bool, name)
|
106
|
+
if handle == 0 || handle == INVALID_HANDLE_VALUE
|
107
|
+
raise Error, get_last_error
|
108
|
+
end
|
109
|
+
CloseHandle(handle)
|
110
|
+
|
111
|
+
self.new(0, 1, name, inherit, &block)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Increases the count of the specified semaphore object by +amount+.
|
115
|
+
# The default is 1. Returns the previous count of the semaphore if
|
116
|
+
# successful. If the +amount+ exceeds the +max_count+ specified when
|
117
|
+
# the semaphore was created then a Semaphore::Error is raised.
|
118
|
+
#
|
119
|
+
def release(amount = 1)
|
120
|
+
pcount = [0].pack('L')
|
121
|
+
unless ReleaseSemaphore(@handle, amount, pcount)
|
122
|
+
raise Error, get_last_error
|
123
|
+
end
|
124
|
+
pcount.unpack('L').first
|
125
|
+
end
|
126
|
+
|
127
|
+
# Returns whether or not the object was opened such that a process
|
128
|
+
# created by the CreateProcess() function (a Windows API function) can
|
129
|
+
# inherit the handle. The default is true.
|
130
|
+
#
|
131
|
+
def inheritable?
|
132
|
+
@inherit
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
################################################################
|
2
|
+
# tc_semaphore.rb
|
3
|
+
#
|
4
|
+
# Test suite for the win32-semaphore package. This test should
|
5
|
+
# be run via the 'rake test' task.
|
6
|
+
################################################################
|
7
|
+
require 'win32/semaphore'
|
8
|
+
require 'test/unit'
|
9
|
+
include Win32
|
10
|
+
|
11
|
+
class TC_Semaphore < Test::Unit::TestCase
|
12
|
+
def setup
|
13
|
+
@sem = Semaphore.new(1, 3, 'test')
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_version
|
17
|
+
assert_equal('0.3.0', Semaphore::VERSION)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_max_semaphore_name
|
21
|
+
name = "foobar" * 500
|
22
|
+
assert_raises(Semaphore::Error){ Semaphore.new(1, 1, name){} }
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_open
|
26
|
+
assert_respond_to(Semaphore, :open)
|
27
|
+
assert_nothing_raised{ Semaphore.open('test'){} }
|
28
|
+
assert_raises(Semaphore::Error){ Semaphore.open('bogus'){} }
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_inheritable
|
32
|
+
assert_respond_to(@sem, :inheritable?)
|
33
|
+
assert_equal(true, @sem.inheritable?)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_release
|
37
|
+
assert_respond_to(@sem, :release)
|
38
|
+
assert_equal(1, @sem.release(1))
|
39
|
+
assert_equal(2, @sem.release(1))
|
40
|
+
assert_raises(Semaphore::Error){ @sem.release(99) }
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_wait
|
44
|
+
assert_respond_to(@sem, :wait)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_wait_any
|
48
|
+
assert_respond_to(@sem, :wait_any)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_wait_all
|
52
|
+
assert_respond_to(@sem, :wait_all)
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_valid_constructor
|
56
|
+
assert_nothing_raised{ Semaphore.new(0, 1){} }
|
57
|
+
assert_nothing_raised{ Semaphore.new(0, 1, "foo"){} }
|
58
|
+
assert_nothing_raised{ Semaphore.new(0, 1, "foo", false){} }
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_invalid_constructor
|
62
|
+
assert_raises(TypeError){ Semaphore.new("foo", "bar"){} }
|
63
|
+
assert_raises(ArgumentError){ Semaphore.new(1, 1, "test", 1, 1){} }
|
64
|
+
end
|
65
|
+
|
66
|
+
def teardown
|
67
|
+
@sem.close
|
68
|
+
@sem = nil
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
|
3
|
+
spec = Gem::Specification.new do |gem|
|
4
|
+
gem.name = "win32-semaphore"
|
5
|
+
gem.version = "0.3.0"
|
6
|
+
gem.author = "Daniel J. Berger"
|
7
|
+
gem.email = "djberg96@gmail.com"
|
8
|
+
gem.homepage = "http://www.rubyforge.org/projects/win32utils"
|
9
|
+
gem.platform = Gem::Platform::RUBY
|
10
|
+
gem.summary = "Interface to MS Windows Semaphore objects."
|
11
|
+
gem.description = "Interface to MS Windows Semaphore objects."
|
12
|
+
gem.test_file = "test/tc_semaphore.rb"
|
13
|
+
gem.has_rdoc = true
|
14
|
+
gem.files = Dir["lib/win32/*.rb"] + Dir["test/*"] + Dir["[A-Z]*"]
|
15
|
+
gem.files.reject! { |fn| fn.include? "CVS" }
|
16
|
+
gem.require_path = "lib"
|
17
|
+
gem.extra_rdoc_files = ["README", "CHANGES", "MANIFEST"]
|
18
|
+
gem.add_dependency("win32-ipc", ">= 0.5.0")
|
19
|
+
end
|
20
|
+
|
21
|
+
if $0 == __FILE__
|
22
|
+
Gem.manage_gems
|
23
|
+
Gem::Builder.new(spec).build
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.2
|
3
|
+
specification_version: 1
|
4
|
+
name: win32-semaphore
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.3.0
|
7
|
+
date: 2007-05-03 00:00:00 -06:00
|
8
|
+
summary: Interface to MS Windows Semaphore objects.
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: djberg96@gmail.com
|
12
|
+
homepage: http://www.rubyforge.org/projects/win32utils
|
13
|
+
rubyforge_project:
|
14
|
+
description: Interface to MS Windows Semaphore objects.
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Daniel J. Berger
|
31
|
+
files:
|
32
|
+
- lib/win32/semaphore.rb
|
33
|
+
- test/CVS
|
34
|
+
- test/tc_semaphore.rb
|
35
|
+
- CHANGES
|
36
|
+
- CVS
|
37
|
+
- doc
|
38
|
+
- examples
|
39
|
+
- lib
|
40
|
+
- MANIFEST
|
41
|
+
- Rakefile
|
42
|
+
- README
|
43
|
+
- test
|
44
|
+
- win32-semaphore.gemspec
|
45
|
+
test_files:
|
46
|
+
- test/tc_semaphore.rb
|
47
|
+
rdoc_options: []
|
48
|
+
|
49
|
+
extra_rdoc_files:
|
50
|
+
- README
|
51
|
+
- CHANGES
|
52
|
+
- MANIFEST
|
53
|
+
executables: []
|
54
|
+
|
55
|
+
extensions: []
|
56
|
+
|
57
|
+
requirements: []
|
58
|
+
|
59
|
+
dependencies:
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: win32-ipc
|
62
|
+
version_requirement:
|
63
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 0.5.0
|
68
|
+
version:
|