win32-mutex 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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.