win32-mutex 0.4.1 → 0.4.2
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.
- checksums.yaml +7 -0
- data/CHANGES +58 -53
- data/MANIFEST +8 -8
- data/README +51 -51
- data/Rakefile +36 -31
- data/examples/example_win32_mutex.rb +64 -64
- data/lib/win32/mutex.rb +146 -146
- data/test/test_win32_mutex.rb +85 -85
- data/win32-mutex.gemspec +29 -27
- metadata +30 -21
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6b251ba3b27d23aec7948bca16d023ae9582ac4c
|
4
|
+
data.tar.gz: 12e840ea6969ea066381de5647a73cd69aabf413
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ad2a8b1b7b60fb50d0a58bda465c61b3b02f281ff2d2dbcc540dbcf30511846f8a384a3428b79ecdfcaed25f5fcca55ec3467627075b21c790d657baaebcfff7
|
7
|
+
data.tar.gz: 55123e27d398edfebc923f632d69060beb496f2012989d5d97143a65a855f2ed067e318977324df194b29fbb1779bd190348e00b9d54f6f909e524889e5a8652
|
data/CHANGES
CHANGED
@@ -1,53 +1,58 @@
|
|
1
|
-
== 0.4.
|
2
|
-
* Fixed
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
*
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
*
|
13
|
-
*
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
*
|
18
|
-
*
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
*
|
23
|
-
*
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
*
|
28
|
-
*
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
*
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
*
|
37
|
-
*
|
38
|
-
|
39
|
-
== 0.2.
|
40
|
-
*
|
41
|
-
*
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
*
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
*
|
1
|
+
== 0.4.2 - 21-Oct-2013
|
2
|
+
* Fixed INVALID_HANDLE_VALUE constant for 64-bit Ruby.
|
3
|
+
* Added Rake as a development dependency.
|
4
|
+
* Updated gem:create task for Rubygems 2.
|
5
|
+
|
6
|
+
== 0.4.1 - 10-Apr-2013
|
7
|
+
* Fixed HANDLE type in underlying FFI code. This affects 64 bit versions
|
8
|
+
of Ruby.
|
9
|
+
|
10
|
+
== 0.4.0 - 10-Jul-2012
|
11
|
+
* Converted to FFI.
|
12
|
+
* Now requires Ruby 1.9 or later.
|
13
|
+
* Removed the Error class. If a Windows function fails it raises the
|
14
|
+
appropriate SystemCallError (Errno::).
|
15
|
+
|
16
|
+
== 0.3.2 - 18-Mar-2011
|
17
|
+
* Updates to the Rakefile and gemspec.
|
18
|
+
* One test file change for Ruby 1.9.
|
19
|
+
|
20
|
+
== 0.3.1 - 8-Aug-2009
|
21
|
+
* Changed license to Artistic 2.0.
|
22
|
+
* Updated the gemspec, including addition of license and description update.
|
23
|
+
* Renamed the test and example files.
|
24
|
+
* Added test-unit, win32-process and win32-mmap as development dependencies.
|
25
|
+
|
26
|
+
== 0.3.0 - 4-May-2007
|
27
|
+
* Now pure Ruby.
|
28
|
+
* Both the Mutex.new and Mutex.open methods now accept a block, and
|
29
|
+
automatically close the associated handle at the end of the block.
|
30
|
+
* The Mutex.new method now accepts an optional third argument that controls
|
31
|
+
whether the mutex object can be inherited by other processes.
|
32
|
+
* Added a gemspec.
|
33
|
+
* Added a Rakefile, including tasks for installation and testing.
|
34
|
+
* Removed the doc/mutext.txt file. The documentation is now inlined via RDoc.
|
35
|
+
There is also some documentation in the README file.
|
36
|
+
* The mutex_test.rb script was updated and bugs were fixed.
|
37
|
+
* Now requires the windows-pr package.
|
38
|
+
|
39
|
+
== 0.2.2 - 29-May-2005
|
40
|
+
* Now Unicode friendly.
|
41
|
+
* Removed the mutex.rd file. The mutex.txt file is now rdoc friendly.
|
42
|
+
* Added some tests and tweaked the test setup.
|
43
|
+
|
44
|
+
== 0.2.1 - 1-Mar-2005
|
45
|
+
* Moved the 'examples' directory to the toplevel directory.
|
46
|
+
* Made the CHANGES and README files rdoc friendly.
|
47
|
+
|
48
|
+
== 0.2.0 - 18-Jul-2004
|
49
|
+
* Updated to use the newer allocation framework. This means that, as of this
|
50
|
+
release, this package requires Ruby 1.8.0 or later.
|
51
|
+
* Fixed a minor bug in the initialization function where an expected error
|
52
|
+
might not be raised.
|
53
|
+
* Added tests and documentation for Mutex.open(). This was in the last
|
54
|
+
version, but I forgot to document or test it.
|
55
|
+
* Moved the test.rb script to doc/examples
|
56
|
+
|
57
|
+
== 0.1.0 - 3-May-2004
|
58
|
+
* Initial release
|
data/MANIFEST
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
* CHANGES
|
2
|
-
* INSTALL
|
3
|
-
* MANIFEST
|
4
|
-
* Rakefile
|
5
|
-
* win32-mutex.gemspec
|
6
|
-
* examples/mutex_test.rb
|
7
|
-
* lib/win32/mutex.rb
|
8
|
-
* test/test_win32_mutex.rb
|
1
|
+
* CHANGES
|
2
|
+
* INSTALL
|
3
|
+
* MANIFEST
|
4
|
+
* Rakefile
|
5
|
+
* win32-mutex.gemspec
|
6
|
+
* examples/mutex_test.rb
|
7
|
+
* lib/win32/mutex.rb
|
8
|
+
* test/test_win32_mutex.rb
|
data/README
CHANGED
@@ -1,51 +1,51 @@
|
|
1
|
-
== Brief Description
|
2
|
-
Interface for Mutexes on MS Windows.
|
3
|
-
|
4
|
-
== Prerequisites
|
5
|
-
win32-ipc 0.6.0 or later
|
6
|
-
|
7
|
-
== Installation
|
8
|
-
gem install win32-mutex
|
9
|
-
|
10
|
-
== Synopsis
|
11
|
-
require 'win32/mutex'
|
12
|
-
|
13
|
-
# Do not leave out the 'Win32::', otherwise you're using Ruby's Mutex class.
|
14
|
-
Win32::Mutex.new(false, 'test') do |m|
|
15
|
-
# Do stuff
|
16
|
-
m.release
|
17
|
-
end
|
18
|
-
|
19
|
-
== Documentation
|
20
|
-
The mutex.rb file contains inline RDoc documentation. If you installed
|
21
|
-
this file as a gem, then you have the docs.
|
22
|
-
|
23
|
-
For an example of win32-mutex in action, look at the example_win32_mutex.rb
|
24
|
-
file in the 'examples' directory. You can also run the 'examples' rake task.
|
25
|
-
|
26
|
-
== Notes
|
27
|
-
The Mutex class is a subclass of Win32::Ipc (win32-ipc). This library
|
28
|
-
require's the win32-ipc library internally. You don't need to explicitly
|
29
|
-
call it.
|
30
|
-
|
31
|
-
== Acknowledgements
|
32
|
-
Originally adapted from the Win32::Mutex Perl module.
|
33
|
-
|
34
|
-
== Known Bugs
|
35
|
-
None that I know of. Please log any other bug reports on the
|
36
|
-
project page at https://github.com/djberg96/win32-mutex.
|
37
|
-
|
38
|
-
== License
|
39
|
-
Artistic 2.0
|
40
|
-
|
41
|
-
== Copyright
|
42
|
-
(C) 2003-2013 Daniel J. Berger, All Rights Reserved
|
43
|
-
|
44
|
-
== Warranty
|
45
|
-
This package is provided "as is" and without any express or
|
46
|
-
implied warranties, including, without limitation, the implied
|
47
|
-
warranties of merchantability and fitness for a particular purpose.
|
48
|
-
|
49
|
-
== Authors
|
50
|
-
Daniel J. Berger
|
51
|
-
Park Heesob
|
1
|
+
== Brief Description
|
2
|
+
Interface for Mutexes on MS Windows.
|
3
|
+
|
4
|
+
== Prerequisites
|
5
|
+
win32-ipc 0.6.0 or later
|
6
|
+
|
7
|
+
== Installation
|
8
|
+
gem install win32-mutex
|
9
|
+
|
10
|
+
== Synopsis
|
11
|
+
require 'win32/mutex'
|
12
|
+
|
13
|
+
# Do not leave out the 'Win32::', otherwise you're using Ruby's Mutex class.
|
14
|
+
Win32::Mutex.new(false, 'test') do |m|
|
15
|
+
# Do stuff
|
16
|
+
m.release
|
17
|
+
end
|
18
|
+
|
19
|
+
== Documentation
|
20
|
+
The mutex.rb file contains inline RDoc documentation. If you installed
|
21
|
+
this file as a gem, then you have the docs.
|
22
|
+
|
23
|
+
For an example of win32-mutex in action, look at the example_win32_mutex.rb
|
24
|
+
file in the 'examples' directory. You can also run the 'examples' rake task.
|
25
|
+
|
26
|
+
== Notes
|
27
|
+
The Mutex class is a subclass of Win32::Ipc (win32-ipc). This library
|
28
|
+
require's the win32-ipc library internally. You don't need to explicitly
|
29
|
+
call it.
|
30
|
+
|
31
|
+
== Acknowledgements
|
32
|
+
Originally adapted from the Win32::Mutex Perl module.
|
33
|
+
|
34
|
+
== Known Bugs
|
35
|
+
None that I know of. Please log any other bug reports on the
|
36
|
+
project page at https://github.com/djberg96/win32-mutex.
|
37
|
+
|
38
|
+
== License
|
39
|
+
Artistic 2.0
|
40
|
+
|
41
|
+
== Copyright
|
42
|
+
(C) 2003-2013 Daniel J. Berger, All Rights Reserved
|
43
|
+
|
44
|
+
== Warranty
|
45
|
+
This package is provided "as is" and without any express or
|
46
|
+
implied warranties, including, without limitation, the implied
|
47
|
+
warranties of merchantability and fitness for a particular purpose.
|
48
|
+
|
49
|
+
== Authors
|
50
|
+
Daniel J. Berger
|
51
|
+
Park Heesob
|
data/Rakefile
CHANGED
@@ -1,31 +1,36 @@
|
|
1
|
-
require 'rake'
|
2
|
-
require 'rake/testtask'
|
3
|
-
require 'rake/clean'
|
4
|
-
|
5
|
-
CLEAN.include("**/*.gem")
|
6
|
-
|
7
|
-
namespace :gem do
|
8
|
-
desc 'Create the win32-mutex gem'
|
9
|
-
task :create => [:clean] do
|
10
|
-
spec = eval(IO.read('win32-mutex.gemspec'))
|
11
|
-
Gem::
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/clean'
|
4
|
+
|
5
|
+
CLEAN.include("**/*.gem")
|
6
|
+
|
7
|
+
namespace :gem do
|
8
|
+
desc 'Create the win32-mutex gem'
|
9
|
+
task :create => [:clean] do
|
10
|
+
spec = eval(IO.read('win32-mutex.gemspec'))
|
11
|
+
if Gem::VERSION < "2.0.0"
|
12
|
+
Gem::Builder.new(spec).build
|
13
|
+
else
|
14
|
+
require 'rubygems/package'
|
15
|
+
Gem::Package.build(spec)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'Install the win32-mutex gem'
|
20
|
+
task :install => [:create] do
|
21
|
+
file = Dir["*.gem"].first
|
22
|
+
sh "gem install #{file}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
desc 'Run the example program'
|
27
|
+
task :example do
|
28
|
+
ruby '-Ilib examples/example_win32_mutex.rb'
|
29
|
+
end
|
30
|
+
|
31
|
+
Rake::TestTask.new do |t|
|
32
|
+
t.verbose = true
|
33
|
+
t.warning = true
|
34
|
+
end
|
35
|
+
|
36
|
+
task :default => :test
|
@@ -1,65 +1,65 @@
|
|
1
|
-
##############################################################
|
2
|
-
# example_win32_mutex.rb
|
3
|
-
#
|
4
|
-
# A test script for general futzing. Modify as you see fit.
|
5
|
-
# This test script requires win32-process and win32-mmap.
|
6
|
-
##############################################################
|
7
|
-
MUTEXNAME = "This is a very long name"
|
8
|
-
|
9
|
-
require 'win32/mutex'
|
10
|
-
require 'win32/process'
|
11
|
-
require 'win32/mmap'
|
12
|
-
include Win32
|
13
|
-
|
14
|
-
pid = Process.fork
|
15
|
-
|
16
|
-
# child_1
|
17
|
-
if pid.nil?
|
18
|
-
mm = MMap.open('test')
|
19
|
-
mx = Win32::Mutex.open(MUTEXNAME)
|
20
|
-
5.times{
|
21
|
-
mx.wait
|
22
|
-
puts "child_1 wait "
|
23
|
-
mm.gvalue += 123
|
24
|
-
sleep 1
|
25
|
-
mm.gvalue -= 123
|
26
|
-
mx.release
|
27
|
-
puts "child_1 release "
|
28
|
-
}
|
29
|
-
exit 1
|
30
|
-
end
|
31
|
-
|
32
|
-
pid2 = Process.fork
|
33
|
-
|
34
|
-
# child_2
|
35
|
-
if pid2.nil?
|
36
|
-
mm = MMap.open('test')
|
37
|
-
mx = Win32::Mutex.open(MUTEXNAME)
|
38
|
-
4.times{
|
39
|
-
mx.wait
|
40
|
-
puts "child_2 wait "
|
41
|
-
mm.gvalue += 456
|
42
|
-
sleep 2
|
43
|
-
mm.gvalue -= 456
|
44
|
-
mx.release
|
45
|
-
puts "child_2 release "
|
46
|
-
}
|
47
|
-
exit 1
|
48
|
-
end
|
49
|
-
|
50
|
-
#parent
|
51
|
-
mm = MMap.new(:size => 1024, :name => 'test', :inherit => true)
|
52
|
-
mm.gvalue = 5
|
53
|
-
mx = Win32::Mutex.new(false, MUTEXNAME)
|
54
|
-
|
55
|
-
3.times{
|
56
|
-
mx.wait
|
57
|
-
puts "parent wait"
|
58
|
-
sleep 5
|
59
|
-
printf("Value of GValue=%d\n", mm.gvalue)
|
60
|
-
mx.release
|
61
|
-
puts "parent release"
|
62
|
-
}
|
63
|
-
|
64
|
-
p Process.waitpid2(pid)
|
1
|
+
##############################################################
|
2
|
+
# example_win32_mutex.rb
|
3
|
+
#
|
4
|
+
# A test script for general futzing. Modify as you see fit.
|
5
|
+
# This test script requires win32-process and win32-mmap.
|
6
|
+
##############################################################
|
7
|
+
MUTEXNAME = "This is a very long name"
|
8
|
+
|
9
|
+
require 'win32/mutex'
|
10
|
+
require 'win32/process'
|
11
|
+
require 'win32/mmap'
|
12
|
+
include Win32
|
13
|
+
|
14
|
+
pid = Process.fork
|
15
|
+
|
16
|
+
# child_1
|
17
|
+
if pid.nil?
|
18
|
+
mm = MMap.open('test')
|
19
|
+
mx = Win32::Mutex.open(MUTEXNAME)
|
20
|
+
5.times{
|
21
|
+
mx.wait
|
22
|
+
puts "child_1 wait "
|
23
|
+
mm.gvalue += 123
|
24
|
+
sleep 1
|
25
|
+
mm.gvalue -= 123
|
26
|
+
mx.release
|
27
|
+
puts "child_1 release "
|
28
|
+
}
|
29
|
+
exit 1
|
30
|
+
end
|
31
|
+
|
32
|
+
pid2 = Process.fork
|
33
|
+
|
34
|
+
# child_2
|
35
|
+
if pid2.nil?
|
36
|
+
mm = MMap.open('test')
|
37
|
+
mx = Win32::Mutex.open(MUTEXNAME)
|
38
|
+
4.times{
|
39
|
+
mx.wait
|
40
|
+
puts "child_2 wait "
|
41
|
+
mm.gvalue += 456
|
42
|
+
sleep 2
|
43
|
+
mm.gvalue -= 456
|
44
|
+
mx.release
|
45
|
+
puts "child_2 release "
|
46
|
+
}
|
47
|
+
exit 1
|
48
|
+
end
|
49
|
+
|
50
|
+
#parent
|
51
|
+
mm = MMap.new(:size => 1024, :name => 'test', :inherit => true)
|
52
|
+
mm.gvalue = 5
|
53
|
+
mx = Win32::Mutex.new(false, MUTEXNAME)
|
54
|
+
|
55
|
+
3.times{
|
56
|
+
mx.wait
|
57
|
+
puts "parent wait"
|
58
|
+
sleep 5
|
59
|
+
printf("Value of GValue=%d\n", mm.gvalue)
|
60
|
+
mx.release
|
61
|
+
puts "parent release"
|
62
|
+
}
|
63
|
+
|
64
|
+
p Process.waitpid2(pid)
|
65
65
|
p Process.waitpid2(pid2)
|
data/lib/win32/mutex.rb
CHANGED
@@ -1,146 +1,146 @@
|
|
1
|
-
require 'win32/ipc'
|
2
|
-
|
3
|
-
# The Win32 module serves as a namespace only.
|
4
|
-
module Win32
|
5
|
-
|
6
|
-
# The Mutex class encapsulates Windows mutex objects.
|
7
|
-
class Mutex < Ipc
|
8
|
-
typedef :ulong, :dword
|
9
|
-
typedef :uintptr_t, :handle
|
10
|
-
|
11
|
-
ffi_lib :kernel32
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
class SecurityAttributes < FFI::Struct
|
16
|
-
layout(
|
17
|
-
:nLength, :dword,
|
18
|
-
:lpSecurityDescriptor, :pointer,
|
19
|
-
:bInheritHandle, :bool
|
20
|
-
)
|
21
|
-
end
|
22
|
-
|
23
|
-
attach_function :CreateMutexW, [:pointer, :bool, :buffer_in], :handle
|
24
|
-
attach_function :OpenMutexW, [:dword, :bool, :buffer_in], :handle
|
25
|
-
attach_function :ReleaseMutex, [:handle], :bool
|
26
|
-
|
27
|
-
private_class_method :CreateMutexW, :OpenMutexW, :ReleaseMutex
|
28
|
-
|
29
|
-
INVALID_HANDLE_VALUE =
|
30
|
-
MUTEX_ALL_ACCESS = 0x1F0001
|
31
|
-
|
32
|
-
public
|
33
|
-
|
34
|
-
# The version of the win32-mutex library
|
35
|
-
VERSION = '0.4.
|
36
|
-
|
37
|
-
# The name of the mutex object.
|
38
|
-
attr_reader :name
|
39
|
-
|
40
|
-
# Creates and returns new Mutex object. If +name+ is omitted, the
|
41
|
-
# Mutex object is created without a name, i.e. it's anonymous.
|
42
|
-
#
|
43
|
-
# If the +initial_owner+ value is true and the caller created the mutex,
|
44
|
-
# the calling thread obtains initial ownership of the mutex object.
|
45
|
-
# Otherwise, the calling thread does not obtain ownership of the mutex.
|
46
|
-
# This value is false by default.
|
47
|
-
#
|
48
|
-
# If +name+ is provided and it already exists, then it is opened
|
49
|
-
# instead, and the +initial_count+ and +max_count+ parameters are
|
50
|
-
# ignored.
|
51
|
-
#
|
52
|
-
# The +inherit+ attribute determines whether or not the mutex can
|
53
|
-
# be inherited by child processes.
|
54
|
-
#
|
55
|
-
def initialize(initial_owner=false, name=nil, inherit=true)
|
56
|
-
@initial_owner = initial_owner
|
57
|
-
@name = name
|
58
|
-
@inherit = inherit
|
59
|
-
|
60
|
-
if inherit
|
61
|
-
sec = SecurityAttributes.new
|
62
|
-
sec[:nLength] = SecurityAttributes.size
|
63
|
-
sec[:bInheritHandle] = true
|
64
|
-
else
|
65
|
-
sec = nil
|
66
|
-
end
|
67
|
-
|
68
|
-
if name && name.encoding.to_s != 'UTF-16LE'
|
69
|
-
name = name + 0.chr
|
70
|
-
name.encode!('UTF-16LE')
|
71
|
-
end
|
72
|
-
|
73
|
-
handle = CreateMutexW(sec, initial_owner, name)
|
74
|
-
|
75
|
-
if handle == 0 || handle == INVALID_HANDLE_VALUE
|
76
|
-
raise SystemCallError.new("CreateMutex", FFI.errno)
|
77
|
-
end
|
78
|
-
|
79
|
-
super(handle)
|
80
|
-
|
81
|
-
if block_given?
|
82
|
-
begin
|
83
|
-
yield self
|
84
|
-
ensure
|
85
|
-
close # From superclass
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
# Open an existing Mutex by +name+. The +inherit+ argument sets
|
91
|
-
# whether or not the object was opened such that a process created by the
|
92
|
-
# CreateProcess() function (a Windows API function) can inherit the
|
93
|
-
# handle. The default is true.
|
94
|
-
#
|
95
|
-
# This method is essentially identical to Mutex.new, except that the
|
96
|
-
# option for +initial_owner+ cannot be set (since it is already set).
|
97
|
-
# Also, this method will raise a Mutex::Error if the mutex doesn't
|
98
|
-
# already exist.
|
99
|
-
#
|
100
|
-
# If you want "open or create" semantics, then use Mutex.new.
|
101
|
-
#
|
102
|
-
def self.open(name, inherit=true, &block)
|
103
|
-
if name.encoding.to_s != 'UTF-16LE'
|
104
|
-
name = name + 0.chr
|
105
|
-
name.encode!('UTF-16LE')
|
106
|
-
end
|
107
|
-
|
108
|
-
begin
|
109
|
-
# The OpenMutex() call here is strictly to force an error if the user
|
110
|
-
# tries to open a mutex that doesn't already exist.
|
111
|
-
handle = OpenMutexW(MUTEX_ALL_ACCESS, inherit, name)
|
112
|
-
|
113
|
-
if handle == 0 || handle == INVALID_HANDLE_VALUE
|
114
|
-
raise SystemCallError.new("OpenMutex", FFI.errno)
|
115
|
-
end
|
116
|
-
ensure
|
117
|
-
CloseHandle(handle) if handle && handle > 0
|
118
|
-
end
|
119
|
-
|
120
|
-
self.new(false, name, inherit, &block)
|
121
|
-
end
|
122
|
-
|
123
|
-
# Releases ownership of the mutex.
|
124
|
-
#
|
125
|
-
def release
|
126
|
-
unless ReleaseMutex(@handle)
|
127
|
-
raise SystemCallError.new("ReleaseMutex", FFI.errno)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
# Returns whether or not the calling thread has initial ownership of
|
132
|
-
# the mutex object.
|
133
|
-
#
|
134
|
-
def initial_owner?
|
135
|
-
@initial_owner
|
136
|
-
end
|
137
|
-
|
138
|
-
# Returns whether or not the object was opened such that a process
|
139
|
-
# created by the CreateProcess() function (a Windows API function) can
|
140
|
-
# inherit the handle. The default is true.
|
141
|
-
#
|
142
|
-
def inheritable?
|
143
|
-
@inherit
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
1
|
+
require 'win32/ipc'
|
2
|
+
|
3
|
+
# The Win32 module serves as a namespace only.
|
4
|
+
module Win32
|
5
|
+
|
6
|
+
# The Mutex class encapsulates Windows mutex objects.
|
7
|
+
class Mutex < Ipc
|
8
|
+
typedef :ulong, :dword
|
9
|
+
typedef :uintptr_t, :handle
|
10
|
+
|
11
|
+
ffi_lib :kernel32
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
class SecurityAttributes < FFI::Struct
|
16
|
+
layout(
|
17
|
+
:nLength, :dword,
|
18
|
+
:lpSecurityDescriptor, :pointer,
|
19
|
+
:bInheritHandle, :bool
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
attach_function :CreateMutexW, [:pointer, :bool, :buffer_in], :handle
|
24
|
+
attach_function :OpenMutexW, [:dword, :bool, :buffer_in], :handle
|
25
|
+
attach_function :ReleaseMutex, [:handle], :bool
|
26
|
+
|
27
|
+
private_class_method :CreateMutexW, :OpenMutexW, :ReleaseMutex
|
28
|
+
|
29
|
+
INVALID_HANDLE_VALUE = FFI::Pointer.new(-1).address
|
30
|
+
MUTEX_ALL_ACCESS = 0x1F0001
|
31
|
+
|
32
|
+
public
|
33
|
+
|
34
|
+
# The version of the win32-mutex library
|
35
|
+
VERSION = '0.4.2'
|
36
|
+
|
37
|
+
# The name of the mutex object.
|
38
|
+
attr_reader :name
|
39
|
+
|
40
|
+
# Creates and returns new Mutex object. If +name+ is omitted, the
|
41
|
+
# Mutex object is created without a name, i.e. it's anonymous.
|
42
|
+
#
|
43
|
+
# If the +initial_owner+ value is true and the caller created the mutex,
|
44
|
+
# the calling thread obtains initial ownership of the mutex object.
|
45
|
+
# Otherwise, the calling thread does not obtain ownership of the mutex.
|
46
|
+
# This value is false by default.
|
47
|
+
#
|
48
|
+
# If +name+ is provided and it already exists, then it is opened
|
49
|
+
# instead, and the +initial_count+ and +max_count+ parameters are
|
50
|
+
# ignored.
|
51
|
+
#
|
52
|
+
# The +inherit+ attribute determines whether or not the mutex can
|
53
|
+
# be inherited by child processes.
|
54
|
+
#
|
55
|
+
def initialize(initial_owner=false, name=nil, inherit=true)
|
56
|
+
@initial_owner = initial_owner
|
57
|
+
@name = name
|
58
|
+
@inherit = inherit
|
59
|
+
|
60
|
+
if inherit
|
61
|
+
sec = SecurityAttributes.new
|
62
|
+
sec[:nLength] = SecurityAttributes.size
|
63
|
+
sec[:bInheritHandle] = true
|
64
|
+
else
|
65
|
+
sec = nil
|
66
|
+
end
|
67
|
+
|
68
|
+
if name && name.encoding.to_s != 'UTF-16LE'
|
69
|
+
name = name + 0.chr
|
70
|
+
name.encode!('UTF-16LE')
|
71
|
+
end
|
72
|
+
|
73
|
+
handle = CreateMutexW(sec, initial_owner, name)
|
74
|
+
|
75
|
+
if handle == 0 || handle == INVALID_HANDLE_VALUE
|
76
|
+
raise SystemCallError.new("CreateMutex", FFI.errno)
|
77
|
+
end
|
78
|
+
|
79
|
+
super(handle)
|
80
|
+
|
81
|
+
if block_given?
|
82
|
+
begin
|
83
|
+
yield self
|
84
|
+
ensure
|
85
|
+
close # From superclass
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Open an existing Mutex by +name+. The +inherit+ argument sets
|
91
|
+
# whether or not the object was opened such that a process created by the
|
92
|
+
# CreateProcess() function (a Windows API function) can inherit the
|
93
|
+
# handle. The default is true.
|
94
|
+
#
|
95
|
+
# This method is essentially identical to Mutex.new, except that the
|
96
|
+
# option for +initial_owner+ cannot be set (since it is already set).
|
97
|
+
# Also, this method will raise a Mutex::Error if the mutex doesn't
|
98
|
+
# already exist.
|
99
|
+
#
|
100
|
+
# If you want "open or create" semantics, then use Mutex.new.
|
101
|
+
#
|
102
|
+
def self.open(name, inherit=true, &block)
|
103
|
+
if name.encoding.to_s != 'UTF-16LE'
|
104
|
+
name = name + 0.chr
|
105
|
+
name.encode!('UTF-16LE')
|
106
|
+
end
|
107
|
+
|
108
|
+
begin
|
109
|
+
# The OpenMutex() call here is strictly to force an error if the user
|
110
|
+
# tries to open a mutex that doesn't already exist.
|
111
|
+
handle = OpenMutexW(MUTEX_ALL_ACCESS, inherit, name)
|
112
|
+
|
113
|
+
if handle == 0 || handle == INVALID_HANDLE_VALUE
|
114
|
+
raise SystemCallError.new("OpenMutex", FFI.errno)
|
115
|
+
end
|
116
|
+
ensure
|
117
|
+
CloseHandle(handle) if handle && handle > 0
|
118
|
+
end
|
119
|
+
|
120
|
+
self.new(false, name, inherit, &block)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Releases ownership of the mutex.
|
124
|
+
#
|
125
|
+
def release
|
126
|
+
unless ReleaseMutex(@handle)
|
127
|
+
raise SystemCallError.new("ReleaseMutex", FFI.errno)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Returns whether or not the calling thread has initial ownership of
|
132
|
+
# the mutex object.
|
133
|
+
#
|
134
|
+
def initial_owner?
|
135
|
+
@initial_owner
|
136
|
+
end
|
137
|
+
|
138
|
+
# Returns whether or not the object was opened such that a process
|
139
|
+
# created by the CreateProcess() function (a Windows API function) can
|
140
|
+
# inherit the handle. The default is true.
|
141
|
+
#
|
142
|
+
def inheritable?
|
143
|
+
@inherit
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
data/test/test_win32_mutex.rb
CHANGED
@@ -1,85 +1,85 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
#######################################################################
|
3
|
-
# test_win32_mutex.rb
|
4
|
-
#
|
5
|
-
# Test suite for the win32-mutex library. This test suite should be
|
6
|
-
# run via the 'rake test' task.
|
7
|
-
#######################################################################
|
8
|
-
require 'test-unit'
|
9
|
-
require 'win32/mutex'
|
10
|
-
|
11
|
-
class TC_Win32_Mutex < Test::Unit::TestCase
|
12
|
-
def setup
|
13
|
-
@mutex = Win32::Mutex.new(true, 'test')
|
14
|
-
@umutex = Win32::Mutex.new(false, 'Ηελλας')
|
15
|
-
end
|
16
|
-
|
17
|
-
test "version is set to expected value" do
|
18
|
-
assert_equal('0.4.
|
19
|
-
end
|
20
|
-
|
21
|
-
test "constructor with no arguments works as expected" do
|
22
|
-
mutex = nil
|
23
|
-
assert_nothing_raised{ mutex = Win32::Mutex.new }
|
24
|
-
mutex.close
|
25
|
-
end
|
26
|
-
|
27
|
-
test "default attributes are set to expected values" do
|
28
|
-
mutex = Win32::Mutex.new
|
29
|
-
assert_false(mutex.initial_owner?)
|
30
|
-
assert_true(mutex.inheritable?)
|
31
|
-
assert_nil(mutex.name)
|
32
|
-
mutex.close
|
33
|
-
end
|
34
|
-
|
35
|
-
test "open method works as expected" do
|
36
|
-
assert_respond_to(Win32::Mutex, :open)
|
37
|
-
assert_nothing_raised{ Win32::Mutex.open('test'){} }
|
38
|
-
assert_nothing_raised{ Win32::Mutex.open('Ηελλας'){} }
|
39
|
-
end
|
40
|
-
|
41
|
-
test "attempting to open an unknown mutex raises an error" do
|
42
|
-
assert_raise(Errno::ENOENT){ Win32::Mutex.open('bogus'){} }
|
43
|
-
end
|
44
|
-
|
45
|
-
test "release method works as expected" do
|
46
|
-
assert_respond_to(@mutex, :release)
|
47
|
-
assert_nothing_raised{ @mutex.release }
|
48
|
-
end
|
49
|
-
|
50
|
-
test "initial_owner? works as expected and returns expected value" do
|
51
|
-
assert_respond_to(@mutex, :initial_owner?)
|
52
|
-
assert_true(@mutex.initial_owner?)
|
53
|
-
assert_false(@umutex.initial_owner?)
|
54
|
-
end
|
55
|
-
|
56
|
-
test "inheritable? works as expected and returns expected value" do
|
57
|
-
assert_respond_to(@mutex, :inheritable?)
|
58
|
-
assert_true(@mutex.inheritable?)
|
59
|
-
end
|
60
|
-
|
61
|
-
test "wait method was inherited" do
|
62
|
-
assert_respond_to(@mutex, :wait)
|
63
|
-
end
|
64
|
-
|
65
|
-
test "wait_any method was inherited" do
|
66
|
-
assert_respond_to(@mutex, :wait_any)
|
67
|
-
end
|
68
|
-
|
69
|
-
test "wait_all method was inherited" do
|
70
|
-
assert_respond_to(@mutex, :wait_all)
|
71
|
-
end
|
72
|
-
|
73
|
-
test "ffi functions are private" do
|
74
|
-
assert_not_respond_to(Win32::Mutex, :CreateMutexW)
|
75
|
-
assert_not_respond_to(Win32::Mutex, :OpenMutexW)
|
76
|
-
assert_not_respond_to(Win32::Mutex, :ReleaseMutex)
|
77
|
-
end
|
78
|
-
|
79
|
-
def teardown
|
80
|
-
@mutex.close
|
81
|
-
@umutex.close
|
82
|
-
@mutex = nil
|
83
|
-
@umutex = nil
|
84
|
-
end
|
85
|
-
end
|
1
|
+
# encoding: utf-8
|
2
|
+
#######################################################################
|
3
|
+
# test_win32_mutex.rb
|
4
|
+
#
|
5
|
+
# Test suite for the win32-mutex library. This test suite should be
|
6
|
+
# run via the 'rake test' task.
|
7
|
+
#######################################################################
|
8
|
+
require 'test-unit'
|
9
|
+
require 'win32/mutex'
|
10
|
+
|
11
|
+
class TC_Win32_Mutex < Test::Unit::TestCase
|
12
|
+
def setup
|
13
|
+
@mutex = Win32::Mutex.new(true, 'test')
|
14
|
+
@umutex = Win32::Mutex.new(false, 'Ηελλας')
|
15
|
+
end
|
16
|
+
|
17
|
+
test "version is set to expected value" do
|
18
|
+
assert_equal('0.4.2', Win32::Mutex::VERSION)
|
19
|
+
end
|
20
|
+
|
21
|
+
test "constructor with no arguments works as expected" do
|
22
|
+
mutex = nil
|
23
|
+
assert_nothing_raised{ mutex = Win32::Mutex.new }
|
24
|
+
mutex.close
|
25
|
+
end
|
26
|
+
|
27
|
+
test "default attributes are set to expected values" do
|
28
|
+
mutex = Win32::Mutex.new
|
29
|
+
assert_false(mutex.initial_owner?)
|
30
|
+
assert_true(mutex.inheritable?)
|
31
|
+
assert_nil(mutex.name)
|
32
|
+
mutex.close
|
33
|
+
end
|
34
|
+
|
35
|
+
test "open method works as expected" do
|
36
|
+
assert_respond_to(Win32::Mutex, :open)
|
37
|
+
assert_nothing_raised{ Win32::Mutex.open('test'){} }
|
38
|
+
assert_nothing_raised{ Win32::Mutex.open('Ηελλας'){} }
|
39
|
+
end
|
40
|
+
|
41
|
+
test "attempting to open an unknown mutex raises an error" do
|
42
|
+
assert_raise(Errno::ENOENT){ Win32::Mutex.open('bogus'){} }
|
43
|
+
end
|
44
|
+
|
45
|
+
test "release method works as expected" do
|
46
|
+
assert_respond_to(@mutex, :release)
|
47
|
+
assert_nothing_raised{ @mutex.release }
|
48
|
+
end
|
49
|
+
|
50
|
+
test "initial_owner? works as expected and returns expected value" do
|
51
|
+
assert_respond_to(@mutex, :initial_owner?)
|
52
|
+
assert_true(@mutex.initial_owner?)
|
53
|
+
assert_false(@umutex.initial_owner?)
|
54
|
+
end
|
55
|
+
|
56
|
+
test "inheritable? works as expected and returns expected value" do
|
57
|
+
assert_respond_to(@mutex, :inheritable?)
|
58
|
+
assert_true(@mutex.inheritable?)
|
59
|
+
end
|
60
|
+
|
61
|
+
test "wait method was inherited" do
|
62
|
+
assert_respond_to(@mutex, :wait)
|
63
|
+
end
|
64
|
+
|
65
|
+
test "wait_any method was inherited" do
|
66
|
+
assert_respond_to(@mutex, :wait_any)
|
67
|
+
end
|
68
|
+
|
69
|
+
test "wait_all method was inherited" do
|
70
|
+
assert_respond_to(@mutex, :wait_all)
|
71
|
+
end
|
72
|
+
|
73
|
+
test "ffi functions are private" do
|
74
|
+
assert_not_respond_to(Win32::Mutex, :CreateMutexW)
|
75
|
+
assert_not_respond_to(Win32::Mutex, :OpenMutexW)
|
76
|
+
assert_not_respond_to(Win32::Mutex, :ReleaseMutex)
|
77
|
+
end
|
78
|
+
|
79
|
+
def teardown
|
80
|
+
@mutex.close
|
81
|
+
@umutex.close
|
82
|
+
@mutex = nil
|
83
|
+
@umutex = nil
|
84
|
+
end
|
85
|
+
end
|
data/win32-mutex.gemspec
CHANGED
@@ -1,27 +1,29 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
|
3
|
-
Gem::Specification.new do |spec|
|
4
|
-
spec.name = 'win32-mutex'
|
5
|
-
spec.version = '0.4.
|
6
|
-
spec.author = 'Daniel J. Berger'
|
7
|
-
spec.license = 'Artistic 2.0'
|
8
|
-
spec.email = 'djberg96@gmail.com'
|
9
|
-
spec.homepage = 'https://github.com/djberg96/win32-mutex'
|
10
|
-
spec.summary = 'Interface to MS Windows Mutex objects.'
|
11
|
-
spec.test_file = 'test/test_win32_mutex.rb'
|
12
|
-
spec.files = Dir['**/*'].reject{ |f| f.include?('git') }
|
13
|
-
|
14
|
-
spec.rubyforge_project = 'win32utils'
|
15
|
-
spec.extra_rdoc_files = ['README', 'CHANGES', 'MANIFEST']
|
16
|
-
spec.required_ruby_version = '> 1.9.0'
|
17
|
-
|
18
|
-
spec.add_dependency('win32-ipc', '>= 0.6.0')
|
19
|
-
|
20
|
-
|
21
|
-
spec.
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = 'win32-mutex'
|
5
|
+
spec.version = '0.4.2'
|
6
|
+
spec.author = 'Daniel J. Berger'
|
7
|
+
spec.license = 'Artistic 2.0'
|
8
|
+
spec.email = 'djberg96@gmail.com'
|
9
|
+
spec.homepage = 'https://github.com/djberg96/win32-mutex'
|
10
|
+
spec.summary = 'Interface to MS Windows Mutex objects.'
|
11
|
+
spec.test_file = 'test/test_win32_mutex.rb'
|
12
|
+
spec.files = Dir['**/*'].reject{ |f| f.include?('git') }
|
13
|
+
|
14
|
+
spec.rubyforge_project = 'win32utils'
|
15
|
+
spec.extra_rdoc_files = ['README', 'CHANGES', 'MANIFEST']
|
16
|
+
spec.required_ruby_version = '> 1.9.0'
|
17
|
+
|
18
|
+
spec.add_dependency('win32-ipc', '>= 0.6.0')
|
19
|
+
|
20
|
+
spec.add_development_dependency('rake')
|
21
|
+
spec.add_development_dependency('test-unit')
|
22
|
+
|
23
|
+
spec.description = <<-EOF
|
24
|
+
The win32-mutex library provides an interface for creating mutex objects
|
25
|
+
on MS Windows. A mutex object is a synchronization object whose state
|
26
|
+
is set to signaled when it is not owned by any thread, and non-signaled
|
27
|
+
when it is owned.
|
28
|
+
EOF
|
29
|
+
end
|
metadata
CHANGED
@@ -1,52 +1,62 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: win32-mutex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
5
|
-
prerelease:
|
4
|
+
version: 0.4.2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Daniel J. Berger
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-10-21 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: win32-ipc
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: 0.6.0
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: 0.6.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
30
41
|
- !ruby/object:Gem::Dependency
|
31
42
|
name: test-unit
|
32
43
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
44
|
requirements:
|
35
|
-
- -
|
45
|
+
- - '>='
|
36
46
|
- !ruby/object:Gem::Version
|
37
47
|
version: '0'
|
38
48
|
type: :development
|
39
49
|
prerelease: false
|
40
50
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
51
|
requirements:
|
43
|
-
- -
|
52
|
+
- - '>='
|
44
53
|
- !ruby/object:Gem::Version
|
45
54
|
version: '0'
|
46
|
-
description:
|
47
|
-
|
48
|
-
|
49
|
-
|
55
|
+
description: |2
|
56
|
+
The win32-mutex library provides an interface for creating mutex objects
|
57
|
+
on MS Windows. A mutex object is a synchronization object whose state
|
58
|
+
is set to signaled when it is not owned by any thread, and non-signaled
|
59
|
+
when it is owned.
|
50
60
|
email: djberg96@gmail.com
|
51
61
|
executables: []
|
52
62
|
extensions: []
|
@@ -66,27 +76,26 @@ files:
|
|
66
76
|
homepage: https://github.com/djberg96/win32-mutex
|
67
77
|
licenses:
|
68
78
|
- Artistic 2.0
|
79
|
+
metadata: {}
|
69
80
|
post_install_message:
|
70
81
|
rdoc_options: []
|
71
82
|
require_paths:
|
72
83
|
- lib
|
73
84
|
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
-
none: false
|
75
85
|
requirements:
|
76
|
-
- -
|
86
|
+
- - '>'
|
77
87
|
- !ruby/object:Gem::Version
|
78
88
|
version: 1.9.0
|
79
89
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
-
none: false
|
81
90
|
requirements:
|
82
|
-
- -
|
91
|
+
- - '>='
|
83
92
|
- !ruby/object:Gem::Version
|
84
93
|
version: '0'
|
85
94
|
requirements: []
|
86
95
|
rubyforge_project: win32utils
|
87
|
-
rubygems_version: 1.
|
96
|
+
rubygems_version: 2.1.9
|
88
97
|
signing_key:
|
89
|
-
specification_version:
|
98
|
+
specification_version: 4
|
90
99
|
summary: Interface to MS Windows Mutex objects.
|
91
100
|
test_files:
|
92
101
|
- test/test_win32_mutex.rb
|