win32-mmap 0.2.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 +23 -0
- data/MANIFEST +15 -0
- data/README +70 -0
- data/install.rb +11 -0
- data/lib/win32/mmap.rb +392 -0
- data/test/tc_mmap.rb +88 -0
- data/win32-mmap.gemspec +24 -0
- metadata +65 -0
data/CHANGES
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
== 0.2.0 - 13-Oct-2006
|
2
|
+
* Completely scrapped the old interface and code. It is now pure Ruby and
|
3
|
+
has a much different API, and some internal changes.
|
4
|
+
* Added a gemspec and an install.rb file for manual installation.
|
5
|
+
* Now requires the windows-pr package, 0.5.5 or higher.
|
6
|
+
* Modified the example scripts.
|
7
|
+
* Updated the docs, and replaced the .txt and .rd files with a single .rdoc
|
8
|
+
file.
|
9
|
+
|
10
|
+
== 0.1.1 - 1-Mar-2005
|
11
|
+
* Moved the 'examples' directory to the toplevel directory.
|
12
|
+
* Made the CHANGES and README files rdoc friendly.
|
13
|
+
|
14
|
+
== 0.1.0 - 12-Aug-2004
|
15
|
+
* Modified to use the newer allocation framework. That means that, as of
|
16
|
+
this release, this package requires Ruby 1.8.0 or later.
|
17
|
+
* Moved sample programs under doc/examples.
|
18
|
+
|
19
|
+
== 0.0.2 - 14-Mar-2004
|
20
|
+
* Fixed sprintf() bug in new().
|
21
|
+
|
22
|
+
== 0.0.1 - 13-Mar-2004
|
23
|
+
* Initial (Beta) release
|
data/MANIFEST
ADDED
data/README
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
= Description
|
2
|
+
This package provides a Ruby interface for memory mapped I/O on MS Windows.
|
3
|
+
|
4
|
+
= Prerequisites
|
5
|
+
Ruby 1.8.0 or later.
|
6
|
+
windows-pr, 0.5.5 or later.
|
7
|
+
|
8
|
+
= Installation
|
9
|
+
== Standard Installation
|
10
|
+
ruby install.rb
|
11
|
+
|
12
|
+
== Gem Installation
|
13
|
+
ruby win32-mmap.gemspec
|
14
|
+
gem install win32-mmap-x.y.z.gem
|
15
|
+
|
16
|
+
= Synopsis
|
17
|
+
require 'win32/mmap'
|
18
|
+
include Win32
|
19
|
+
|
20
|
+
map1 = MMap.new(:file => "C:\\test.map", :size => 1024)
|
21
|
+
map1.foo = 'hello'
|
22
|
+
map1.bar = 77
|
23
|
+
map1.close
|
24
|
+
|
25
|
+
map2 = MMap.new(:file => "C:\\test.map")
|
26
|
+
p map2.foo # 'hello'
|
27
|
+
p map2.bar # 77
|
28
|
+
map2.close
|
29
|
+
|
30
|
+
= About Memory Mapped Files under Windows
|
31
|
+
Under Windows, code and data are both repesented by pages of memory backed
|
32
|
+
by files on disk - code by executable image an data by system pagefile
|
33
|
+
(swapfile). These are called memory mapped files. Memory mapped files can be
|
34
|
+
used to provide a mechanism for shared memory between processes. Different
|
35
|
+
processes are able to share data backed by the same swapfile, whether it's
|
36
|
+
the system pagefile or a user-defined swapfile.
|
37
|
+
|
38
|
+
Windows has a tight security system that prevents processes from directly
|
39
|
+
sharing information among each other, but mapped memory files provide a
|
40
|
+
mechanism that works with the Windows security system - by using a name that
|
41
|
+
all processes use to open the swapfile.
|
42
|
+
|
43
|
+
A shared section of the swapfile is translated into pages of memory that are
|
44
|
+
addressable by more than one process, Windows uses a system resource called a
|
45
|
+
prototype page table entry (PPTE) to enable more than one process to address
|
46
|
+
the same physical page of memory, thus multiple process can share the same
|
47
|
+
data without violating the Windows system security.
|
48
|
+
|
49
|
+
In short, MMF's provide shared memory under Windows.
|
50
|
+
|
51
|
+
(This explanation was largely borrowed from Roger Lee's Win32::MMF Perl
|
52
|
+
module.)
|
53
|
+
|
54
|
+
= Future Plans
|
55
|
+
Suggestions welcome.
|
56
|
+
|
57
|
+
= License
|
58
|
+
Ruby's
|
59
|
+
|
60
|
+
= Copyright
|
61
|
+
(C) 2003-2006 Daniel J. Berger, All Rights Reserved
|
62
|
+
|
63
|
+
= Warranty
|
64
|
+
This package is provided "as is" and without any express or
|
65
|
+
implied warranties, including, without limitation, the implied
|
66
|
+
warranties of merchantability and fitness for a particular purpose.
|
67
|
+
|
68
|
+
= Authors
|
69
|
+
Daniel J. Berger
|
70
|
+
Park Heesob
|
data/install.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# For those who don't like gems...
|
2
|
+
require 'rbconfig'
|
3
|
+
require 'ftools'
|
4
|
+
include Config
|
5
|
+
|
6
|
+
sitelibdir = CONFIG['sitelibdir']
|
7
|
+
installdir = sitelibdir + '/win32'
|
8
|
+
file = 'lib\win32\mmap.rb'
|
9
|
+
|
10
|
+
Dir.mkdir(installdir) unless File.exists?(installdir)
|
11
|
+
File.copy(file, installdir, true)
|
data/lib/win32/mmap.rb
ADDED
@@ -0,0 +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
|
+
module Win32
|
10
|
+
|
11
|
+
# Memory mapped files for MS Windows.
|
12
|
+
#
|
13
|
+
class MMap
|
14
|
+
VERSION = '0.2.0'
|
15
|
+
|
16
|
+
# This is a slightly different version of memcpy than what's provided
|
17
|
+
# in the Windows::MSVCRT::Buffer module. The difference is that the
|
18
|
+
# first argument is an address, not a char buffer.
|
19
|
+
MEMCPY = Win32API.new('msvcrt', 'memcpy', 'LPL', 'P')
|
20
|
+
|
21
|
+
# All errors generated by Win32::MMap are of type MMap::Error.
|
22
|
+
#
|
23
|
+
class Error < StandardError; end
|
24
|
+
|
25
|
+
include Windows::Error
|
26
|
+
include Windows::File
|
27
|
+
include Windows::FileMapping
|
28
|
+
include Windows::Handle
|
29
|
+
include Windows::MSVCRT::Buffer
|
30
|
+
include Windows::Synchronize
|
31
|
+
include Windows::Memory
|
32
|
+
|
33
|
+
# The name of the file from which to create a mapping object. This
|
34
|
+
# value may be nil.
|
35
|
+
#
|
36
|
+
attr_accessor :file
|
37
|
+
|
38
|
+
# The protection for the file view. This may be any of the following
|
39
|
+
# values:
|
40
|
+
#
|
41
|
+
# * PAGE_READONLY
|
42
|
+
# * PAGE_READWRITE
|
43
|
+
# * PAGE_WRITECOPY
|
44
|
+
# * PAGE_WRITECOPY
|
45
|
+
# * PAGE_EXECUTE_READ
|
46
|
+
# * PAGE_EXECUTE_READWRITE
|
47
|
+
#
|
48
|
+
# You can OR the protection value with any of these section attributes:
|
49
|
+
#
|
50
|
+
# * SEC_COMMIT
|
51
|
+
# * SEC_IMAGE
|
52
|
+
# * SEC_LARGE_PAGES
|
53
|
+
# * SEC_NOCACHE
|
54
|
+
# * SEC_RESERVE
|
55
|
+
#
|
56
|
+
# The default protection is PAGE_READWRITE.
|
57
|
+
#
|
58
|
+
attr_accessor :protection
|
59
|
+
|
60
|
+
# A string that determines the name of the mapping object.
|
61
|
+
# By default this value is nil, i.e. anonymous. If you specify a +name+
|
62
|
+
# that already exists then an attempt is made to access that object.
|
63
|
+
#
|
64
|
+
attr_accessor :name
|
65
|
+
|
66
|
+
# The maximum size for the file mapping object. If a +file+ is
|
67
|
+
# specified, this value defaults to the size of +file+. Otherwise
|
68
|
+
# it defaults to zero (though you should set it manually).
|
69
|
+
#
|
70
|
+
attr_accessor :size
|
71
|
+
|
72
|
+
# Access desired to the file mapping object. This may be
|
73
|
+
# any of the following values:
|
74
|
+
#
|
75
|
+
# * FILE_MAP_WRITE
|
76
|
+
# * FILE_MAP_READ
|
77
|
+
# * FILE_MAP_COPY
|
78
|
+
# * FILE_MAP_ALL_ACCESS
|
79
|
+
#
|
80
|
+
# The default access is FILE_MAP_WRITE.
|
81
|
+
#
|
82
|
+
attr_accessor :access
|
83
|
+
|
84
|
+
# The address of the file view mapping.
|
85
|
+
#
|
86
|
+
attr_reader :address
|
87
|
+
|
88
|
+
# Suggested starting address of mapped view. If this value is not
|
89
|
+
# specified, the system will choose the base mapping address. If you do
|
90
|
+
# specify a value, it must be a multiple of the system's allocation
|
91
|
+
# granularity.
|
92
|
+
#
|
93
|
+
# Note: The MSDN documentation recommends that, in most case cases, you
|
94
|
+
# should not set this value.
|
95
|
+
#--
|
96
|
+
# A system's allocation granularity can be found via GetSystemInfo()
|
97
|
+
# and the dwAllocationGranularity member of the SYSTEM_INFO struct.
|
98
|
+
#
|
99
|
+
attr_accessor :base_address
|
100
|
+
|
101
|
+
# Sets whether or not a semaphore lock is automatically placed on the
|
102
|
+
# mapped view for read and write operations. This is true by default.
|
103
|
+
#
|
104
|
+
attr_writer :autolock
|
105
|
+
|
106
|
+
# The value, in milliseconds, used to wait on the semaphore lock. Only
|
107
|
+
# used if the +autolock+ option is true. The default is 10 milliseconds.
|
108
|
+
#
|
109
|
+
attr_accessor :timeout
|
110
|
+
|
111
|
+
# :call-seq:
|
112
|
+
# MMap.new(opts = {})
|
113
|
+
# MMap.new(opts = {}){ |address| block }
|
114
|
+
#
|
115
|
+
# Creates and returns a new Win32::MMap object. If +file+ is set, then
|
116
|
+
# that file is used to create the mapping. If a block is provided the
|
117
|
+
# address is yielded and the mapping object is automatically closed at the
|
118
|
+
# end of the block.
|
119
|
+
#
|
120
|
+
# Accepts any one of the following hash attributes:
|
121
|
+
#
|
122
|
+
# * protection
|
123
|
+
# * size
|
124
|
+
# * access
|
125
|
+
# * inherit
|
126
|
+
# * name
|
127
|
+
# * base_address
|
128
|
+
# * autolock
|
129
|
+
# * timeout
|
130
|
+
# * file
|
131
|
+
#
|
132
|
+
# Please see the documentation for the individual attributes for
|
133
|
+
# further details. Note that, although these are accessors, they
|
134
|
+
# *must* be set in the constructor (if set at all). Setting them
|
135
|
+
# after the call to MMap.new will not have any effect.
|
136
|
+
#
|
137
|
+
# == Example
|
138
|
+
# require 'win32/mmap'
|
139
|
+
# require 'windows/msvcrt/string'
|
140
|
+
# include Windows::MSVCRT::String
|
141
|
+
# include Win32
|
142
|
+
#
|
143
|
+
# # Reverse the contents of a file.
|
144
|
+
# mmap = MMap.new(:file => 'test.txt') do |addr|
|
145
|
+
# strrev(addr)
|
146
|
+
# end
|
147
|
+
#
|
148
|
+
def initialize(opts = {})
|
149
|
+
valid = %w/
|
150
|
+
file name protection access inherit size
|
151
|
+
base_address open autolock timeout
|
152
|
+
/
|
153
|
+
|
154
|
+
opts.each{ |key, value|
|
155
|
+
key = key.to_s.downcase
|
156
|
+
unless valid.include?(key)
|
157
|
+
raise ArgumentError, "Invalid key '#{key}'"
|
158
|
+
end
|
159
|
+
if key == 'inherit'
|
160
|
+
self.inherit = value # To force inherit= method call
|
161
|
+
else
|
162
|
+
instance_variable_set("@#{key}", value)
|
163
|
+
end
|
164
|
+
}
|
165
|
+
|
166
|
+
@protection ||= PAGE_READWRITE
|
167
|
+
@access ||= FILE_MAP_WRITE
|
168
|
+
@size ||= 0
|
169
|
+
@inherit ||= 0
|
170
|
+
@base_address ||= 0
|
171
|
+
@timeout ||= 10 # Milliseconds
|
172
|
+
|
173
|
+
@hash = {}
|
174
|
+
|
175
|
+
# Anything except an explicit false means the autolock is on.
|
176
|
+
@autolock = true unless @autolock == false
|
177
|
+
|
178
|
+
@lock_flag = 0 # Internal use only
|
179
|
+
|
180
|
+
if @file
|
181
|
+
if File.exists?(@file)
|
182
|
+
fsize = File.size(@file)
|
183
|
+
raise Error, 'cannot open 0 byte file' if fsize.zero?
|
184
|
+
@size = fsize if @size < fsize
|
185
|
+
end
|
186
|
+
|
187
|
+
rights = GENERIC_READ|GENERIC_WRITE
|
188
|
+
|
189
|
+
@fh = CreateFile(@file, rights, 0, 0, OPEN_ALWAYS, 0, 0)
|
190
|
+
|
191
|
+
if @fh == INVALID_HANDLE_VALUE
|
192
|
+
raise Error, get_last_error
|
193
|
+
end
|
194
|
+
else
|
195
|
+
@fh = INVALID_HANDLE_VALUE
|
196
|
+
end
|
197
|
+
|
198
|
+
if @open
|
199
|
+
@mh = OpenFileMapping.call(@access, @inherit, @name)
|
200
|
+
else
|
201
|
+
@mh = CreateFileMapping(@fh, @inherit, @protection, 0, @size, @name)
|
202
|
+
end
|
203
|
+
|
204
|
+
if @mh == 0
|
205
|
+
raise Error, get_last_error
|
206
|
+
end
|
207
|
+
|
208
|
+
if @open
|
209
|
+
@address = MapViewOfFileEx(@mh, @access, 0, 0, 0, @base_address)
|
210
|
+
@size = get_view_size()
|
211
|
+
else
|
212
|
+
@address = MapViewOfFileEx(@mh, @access, 0, 0, 0, @base_address)
|
213
|
+
end
|
214
|
+
|
215
|
+
if @address == 0
|
216
|
+
raise Error, get_last_error
|
217
|
+
end
|
218
|
+
|
219
|
+
if @autolock
|
220
|
+
@semaphore = CreateSemaphore(nil, 1, 1, "#{@name}.ruby_lock")
|
221
|
+
if @semaphore == 0
|
222
|
+
raise Error, get_last_error
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
if block_given?
|
227
|
+
begin
|
228
|
+
yield @address
|
229
|
+
ensure
|
230
|
+
close
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
@address
|
235
|
+
end
|
236
|
+
|
237
|
+
# Opens an existing file mapping using +name+. You may pass a hash
|
238
|
+
# of +opts+ as you would to MMap.new. If you don't specify a size
|
239
|
+
# as part of the +opts+, it will be dynamically determined for you
|
240
|
+
# (in blocks equal to your system's page size, typically 4k).
|
241
|
+
#
|
242
|
+
# This method is otherwise identical to MMap.new.
|
243
|
+
#--
|
244
|
+
# This forces MMap.new to use OpenFileMapping() behind the scenes.
|
245
|
+
#
|
246
|
+
def self.open(name, opts={})
|
247
|
+
opts[:name] = name
|
248
|
+
opts[:open] = true
|
249
|
+
self.new(opts)
|
250
|
+
end
|
251
|
+
|
252
|
+
# Sets whether or not the mapping handle can be inherited
|
253
|
+
# by child processes.
|
254
|
+
#--
|
255
|
+
# If true, we have to create a SECURITY_ATTRIBUTES struct and set
|
256
|
+
# its nLength member to 12 and its bInheritHandle member to TRUE.
|
257
|
+
#
|
258
|
+
def inherit=(bool)
|
259
|
+
if bool
|
260
|
+
buf = 0.chr * 12 # sizeof(SECURITY_ATTRIBUTES)
|
261
|
+
buf[0,4] = [12].pack('L')
|
262
|
+
buf[8,4] = [1].pack('L') # 1 == TRUE
|
263
|
+
@inherit = buf
|
264
|
+
else
|
265
|
+
@inherit = 0
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
# Returns whether or not the mapping handle can be
|
270
|
+
# inherited by child processes. The default is false.
|
271
|
+
#
|
272
|
+
def inherit?
|
273
|
+
@inherit != 0
|
274
|
+
end
|
275
|
+
|
276
|
+
# Writes +num_bytes+ to the disk within a mapped view of a file, or to
|
277
|
+
# the end of the mapping if +num_bytes+ is not specified.
|
278
|
+
#
|
279
|
+
def flush(num_bytes = 0)
|
280
|
+
unless FlushViewOfFile(@address, num_bytes)
|
281
|
+
raise Error, get_last_error
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
# Unmaps the file view and closes all open file handles. You should
|
286
|
+
# always call this when you are finished with the object (when using
|
287
|
+
# the non-block form).
|
288
|
+
#
|
289
|
+
def close
|
290
|
+
UnmapViewOfFile(@address) if @address
|
291
|
+
CloseHandle(@fh) if @fh
|
292
|
+
CloseHandle(@mh) if @mh
|
293
|
+
ReleaseSemaphore(@semaphore, 1, nil) if @semaphore
|
294
|
+
end
|
295
|
+
|
296
|
+
# Returns whether or not a semaphore lock is automatically placed on the
|
297
|
+
# mapped view for read and write operations. This is true by default.
|
298
|
+
#
|
299
|
+
def autolock?
|
300
|
+
@autolock
|
301
|
+
end
|
302
|
+
|
303
|
+
private
|
304
|
+
|
305
|
+
# This is used to allow dynamic getters and setters between memory
|
306
|
+
# mapped objects.
|
307
|
+
#--
|
308
|
+
# This replaces the getvar/setvar API from 0.1.0.
|
309
|
+
#
|
310
|
+
def method_missing(method_id, *args)
|
311
|
+
method = method_id.id2name
|
312
|
+
args = args.first if args.length == 1
|
313
|
+
|
314
|
+
if method[-1,1] == '=' # Setter
|
315
|
+
method.chop!
|
316
|
+
@hash["#{method}"] = args
|
317
|
+
|
318
|
+
if @autolock
|
319
|
+
if mmap_lock
|
320
|
+
instance_variable_set("@#{method}", args)
|
321
|
+
marshal = Marshal.dump(@hash)
|
322
|
+
MEMCPY.call(@address, marshal, marshal.length)
|
323
|
+
mmap_unlock
|
324
|
+
end
|
325
|
+
else
|
326
|
+
instance_variable_set("@#{method}", args)
|
327
|
+
marshal = Marshal.dump(@hash)
|
328
|
+
MEMCPY.call(@address, marshal, marshal.length)
|
329
|
+
end
|
330
|
+
else # Getter
|
331
|
+
buf = 0.chr * @size
|
332
|
+
if @autolock
|
333
|
+
if mmap_lock
|
334
|
+
marshal = memcpy(buf, @address, @size)
|
335
|
+
hash = Marshal.load(marshal)
|
336
|
+
val = hash["#{method}"]
|
337
|
+
instance_variable_set("@#{method}", val)
|
338
|
+
mmap_unlock
|
339
|
+
end
|
340
|
+
else
|
341
|
+
marshal = memcpy(buf, @address, @size)
|
342
|
+
hash = Marshal.load(marshal)
|
343
|
+
val = hash["#{method}"]
|
344
|
+
instance_variable_set("@#{method}", val)
|
345
|
+
end
|
346
|
+
return instance_variable_get("@#{method}")
|
347
|
+
end
|
348
|
+
end
|
349
|
+
|
350
|
+
# Adds a semaphore lock the mapping. Only used if +autolock+ is set
|
351
|
+
# to true in the constructor.
|
352
|
+
#
|
353
|
+
def mmap_lock
|
354
|
+
bool = false
|
355
|
+
|
356
|
+
if(@lock_flag == 0)
|
357
|
+
if WaitForSingleObject(@semaphore, @timeout) == WAIT_OBJECT_0
|
358
|
+
bool = true
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
@lock_flag += 1
|
363
|
+
bool
|
364
|
+
end
|
365
|
+
|
366
|
+
# Releases a semaphore lock on the view. Only used if +autolock+ is
|
367
|
+
# set to true in the constructor.
|
368
|
+
#
|
369
|
+
def mmap_unlock
|
370
|
+
@lock_flag -= 1
|
371
|
+
|
372
|
+
if @lock_flag != 0
|
373
|
+
return false
|
374
|
+
end
|
375
|
+
|
376
|
+
if ReleaseSemaphore(@semaphore, 1, nil) == 0
|
377
|
+
raise Error, get_last_error
|
378
|
+
end
|
379
|
+
|
380
|
+
true
|
381
|
+
end
|
382
|
+
|
383
|
+
# Gets the size of an existing mapping based on the address. Used by
|
384
|
+
# the MMap.open method when a size isn't specified.
|
385
|
+
#
|
386
|
+
def get_view_size
|
387
|
+
mbi = [0,0,0,0,0,0,0].pack('LLLLLLL') # MEMORY_BASIC_INFORMATION
|
388
|
+
VirtualQuery(@address, mbi, mbi.size)
|
389
|
+
mbi[12,4].unpack('L').first # RegionSize
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|
data/test/tc_mmap.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
#################################################
|
2
|
+
# tc_mmap.rb
|
3
|
+
#
|
4
|
+
# Test suite for the win32-mmap package.
|
5
|
+
#################################################
|
6
|
+
Dir.chdir '..' if File.basename(Dir.pwd) == 'test'
|
7
|
+
$LOAD_PATH.unshift Dir.pwd
|
8
|
+
$LOAD_PATH.unshift Dir.pwd + '/lib'
|
9
|
+
|
10
|
+
require 'test/unit'
|
11
|
+
require 'win32/mmap'
|
12
|
+
include Win32
|
13
|
+
|
14
|
+
# The order of the tests matters (for now)
|
15
|
+
class TC_Mmap < Test::Unit::TestCase
|
16
|
+
def setup
|
17
|
+
@mmap = MMap.new(:name => 'test', :size => 100)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_version
|
21
|
+
assert_equal('0.2.0', MMap::VERSION)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_dynamic_value
|
25
|
+
assert_nothing_raised{ @mmap.foo = 'test' }
|
26
|
+
assert_equal('test', @mmap.foo)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_valid_options
|
30
|
+
assert_raises(ArgumentError){ MMap.new(:foo => 1) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_address
|
34
|
+
assert_respond_to(@mmap, :address)
|
35
|
+
assert_kind_of(Fixnum, @mmap.address)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_base_address
|
39
|
+
assert_respond_to(@mmap, :base_address)
|
40
|
+
assert_respond_to(@mmap, :base_address=)
|
41
|
+
assert_kind_of(Fixnum, @mmap.base_address)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_name
|
45
|
+
assert_respond_to(@mmap, :name)
|
46
|
+
assert_respond_to(@mmap, :name=)
|
47
|
+
assert_equal('test', @mmap.name)
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_inherit
|
51
|
+
assert_respond_to(@mmap, :inherit?)
|
52
|
+
assert_respond_to(@mmap, :inherit=)
|
53
|
+
assert_equal(false, @mmap.inherit?)
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_size
|
57
|
+
assert_respond_to(@mmap, :size)
|
58
|
+
assert_respond_to(@mmap, :size=)
|
59
|
+
assert_equal(100, @mmap.size)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_file
|
63
|
+
assert_respond_to(@mmap, :file)
|
64
|
+
assert_respond_to(@mmap, :file=)
|
65
|
+
assert_nil(@mmap.file)
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_access
|
69
|
+
assert_respond_to(@mmap, :access)
|
70
|
+
assert_respond_to(@mmap, :access=)
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_autolock
|
74
|
+
assert_respond_to(@mmap, :autolock?)
|
75
|
+
assert_respond_to(@mmap, :autolock=)
|
76
|
+
assert_equal(true, @mmap.autolock?)
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_protection
|
80
|
+
assert_respond_to(@mmap, :protection)
|
81
|
+
assert_respond_to(@mmap, :protection=)
|
82
|
+
assert_equal(4, @mmap.protection)
|
83
|
+
end
|
84
|
+
|
85
|
+
def teardown
|
86
|
+
@mmap.close
|
87
|
+
end
|
88
|
+
end
|
data/win32-mmap.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
|
3
|
+
spec = Gem::Specification.new do |gem|
|
4
|
+
gem.name = "win32-mmap"
|
5
|
+
gem.version = "0.2.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 = "Memory mapped IO for Windows."
|
11
|
+
gem.description = "Memory mapped IO for Windows."
|
12
|
+
gem.test_file = "test/tc_mmap.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"]
|
18
|
+
gem.add_dependency("windows-pr", ">= 0.5.5")
|
19
|
+
end
|
20
|
+
|
21
|
+
if $0 == __FILE__
|
22
|
+
Gem.manage_gems
|
23
|
+
Gem::Builder.new(spec).build
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.0
|
3
|
+
specification_version: 1
|
4
|
+
name: win32-mmap
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.2.0
|
7
|
+
date: 2006-10-13 00:00:00 -06:00
|
8
|
+
summary: Memory mapped IO for Windows.
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: djberg96@gmail.com
|
12
|
+
homepage: http://www.rubyforge.org/projects/win32utils
|
13
|
+
rubyforge_project:
|
14
|
+
description: Memory mapped IO for Windows.
|
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/mmap.rb
|
33
|
+
- test/tc_mmap.rb
|
34
|
+
- CHANGES
|
35
|
+
- doc
|
36
|
+
- examples
|
37
|
+
- install.rb
|
38
|
+
- lib
|
39
|
+
- MANIFEST
|
40
|
+
- README
|
41
|
+
- test
|
42
|
+
- win32-mmap.gemspec
|
43
|
+
test_files:
|
44
|
+
- test/tc_mmap.rb
|
45
|
+
rdoc_options: []
|
46
|
+
|
47
|
+
extra_rdoc_files:
|
48
|
+
- README
|
49
|
+
- CHANGES
|
50
|
+
executables: []
|
51
|
+
|
52
|
+
extensions: []
|
53
|
+
|
54
|
+
requirements: []
|
55
|
+
|
56
|
+
dependencies:
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: windows-pr
|
59
|
+
version_requirement:
|
60
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 0.5.5
|
65
|
+
version:
|