win32-mmap 0.2.4 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/win32/mmap.rb CHANGED
@@ -1,397 +1,392 @@
1
- require 'windows/file'
2
- require 'windows/file_mapping'
3
- require 'windows/error'
4
- require 'windows/handle'
5
- require 'windows/msvcrt/buffer'
6
- require 'windows/synchronize'
7
- require 'windows/memory'
8
-
9
- # The Win32 module serves as a namespace only.
10
- #
11
- module Win32
12
-
13
- # The MMap class encapsulates functions for memory mapped files.
14
- #
15
- class MMap
16
-
17
- # The version of the win32-mmap library.
18
- VERSION = '0.2.4'
19
-
20
- # Error typically raised in any method of Win32::MMap should fail.
21
- #
22
- class Error < StandardError; end
23
-
24
- include Windows::Error
25
- include Windows::File
26
- include Windows::FileMapping
27
- include Windows::Handle
28
- include Windows::MSVCRT::Buffer
29
- include Windows::Synchronize
30
- include Windows::Memory
31
-
32
- # The name of the file from which to create a mapping object. This
33
- # value may be nil.
34
- #
35
- attr_accessor :file
36
-
37
- # The protection for the file view. This may be any of the following
38
- # values:
39
- #
40
- # * PAGE_READONLY
41
- # * PAGE_READWRITE
42
- # * PAGE_WRITECOPY
43
- # * PAGE_WRITECOPY
44
- # * PAGE_EXECUTE_READ
45
- # * PAGE_EXECUTE_READWRITE
46
- #
47
- # You can OR the protection value with any of these section attributes:
48
- #
49
- # * SEC_COMMIT
50
- # * SEC_IMAGE
51
- # * SEC_LARGE_PAGES
52
- # * SEC_NOCACHE
53
- # * SEC_RESERVE
54
- #
55
- # The default protection is PAGE_READWRITE.
56
- #
57
- attr_accessor :protection
58
-
59
- # A string that determines the name of the mapping object.
60
- # By default this value is nil, i.e. anonymous. If you specify a +name+
61
- # that already exists then an attempt is made to access that object.
62
- #
63
- attr_accessor :name
64
-
65
- # The maximum size for the file mapping object. If a +file+ is
66
- # specified, this value defaults to the size of +file+. Otherwise
67
- # it defaults to zero (though you should set it manually).
68
- #
69
- attr_accessor :size
70
-
71
- # Access desired to the file mapping object. This may be
72
- # any of the following values:
73
- #
74
- # * FILE_MAP_WRITE
75
- # * FILE_MAP_READ
76
- # * FILE_MAP_COPY
77
- # * FILE_MAP_ALL_ACCESS
78
- #
79
- # The default access is FILE_MAP_WRITE.
80
- #
81
- attr_accessor :access
82
-
83
- # The address of the file view mapping.
84
- #
85
- attr_reader :address
86
-
87
- # Suggested starting address of mapped view. If this value is not
88
- # specified, the system will choose the base mapping address. If you do
89
- # specify a value, it must be a multiple of the system's allocation
90
- # granularity.
91
- #
92
- # Note: The MSDN documentation recommends that, in most case cases, you
93
- # should not set this value.
94
- #--
95
- # A system's allocation granularity can be found via GetSystemInfo()
96
- # and the dwAllocationGranularity member of the SYSTEM_INFO struct.
97
- #
98
- attr_accessor :base_address
99
-
100
- # Sets whether or not a semaphore lock is automatically placed on the
101
- # mapped view for read and write operations. This is true by default.
102
- #
103
- attr_writer :autolock
104
-
105
- # The value, in milliseconds, used to wait on the semaphore lock. Only
106
- # used if the +autolock+ option is true. The default is 10 milliseconds.
107
- #
108
- attr_accessor :timeout
109
-
110
- # :call-seq:
111
- # MMap.new(opts = {})
112
- # MMap.new(opts = {}){ |address| block }
113
- #
114
- # Creates and returns a new Win32::MMap object. If +file+ is set, then
115
- # that file is used to create the mapping. If a block is provided the
116
- # address is yielded and the mapping object is automatically closed at the
117
- # end of the block.
118
- #
119
- # Accepts any one of the following hash attributes:
120
- #
121
- # * protection
122
- # * size
123
- # * access
124
- # * inherit
125
- # * name
126
- # * base_address
127
- # * autolock
128
- # * timeout
129
- # * file
130
- #
131
- # Please see the documentation on the individual attributes for
132
- # further details. Note that, although these are accessors, they
133
- # *must* be set in the constructor (if set at all). Setting them
134
- # after the call to MMap.new will not have any effect.
135
- #
136
- # == Example
137
- # require 'win32/mmap'
138
- # require 'windows/msvcrt/string'
139
- # include Windows::MSVCRT::String
140
- # include Win32
141
- #
142
- # # Reverse the contents of a file.
143
- # mmap = MMap.new(:file => 'test.txt') do |addr|
144
- # strrev(addr)
145
- # end
146
- #
147
- def initialize(opts = {})
148
- valid = %w/
149
- file name protection access inherit size
150
- base_address open autolock timeout
151
- /
152
-
153
- @open = nil
154
- @file = nil
155
- @autolock = nil
156
-
157
- opts.each{ |key, value|
158
- key = key.to_s.downcase
159
- unless valid.include?(key)
160
- raise ArgumentError, "Invalid key '#{key}'"
161
- end
162
- if key == 'inherit'
163
- self.inherit = value # To force inherit= method call
164
- else
165
- instance_variable_set("@#{key}", value)
166
- end
167
- }
168
-
169
- @protection ||= PAGE_READWRITE
170
- @access ||= FILE_MAP_WRITE
171
- @size ||= 0
172
- @inherit ||= 0
173
- @base_address ||= 0
174
- @timeout ||= 10 # Milliseconds
175
-
176
- @hash = {}
177
-
178
- # Anything except an explicit false means the autolock is on.
179
- @autolock = true unless @autolock == false
180
-
181
- @lock_flag = 0 # Internal use only
182
-
183
- if @file
184
- if File.exists?(@file)
185
- fsize = File.size(@file)
186
- raise Error, 'cannot open 0 byte file' if fsize.zero?
187
- @size = fsize if @size < fsize
188
- end
189
-
190
- rights = GENERIC_READ|GENERIC_WRITE
191
-
192
- @fh = CreateFile(@file, rights, 0, 0, OPEN_ALWAYS, 0, 0)
193
-
194
- if @fh == INVALID_HANDLE_VALUE
195
- raise Error, get_last_error
196
- end
197
- else
198
- @fh = INVALID_HANDLE_VALUE
199
- end
200
-
201
- if @open
202
- @mh = OpenFileMapping(@access, @inherit, @name)
203
- else
204
- @mh = CreateFileMapping(@fh, @inherit, @protection, 0, @size, @name)
205
- end
206
-
207
- if @mh == 0
208
- raise Error, get_last_error
209
- end
210
-
211
- if @open
212
- @address = MapViewOfFileEx(@mh, @access, 0, 0, 0, @base_address)
213
- @size = get_view_size()
214
- else
215
- @address = MapViewOfFileEx(@mh, @access, 0, 0, 0, @base_address)
216
- end
217
-
218
- if @address == 0
219
- raise Error, get_last_error
220
- end
221
-
222
- if @autolock
223
- @semaphore = CreateSemaphore(nil, 1, 1, "#{@name}.ruby_lock")
224
- if @semaphore == 0
225
- raise Error, get_last_error
226
- end
227
- end
228
-
229
- if block_given?
230
- begin
231
- yield @address
232
- ensure
233
- close
234
- end
235
- end
236
-
237
- @address
238
- end
239
-
240
- # Opens an existing file mapping using +name+. You may pass a hash
241
- # of +opts+ as you would to MMap.new. If you don't specify a size
242
- # as part of the +opts+, it will be dynamically determined for you
243
- # (in blocks equal to your system's page size, typically 4k).
244
- #
245
- # This method is otherwise identical to MMap.new.
246
- #--
247
- # This forces MMap.new to use OpenFileMapping() behind the scenes.
248
- #
249
- def self.open(name, opts={}, &block)
250
- opts[:name] = name
251
- opts[:open] = true
252
- self.new(opts, &block)
253
- end
254
-
255
- # Sets whether or not the mapping handle can be inherited
256
- # by child processes.
257
- #--
258
- # If true, we have to create a SECURITY_ATTRIBUTES struct and set
259
- # its nLength member to 12 and its bInheritHandle member to TRUE.
260
- #
261
- def inherit=(bool)
262
- if bool
263
- buf = 0.chr * 12 # sizeof(SECURITY_ATTRIBUTES)
264
- buf[0,4] = [12].pack('L')
265
- buf[8,4] = [1].pack('L') # 1 == TRUE
266
- @inherit = buf
267
- else
268
- @inherit = 0
269
- end
270
- end
271
-
272
- # Returns whether or not the mapping handle can be
273
- # inherited by child processes. The default is false.
274
- #
275
- def inherit?
276
- @inherit != 0
277
- end
278
-
279
- # Writes +num_bytes+ to the disk within a mapped view of a file, or to
280
- # the end of the mapping if +num_bytes+ is not specified.
281
- #
282
- def flush(num_bytes = 0)
283
- unless FlushViewOfFile(@address, num_bytes)
284
- raise Error, get_last_error
285
- end
286
- end
287
-
288
- # Unmaps the file view and closes all open file handles. You should
289
- # always call this when you are finished with the object (when using
290
- # the non-block form).
291
- #
292
- def close
293
- UnmapViewOfFile(@address) if @address
294
- CloseHandle(@fh) if @fh
295
- CloseHandle(@mh) if @mh
296
- ReleaseSemaphore(@semaphore, 1, nil) if @semaphore
297
- end
298
-
299
- # Returns whether or not a semaphore lock is automatically placed on the
300
- # mapped view for read and write operations. This is true by default.
301
- #
302
- def autolock?
303
- @autolock
304
- end
305
-
306
- private
307
-
308
- # :stopdoc:
309
-
310
- # This is used to allow dynamic getters and setters between memory
311
- # mapped objects.
312
- #--
313
- # This replaces the getvar/setvar API from 0.1.0.
314
- #
315
- def method_missing(method_id, *args)
316
- method = method_id.id2name
317
- args = args.first if args.length == 1
318
-
319
- if method[-1,1] == '=' # Setter
320
- method.chop!
321
- @hash["#{method}"] = args
322
-
323
- if @autolock
324
- if mmap_lock
325
- instance_variable_set("@#{method}", args)
326
- marshal = Marshal.dump(@hash)
327
- memcpy(@address, marshal)
328
- mmap_unlock
329
- end
330
- else
331
- instance_variable_set("@#{method}", args)
332
- marshal = Marshal.dump(@hash)
333
- memcpy(@address, marshal)
334
- end
335
- else # Getter
336
- buf = 0.chr * @size
337
- if @autolock
338
- if mmap_lock
339
- memcpy(buf, @address, @size)
340
- hash = Marshal.load(buf)
341
- val = hash["#{method}"]
342
- instance_variable_set("@#{method}", val)
343
- mmap_unlock
344
- end
345
- else
346
- memcpy(buf, @address, @size)
347
- hash = Marshal.load(buf)
348
- val = hash["#{method}"]
349
- instance_variable_set("@#{method}", val)
350
- end
351
- return instance_variable_get("@#{method}")
352
- end
353
- end
354
-
355
- # Adds a semaphore lock the mapping. Only used if +autolock+ is set
356
- # to true in the constructor.
357
- #
358
- def mmap_lock
359
- bool = false
360
-
361
- if(@lock_flag == 0)
362
- if WaitForSingleObject(@semaphore, @timeout) == WAIT_OBJECT_0
363
- bool = true
364
- end
365
- end
366
-
367
- @lock_flag += 1
368
- bool
369
- end
370
-
371
- # Releases a semaphore lock on the view. Only used if +autolock+ is
372
- # set to true in the constructor.
373
- #
374
- def mmap_unlock
375
- @lock_flag -= 1
376
-
377
- if @lock_flag != 0
378
- return false
379
- end
380
-
381
- if ReleaseSemaphore(@semaphore, 1, nil) == 0
382
- raise Error, get_last_error
383
- end
384
-
385
- true
386
- end
387
-
388
- # Gets the size of an existing mapping based on the address. Used by
389
- # the MMap.open method when a size isn't specified.
390
- #
391
- def get_view_size
392
- mbi = [0,0,0,0,0,0,0].pack('LLLLLLL') # MEMORY_BASIC_INFORMATION
393
- VirtualQuery(@address, mbi, mbi.size)
394
- mbi[12,4].unpack('L').first # RegionSize
395
- end
396
- end
397
- end
1
+ require File.join(File.dirname(__FILE__), 'windows', 'constants')
2
+ require File.join(File.dirname(__FILE__), 'windows', 'structs')
3
+ require File.join(File.dirname(__FILE__), 'windows', 'functions')
4
+
5
+ # The Win32 module serves as a namespace only.
6
+ #
7
+ module Win32
8
+ # The MMap class encapsulates functions for memory mapped files.
9
+ #
10
+ class MMap
11
+ # The version of the win32-mmap library.
12
+ VERSION = '0.3.0'
13
+
14
+ include Windows::Constants
15
+ include Windows::Functions
16
+ include Windows::Structs
17
+
18
+ # The name of the file from which to create a mapping object. This
19
+ # value may be nil.
20
+ #
21
+ attr_accessor :file
22
+
23
+ # The protection for the file view. This may be any of the following
24
+ # values:
25
+ #
26
+ # * PAGE_READONLY
27
+ # * PAGE_READWRITE
28
+ # * PAGE_WRITECOPY
29
+ # * PAGE_WRITECOPY
30
+ # * PAGE_EXECUTE_READ
31
+ # * PAGE_EXECUTE_READWRITE
32
+ #
33
+ # You can OR the protection value with any of these section attributes:
34
+ #
35
+ # * SEC_COMMIT
36
+ # * SEC_IMAGE
37
+ # * SEC_LARGE_PAGES
38
+ # * SEC_NOCACHE
39
+ # * SEC_RESERVE
40
+ #
41
+ # The default protection is PAGE_READWRITE.
42
+ #
43
+ attr_accessor :protection
44
+
45
+ # A string that determines the name of the mapping object.
46
+ # By default this value is nil, i.e. anonymous. If you specify a +name+
47
+ # that already exists then an attempt is made to access that object.
48
+ #
49
+ attr_accessor :name
50
+
51
+ # The maximum size for the file mapping object. If a +file+ is
52
+ # specified, this value defaults to the size of +file+. Otherwise
53
+ # it defaults to zero (though you should set it manually).
54
+ #
55
+ attr_accessor :size
56
+
57
+ # Access desired to the file mapping object. This may be
58
+ # any of the following values:
59
+ #
60
+ # * FILE_MAP_WRITE
61
+ # * FILE_MAP_READ
62
+ # * FILE_MAP_COPY
63
+ # * FILE_MAP_ALL_ACCESS
64
+ #
65
+ # The default access is FILE_MAP_WRITE.
66
+ #
67
+ attr_accessor :access
68
+
69
+ # The address of the file view mapping.
70
+ #
71
+ attr_reader :address
72
+
73
+ # Suggested starting address of mapped view. If this value is not
74
+ # specified, the system will choose the base mapping address. If you do
75
+ # specify a value, it must be a multiple of the system's allocation
76
+ # granularity.
77
+ #
78
+ # Note: The MSDN documentation recommends that, in most case cases, you
79
+ # should not set this value.
80
+ #--
81
+ # A system's allocation granularity can be found via GetSystemInfo()
82
+ # and the dwAllocationGranularity member of the SYSTEM_INFO struct.
83
+ #
84
+ attr_accessor :base_address
85
+
86
+ # Sets whether or not a semaphore lock is automatically placed on the
87
+ # mapped view for read and write operations. This is true by default.
88
+ #
89
+ attr_writer :autolock
90
+
91
+ # The value, in milliseconds, used to wait on the semaphore lock. Only
92
+ # used if the +autolock+ option is true. The default is 10 milliseconds.
93
+ #
94
+ attr_accessor :timeout
95
+
96
+ # :call-seq:
97
+ # MMap.new(opts = {})
98
+ # MMap.new(opts = {}){ |address| block }
99
+ #
100
+ # Creates and returns a new Win32::MMap object. If +file+ is set, then
101
+ # that file is used to create the mapping. If a block is provided the
102
+ # address is yielded and the mapping object is automatically closed at the
103
+ # end of the block.
104
+ #
105
+ # Accepts any one of the following hash attributes:
106
+ #
107
+ # * protection
108
+ # * size
109
+ # * access
110
+ # * inherit
111
+ # * name
112
+ # * base_address
113
+ # * autolock
114
+ # * timeout
115
+ # * file
116
+ #
117
+ # Please see the documentation on the individual attributes for
118
+ # further details. Note that, although these are accessors, they
119
+ # *must* be set in the constructor (if set at all). Setting them
120
+ # after the call to MMap.new will not have any effect.
121
+ #
122
+ # == Example
123
+ # require 'win32/mmap'
124
+ # require 'windows/msvcrt/string'
125
+ # include Windows::MSVCRT::String
126
+ # include Win32
127
+ #
128
+ # # Reverse the contents of a file.
129
+ # mmap = MMap.new(:file => 'test.txt') do |addr|
130
+ # strrev(addr)
131
+ # end
132
+ #
133
+ def initialize(opts = {})
134
+ valid = %w[
135
+ file name protection access inherit size
136
+ base_address open autolock timeout
137
+ ]
138
+
139
+ @open = nil
140
+ @file = nil
141
+ @autolock = nil
142
+
143
+ # Validate the keys, handle inherit specially.
144
+ opts.each{ |key, value|
145
+ key = key.to_s.downcase
146
+
147
+ unless valid.include?(key)
148
+ raise ArgumentError, "Invalid key '#{key}'"
149
+ end
150
+
151
+ if key == 'inherit'
152
+ self.inherit = value # To force inherit= method call
153
+ else
154
+ instance_variable_set("@#{key}", value)
155
+ end
156
+ }
157
+
158
+ @protection ||= PAGE_READWRITE
159
+ @access ||= FILE_MAP_WRITE
160
+ @size ||= 0
161
+ @inherit ||= nil
162
+ @base_address ||= 0
163
+ @timeout ||= 10 # Milliseconds
164
+
165
+ self.inherit = false unless @inherit
166
+
167
+ @hash = {}
168
+
169
+ # Anything except an explicit false means the autolock is on.
170
+ @autolock = true unless @autolock == false
171
+
172
+ @lock_flag = 0 # Internal use only
173
+
174
+ if @file
175
+ if File.exists?(@file)
176
+ fsize = File.size(@file)
177
+ raise ArgumentError, 'cannot open 0 byte file' if fsize.zero?
178
+ @size = fsize if @size < fsize
179
+ end
180
+
181
+ rights = GENERIC_READ|GENERIC_WRITE
182
+
183
+ @fh = CreateFile(@file, rights, 0, 0, OPEN_ALWAYS, 0, 0)
184
+
185
+ if @fh == INVALID_HANDLE_VALUE
186
+ raise SystemCallError.new('CreateFile', FFI.errno)
187
+ end
188
+ else
189
+ @fh = INVALID_HANDLE_VALUE
190
+ end
191
+
192
+ if @open
193
+ @mh = OpenFileMapping(@access, @inherit[:bInheritHandle], @name)
194
+ raise SystemCallError.new('OpenFileMapping', FFI.errno) if @mh == 0
195
+ else
196
+ @mh = CreateFileMapping(@fh, @inherit, @protection, 0, @size, @name)
197
+ raise SystemCallError.new('CreateFileMapping', FFI.errno) if @mh == 0
198
+ end
199
+
200
+ if @open
201
+ @address = MapViewOfFileEx(@mh, @access, 0, 0, 0, @base_address)
202
+ @size = get_view_size()
203
+ else
204
+ @address = MapViewOfFileEx(@mh, @access, 0, 0, 0, @base_address)
205
+ end
206
+
207
+ if @address == 0
208
+ raise SystemCallError.new('MapviewOfFileEx', FFI.errno)
209
+ end
210
+
211
+ if @autolock
212
+ @semaphore = CreateSemaphore(nil, 1, 1, "#{@name}.ruby_lock")
213
+ if @semaphore == 0
214
+ raise Error, get_last_error
215
+ end
216
+ end
217
+
218
+ if block_given?
219
+ begin
220
+ yield @address
221
+ ensure
222
+ close
223
+ end
224
+ end
225
+
226
+ @address
227
+ end
228
+
229
+ # Opens an existing file mapping using +name+. You may pass a hash
230
+ # of +opts+ as you would to MMap.new. If you don't specify a size
231
+ # as part of the +opts+, it will be dynamically determined for you
232
+ # (in blocks equal to your system's page size, typically 4k).
233
+ #
234
+ # This method is otherwise identical to MMap.new.
235
+ #--
236
+ # This forces MMap.new to use OpenFileMapping() behind the scenes.
237
+ #
238
+ def self.open(name, opts={}, &block)
239
+ opts[:name] = name
240
+ opts[:open] = true
241
+ self.new(opts, &block)
242
+ end
243
+
244
+ # Sets whether or not the mapping handle can be inherited
245
+ # by child processes.
246
+ #--
247
+ # If true, we have to create a SECURITY_ATTRIBUTES struct and set
248
+ # its nLength member to 12 and its bInheritHandle member to TRUE.
249
+ #
250
+ def inherit=(bool)
251
+ @inherit = SECURITY_ATTRIBUTES.new
252
+ @inherit[:nLength] = SECURITY_ATTRIBUTES.size
253
+
254
+ if bool
255
+ @inherit[:bInheritHandle] = true
256
+ else
257
+ @inherit[:bInheritHandle] = false
258
+ end
259
+ end
260
+
261
+ # Returns whether or not the mapping handle can be
262
+ # inherited by child processes. The default is false.
263
+ #
264
+ def inherit?
265
+ @inherit and @inherit[:bInheritHandle]
266
+ end
267
+
268
+ # Writes +num_bytes+ to the disk within a mapped view of a file, or to
269
+ # the end of the mapping if +num_bytes+ is not specified.
270
+ #
271
+ def flush(num_bytes = 0)
272
+ unless FlushViewOfFile(@address, num_bytes)
273
+ SystemCallError.new('FlushViewOfFile', FFI.errno)
274
+ end
275
+ end
276
+
277
+ # Unmaps the file view and closes all open file handles. You should
278
+ # always call this when you are finished with the object (when using
279
+ # the non-block form).
280
+ #
281
+ def close
282
+ UnmapViewOfFile(@address) if @address
283
+ CloseHandle(@fh) if @fh
284
+ CloseHandle(@mh) if @mh
285
+ ReleaseSemaphore(@semaphore, 1, nil) if @semaphore
286
+ end
287
+
288
+ # Returns whether or not a semaphore lock is automatically placed on the
289
+ # mapped view for read and write operations. This is true by default.
290
+ #
291
+ def autolock?
292
+ @autolock
293
+ end
294
+
295
+ private
296
+
297
+ # :stopdoc:
298
+
299
+ # This is used to allow dynamic getters and setters between memory
300
+ # mapped objects.
301
+ #--
302
+ # This replaces the getvar/setvar API from 0.1.0.
303
+ #
304
+ # TODO: FIX!
305
+ #
306
+ def method_missing(method_id, *args)
307
+ method = method_id.id2name
308
+ args = args.first if args.length == 1
309
+
310
+ if method[-1,1] == '=' # Setter
311
+ method.chop!
312
+ @hash["#{method}"] = args
313
+
314
+ if @autolock
315
+ if mmap_lock
316
+ instance_variable_set("@#{method}", args)
317
+ marshal = Marshal.dump(@hash)
318
+ ptr = FFI::Pointer.new(:char, @address)
319
+ ptr.write_string(marshal,marshal.length)
320
+ mmap_unlock
321
+ end
322
+ else
323
+ instance_variable_set("@#{method}", args)
324
+ marshal = Marshal.dump(@hash)
325
+ ptr = FFI::Pointer.new(:char, @address)
326
+ ptr.write_string(marshal,marshal.length)
327
+ end
328
+ else # Getter
329
+ buf = FFI::MemoryPointer.new(:char, @size)
330
+
331
+ if @autolock
332
+ if mmap_lock
333
+ ptr = FFI::Pointer.new(:char, @address)
334
+ buf = ptr.read_string(@size)
335
+ hash = Marshal.load(buf)
336
+ val = hash["#{method}"]
337
+ instance_variable_set("@#{method}", val)
338
+ mmap_unlock
339
+ end
340
+ else
341
+ ptr = FFI::Pointer.new(:char, @address)
342
+ buf = ptr.read_string(@size)
343
+ hash = Marshal.load(buf)
344
+ val = hash["#{method}"]
345
+ instance_variable_set("@#{method}", val)
346
+ end
347
+
348
+ return instance_variable_get("@#{method}")
349
+ end
350
+ end
351
+
352
+ # Adds a semaphore lock the mapping. Only used if +autolock+ is set
353
+ # to true in the constructor.
354
+ #
355
+ def mmap_lock
356
+ bool = false
357
+
358
+ if(@lock_flag == 0)
359
+ if WaitForSingleObject(@semaphore, @timeout) == WAIT_OBJECT_0
360
+ bool = true
361
+ end
362
+ end
363
+
364
+ @lock_flag += 1
365
+ bool
366
+ end
367
+
368
+ # Releases a semaphore lock on the view. Only used if +autolock+ is
369
+ # set to true in the constructor.
370
+ #
371
+ def mmap_unlock
372
+ @lock_flag -= 1
373
+
374
+ return false if @lock_flag != 0
375
+
376
+ if ReleaseSemaphore(@semaphore, 1, nil) == 0
377
+ raise SystemCallError.new('ReleaseSemaphore', FFI.errno)
378
+ end
379
+
380
+ true
381
+ end
382
+
383
+ # Gets the size of an existing mapping based on the address. This
384
+ # is used by the MMap.open method when a size isn't specified.
385
+ #
386
+ def get_view_size
387
+ mbi = MEMORY_BASIC_INFORMATION.new
388
+ VirtualQuery(@address, mbi, mbi.size)
389
+ mbi[:RegionSize]
390
+ end
391
+ end # MMap
392
+ end # Win32