win32-mutex 0.3.2 → 0.4.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 CHANGED
@@ -1,3 +1,9 @@
1
+ == 0.4.0 - 10-Jul-2012
2
+ * Converted to FFI.
3
+ * Now requires Ruby 1.9 or later.
4
+ * Removed the Error class. If a Windows function fails it raises the
5
+ appropriate SystemCallError (Errno::).
6
+
1
7
  == 0.3.2 - 18-Mar-2011
2
8
  * Updates to the Rakefile and gemspec.
3
9
  * One test file change for Ruby 1.9.
data/MANIFEST CHANGED
@@ -5,4 +5,4 @@
5
5
  * win32-mutex.gemspec
6
6
  * examples/mutex_test.rb
7
7
  * lib/win32/mutex.rb
8
- * test/tc_mutex.rb
8
+ * test/test_win32_mutex.rb
data/README CHANGED
@@ -2,7 +2,7 @@
2
2
  Interface for Mutexes on MS Windows.
3
3
 
4
4
  == Prerequisites
5
- win32-ipc 0.5.0 or later
5
+ win32-ipc 0.6.0 or later
6
6
 
7
7
  == Installation
8
8
  gem install win32-mutex
data/lib/win32/mutex.rb CHANGED
@@ -3,129 +3,141 @@ require 'win32/ipc'
3
3
  # The Win32 module serves as a namespace only.
4
4
  module Win32
5
5
 
6
- # The Mutex class encapsulates Windows mutex objects.
7
- class Mutex < Ipc
8
-
9
- # This is the error raised if any of the Mutex methods fail.
10
- class Error < StandardError; end
11
-
12
- extend Windows::Synchronize
13
- extend Windows::Error
14
- extend Windows::Handle
15
-
16
- # The version of the win32-mutex library
17
- VERSION = '0.3.2'
18
-
19
- # The name of the mutex object.
20
- attr_reader :name
21
-
22
- # Creates and returns new Mutex object. If +name+ is omitted, the
23
- # Mutex object is created without a name, i.e. it's anonymous.
24
- #
25
- # If the +initial_owner+ value is true and the caller created the mutex,
26
- # the calling thread obtains initial ownership of the mutex object.
27
- # Otherwise, the calling thread does not obtain ownership of the mutex.
28
- # This value is false by default.
29
- #
30
- # If +name+ is provided and it already exists, then it is opened
31
- # instead, and the +initial_count+ and +max_count+ parameters are
32
- # ignored.
33
- #
34
- # The +inherit+ attribute determines whether or not the mutex can
35
- # be inherited by child processes.
36
- #
37
- def initialize(initial_owner=false, name=nil, inherit=true)
38
- @initial_owner = initial_owner
39
- @name = name
40
- @inherit = inherit
41
-
42
- # Used to prevent potential segfaults.
43
- if name && !name.is_a?(String)
44
- raise TypeError, 'name must be a string'
45
- end
46
-
47
- if inherit
48
- sec = 0.chr * 12 # sizeof(SECURITY_ATTRIBUTES)
49
- sec[0,4] = [12].pack('L')
50
- sec[8,4] = [1].pack('L') # 1 == TRUE
51
- else
52
- sec = 0
53
- end
54
-
55
- initial = initial_owner ? 1 : 0
56
-
57
- handle = CreateMutex(sec, initial, name)
58
-
59
- if handle == 0 || handle == INVALID_HANDLE_VALUE
60
- raise Error, get_last_error
61
- end
62
-
63
- super(handle)
64
-
65
- if block_given?
66
- begin
67
- yield self
68
- ensure
69
- close # From superclass
70
- end
71
- end
6
+ # The Mutex class encapsulates Windows mutex objects.
7
+ class Mutex < Ipc
8
+ ffi_lib :kernel32
9
+
10
+ private
11
+
12
+ class SecurityAttributes < FFI::Struct
13
+ layout(
14
+ :nLength, :ulong,
15
+ :lpSecurityDescriptor, :pointer,
16
+ :bInheritHandle, :bool
17
+ )
18
+ end
19
+
20
+ attach_function :CreateMutexW, [:pointer, :bool, :buffer_in], :ulong
21
+ attach_function :OpenMutexW, [:ulong, :bool, :buffer_in], :ulong
22
+ attach_function :ReleaseMutex, [:ulong], :bool
23
+
24
+ private_class_method :CreateMutexW, :OpenMutexW, :ReleaseMutex
25
+
26
+ INVALID_HANDLE_VALUE = 0xFFFFFFFF
27
+ MUTEX_ALL_ACCESS = 0x1F0001
28
+
29
+ public
30
+
31
+ # The version of the win32-mutex library
32
+ VERSION = '0.4.0'
33
+
34
+ # The name of the mutex object.
35
+ attr_reader :name
36
+
37
+ # Creates and returns new Mutex object. If +name+ is omitted, the
38
+ # Mutex object is created without a name, i.e. it's anonymous.
39
+ #
40
+ # If the +initial_owner+ value is true and the caller created the mutex,
41
+ # the calling thread obtains initial ownership of the mutex object.
42
+ # Otherwise, the calling thread does not obtain ownership of the mutex.
43
+ # This value is false by default.
44
+ #
45
+ # If +name+ is provided and it already exists, then it is opened
46
+ # instead, and the +initial_count+ and +max_count+ parameters are
47
+ # ignored.
48
+ #
49
+ # The +inherit+ attribute determines whether or not the mutex can
50
+ # be inherited by child processes.
51
+ #
52
+ def initialize(initial_owner=false, name=nil, inherit=true)
53
+ @initial_owner = initial_owner
54
+ @name = name
55
+ @inherit = inherit
56
+
57
+ if inherit
58
+ sec = SecurityAttributes.new
59
+ sec[:nLength] = SecurityAttributes.size
60
+ sec[:bInheritHandle] = true
61
+ else
62
+ sec = nil
72
63
  end
73
64
 
74
- # Open an existing Mutex by +name+. The +inherit+ argument sets
75
- # whether or not the object was opened such that a process created by the
76
- # CreateProcess() function (a Windows API function) can inherit the
77
- # handle. The default is true.
78
- #
79
- # This method is essentially identical to Mutex.new, except that the
80
- # option for +initial_owner+ cannot be set (since it is already set).
81
- # Also, this method will raise a Mutex::Error if the mutex doesn't
82
- # already exist.
83
- #
84
- # If you want "open or create" semantics, then use Mutex.new.
85
- #
86
- def self.open(name, inherit=true, &block)
87
- if name && !name.is_a?(String)
88
- raise TypeError, 'name must be a string'
89
- end
90
-
91
- bool = inherit ? 1 : 0
92
-
93
- # The OpenMutex() call here is strictly to force an error if the user
94
- # tries to open a mutex that doesn't already exist.
95
- begin
96
- handle = OpenMutex(MUTEX_ALL_ACCESS, bool, name)
97
-
98
- if handle == 0 || handle == INVALID_HANDLE_VALUE
99
- raise Error, get_last_error
100
- end
101
- ensure
102
- CloseHandle(handle) if handle && handle > 0
103
- end
104
-
105
- self.new(false, name, inherit, &block)
65
+ if name && name.encoding.to_s != 'UTF-16LE'
66
+ name = name + 0.chr
67
+ name.encode!('UTF-16LE')
106
68
  end
107
69
 
108
- # Releases ownership of the mutex.
109
- #
110
- def release
111
- unless ReleaseMutex(@handle)
112
- raise Error, get_last_error
113
- end
70
+ handle = CreateMutexW(sec, initial_owner, name)
71
+
72
+ if handle == 0 || handle == INVALID_HANDLE_VALUE
73
+ raise SystemCallError.new("CreateMutex", FFI.errno)
114
74
  end
115
75
 
116
- # Returns whether or not the calling thread has initial ownership of
117
- # the mutex object.
118
- #
119
- def initial_owner?
120
- @initial_owner
76
+ super(handle)
77
+
78
+ if block_given?
79
+ begin
80
+ yield self
81
+ ensure
82
+ close # From superclass
83
+ end
121
84
  end
85
+ end
86
+
87
+ # Open an existing Mutex by +name+. The +inherit+ argument sets
88
+ # whether or not the object was opened such that a process created by the
89
+ # CreateProcess() function (a Windows API function) can inherit the
90
+ # handle. The default is true.
91
+ #
92
+ # This method is essentially identical to Mutex.new, except that the
93
+ # option for +initial_owner+ cannot be set (since it is already set).
94
+ # Also, this method will raise a Mutex::Error if the mutex doesn't
95
+ # already exist.
96
+ #
97
+ # If you want "open or create" semantics, then use Mutex.new.
98
+ #
99
+ def self.open(name, inherit=true, &block)
100
+ if name.encoding.to_s != 'UTF-16LE'
101
+ name = name + 0.chr
102
+ name.encode!('UTF-16LE')
103
+ end
104
+
105
+ begin
106
+ # The OpenMutex() call here is strictly to force an error if the user
107
+ # tries to open a mutex that doesn't already exist.
108
+ handle = OpenMutexW(MUTEX_ALL_ACCESS, inherit, name)
109
+
110
+ if handle == 0 || handle == INVALID_HANDLE_VALUE
111
+ raise SystemCallError.new("OpenMutex", FFI.errno)
112
+ end
113
+ ensure
114
+ CloseHandle(handle) if handle && handle > 0
115
+ end
116
+
117
+ self.new(false, name, inherit, &block)
118
+ end
122
119
 
123
- # Returns whether or not the object was opened such that a process
124
- # created by the CreateProcess() function (a Windows API function) can
125
- # inherit the handle. The default is true.
126
- #
127
- def inheritable?
128
- @inherit
120
+ # Releases ownership of the mutex.
121
+ #
122
+ def release
123
+ unless ReleaseMutex(@handle)
124
+ raise SystemCallError.new("ReleaseMutex", FFI.errno)
129
125
  end
130
- end
126
+ end
127
+
128
+ # Returns whether or not the calling thread has initial ownership of
129
+ # the mutex object.
130
+ #
131
+ def initial_owner?
132
+ @initial_owner
133
+ end
134
+
135
+ # Returns whether or not the object was opened such that a process
136
+ # created by the CreateProcess() function (a Windows API function) can
137
+ # inherit the handle. The default is true.
138
+ #
139
+ def inheritable?
140
+ @inherit
141
+ end
142
+ end
131
143
  end
@@ -1,14 +1,11 @@
1
1
  # encoding: utf-8
2
2
  #######################################################################
3
- # test_Win32::Mutex.rb
3
+ # test_win32_mutex.rb
4
4
  #
5
- # Test suite for the win32-Win32::Mutex package. This test suite
6
- # should be run via the 'rake test' task.
5
+ # Test suite for the win32-mutex library. This test suite should be
6
+ # run via the 'rake test' task.
7
7
  #######################################################################
8
- require 'rubygems'
9
- gem 'test-unit'
10
-
11
- require 'test/unit'
8
+ require 'test-unit'
12
9
  require 'win32/mutex'
13
10
 
14
11
  class TC_Win32_Mutex < Test::Unit::TestCase
@@ -18,47 +15,67 @@ class TC_Win32_Mutex < Test::Unit::TestCase
18
15
  end
19
16
 
20
17
  def test_version
21
- assert_equal('0.3.2', Win32::Mutex::VERSION)
18
+ assert_equal('0.4.0', 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
22
25
  end
23
26
 
24
- def test_open
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
25
36
  assert_respond_to(Win32::Mutex, :open)
26
37
  assert_nothing_raised{ Win32::Mutex.open('test'){} }
27
38
  assert_nothing_raised{ Win32::Mutex.open('Ηελλας'){} }
28
39
  end
29
40
 
30
- def test_open_expected_errors
31
- assert_raise(Win32::Mutex::Error){ Win32::Mutex.open('bogus'){} }
41
+ test "attempting to open an unknown mutex raises an error" do
42
+ assert_raise(Errno::ENOENT){ Win32::Mutex.open('bogus'){} }
32
43
  end
33
44
 
34
- def test_release
45
+ test "release method works as expected" do
35
46
  assert_respond_to(@mutex, :release)
36
47
  assert_nothing_raised{ @mutex.release }
37
48
  end
38
49
 
39
- def test_initial_owner
50
+ test "initial_owner? works as expected and returns expected value" do
40
51
  assert_respond_to(@mutex, :initial_owner?)
41
52
  assert_true(@mutex.initial_owner?)
42
53
  assert_false(@umutex.initial_owner?)
43
54
  end
44
55
 
45
- def test_inheritable
56
+ test "inheritable? works as expected and returns expected value" do
46
57
  assert_respond_to(@mutex, :inheritable?)
47
58
  assert_true(@mutex.inheritable?)
48
59
  end
49
60
 
50
- def test_wait
61
+ test "wait method was inherited" do
51
62
  assert_respond_to(@mutex, :wait)
52
63
  end
53
64
 
54
- def test_wait_any
65
+ test "wait_any method was inherited" do
55
66
  assert_respond_to(@mutex, :wait_any)
56
67
  end
57
68
 
58
- def test_wait_all
69
+ test "wait_all method was inherited" do
59
70
  assert_respond_to(@mutex, :wait_all)
60
71
  end
61
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
+
62
79
  def teardown
63
80
  @mutex.close
64
81
  @umutex.close
data/win32-mutex.gemspec CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'win32-mutex'
5
- spec.version = '0.3.2'
5
+ spec.version = '0.4.0'
6
6
  spec.author = 'Daniel J. Berger'
7
7
  spec.license = 'Artistic 2.0'
8
8
  spec.email = 'djberg96@gmail.com'
@@ -13,12 +13,10 @@ Gem::Specification.new do |spec|
13
13
 
14
14
  spec.rubyforge_project = 'win32utils'
15
15
  spec.extra_rdoc_files = ['README', 'CHANGES', 'MANIFEST']
16
+ spec.required_ruby_version = '> 1.9.0'
16
17
 
17
- spec.add_dependency('win32-ipc', '>= 0.5.0')
18
-
19
- spec.add_development_dependency('test-unit', '>= 2.0.3')
20
- spec.add_development_dependency('win32-process', '>= 0.6.1')
21
- spec.add_development_dependency('win32-mmap', '>= 0.2.2')
18
+ spec.add_dependency('win32-ipc', '>= 0.6.0')
19
+ spec.add_development_dependency('test-unit')
22
20
 
23
21
  spec.description = <<-EOF
24
22
  The win32-mutex library provides an interface for creating mutex objects
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: win32-mutex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,52 +9,40 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-18 00:00:00.000000000 Z
12
+ date: 2012-07-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: win32-ipc
16
- requirement: &5842660 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: 0.5.0
21
+ version: 0.6.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *5842660
25
- - !ruby/object:Gem::Dependency
26
- name: test-unit
27
- requirement: &5841950 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
28
25
  none: false
29
26
  requirements:
30
27
  - - ! '>='
31
28
  - !ruby/object:Gem::Version
32
- version: 2.0.3
33
- type: :development
34
- prerelease: false
35
- version_requirements: *5841950
29
+ version: 0.6.0
36
30
  - !ruby/object:Gem::Dependency
37
- name: win32-process
38
- requirement: &5841220 !ruby/object:Gem::Requirement
31
+ name: test-unit
32
+ requirement: !ruby/object:Gem::Requirement
39
33
  none: false
40
34
  requirements:
41
35
  - - ! '>='
42
36
  - !ruby/object:Gem::Version
43
- version: 0.6.1
37
+ version: '0'
44
38
  type: :development
45
39
  prerelease: false
46
- version_requirements: *5841220
47
- - !ruby/object:Gem::Dependency
48
- name: win32-mmap
49
- requirement: &5840660 !ruby/object:Gem::Requirement
40
+ version_requirements: !ruby/object:Gem::Requirement
50
41
  none: false
51
42
  requirements:
52
43
  - - ! '>='
53
44
  - !ruby/object:Gem::Version
54
- version: 0.2.2
55
- type: :development
56
- prerelease: false
57
- version_requirements: *5840660
45
+ version: '0'
58
46
  description: ! " The win32-mutex library provides an interface for creating mutex
59
47
  objects\n on MS Windows. A mutex object is a synchronization object whose state\n
60
48
  \ is set to signaled when it is not owned by any thread, and non-signaled\n when
@@ -85,9 +73,9 @@ require_paths:
85
73
  required_ruby_version: !ruby/object:Gem::Requirement
86
74
  none: false
87
75
  requirements:
88
- - - ! '>='
76
+ - - ! '>'
89
77
  - !ruby/object:Gem::Version
90
- version: '0'
78
+ version: 1.9.0
91
79
  required_rubygems_version: !ruby/object:Gem::Requirement
92
80
  none: false
93
81
  requirements:
@@ -96,7 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
84
  version: '0'
97
85
  requirements: []
98
86
  rubyforge_project: win32utils
99
- rubygems_version: 1.8.11
87
+ rubygems_version: 1.8.24
100
88
  signing_key:
101
89
  specification_version: 3
102
90
  summary: Interface to MS Windows Mutex objects.