On Sun, 15 Oct 2006, Nicholas Frechette wrote:

> Hi, I'm currently working on a side project which has me store binary
> content in memory.  In order to make it's use as transparent as possible, i
> overloaded the 'require' method to search as well in the memory and this
> works fine at the moment. In the same line of thought, I tried changing the
> way File.new works to return a StringIO object pointing to my binary data in
> memory instead of an ordinary IO object... However, i ran into an
> interesting problem. Consider the following code:

the way to accomplish this is to use mmap.  that's what the call basically
does: map file to memory and return them as strings.  if you create more than
one mapping you will not map the file twice (if you give the right flags to
the ctor).  here's a little example of using mmap to modify the running
program:


here's the program

     harp:~ > cat a.rb
     require 'mmap'

     mmap = Mmap.new __FILE__, 'rw', Mmap::MAP_SHARED

     mmap << { mmap => Time.now.to_f.to_s }.inspect << "\n"
     mmap.msync
     mmap.munmap

     p DATA.readlines

     __END__


here's one run

     harp:~ > ruby a.rb
     ["{#<Mmap:0xb75cc79c>=>\"1160922660.6115\"}\n"]

     harp:~ > cat a.rb
     require 'mmap'

     mmap = Mmap.new __FILE__, 'rw', Mmap::MAP_SHARED

     mmap << { mmap => Time.now.to_f.to_s }.inspect << "\n"
     mmap.msync
     mmap.munmap

     p DATA.readlines

     __END__
     {#<Mmap:0xb75cc79c>=>"1160922660.6115"}


here's the next

     harp:~ > ruby a.rb
     ["{#<Mmap:0xb75cc79c>=>\"1160922660.6115\"}\n", "{#<Mmap:0xb75d079c>=>\"1160922666.11629\"}\n"]

     harp:~ > cat a.rb
     require 'mmap'

     mmap = Mmap.new __FILE__, 'rw', Mmap::MAP_SHARED

     mmap << { mmap => Time.now.to_f.to_s }.inspect << "\n"
     mmap.msync
     mmap.munmap

     p DATA.readlines

     __END__
     {#<Mmap:0xb75cc79c>=>"1160922660.6115"}
     {#<Mmap:0xb75d079c>=>"1160922666.11629"}


as many times as you might call " Mmap.new __FILE__, 'rw', Mmap::MAP_SHARED "
your process will only have one mapping.  in fact, you really cannot map it
more times:


     harp:~ > cat a.rb
     require 'mmap'

     mmaps = Array.new(3){ Mmap.new __FILE__, 'rw', Mmap::MAP_SHARED }

     mmaps.each do |mmap|
       mmap << { mmap => Time.now.to_f.to_s }.inspect << "\n"
       mmap.msync
       mmap.munmap
     end

     p DATA.readlines

     __END__


     harp:~ > ruby a.rb
     ["{#<Mmap:0xb75d179c>=>\"1160922968.42437\"}\n"]


     harp:~ > cat a.rb
     require 'mmap'

     mmaps = Array.new(3){ Mmap.new __FILE__, 'rw', Mmap::MAP_SHARED }

     mmaps.each do |mmap|
       mmap << { mmap => Time.now.to_f.to_s }.inspect << "\n"
       mmap.msync
       mmap.munmap
     end

     p DATA.readlines

     __END__
     {#<Mmap:0xb75d179c>=>"1160922968.42437"}


notice how the second and third calls were no-ops.  that's because all three
mappings were actually the same, and unmapping the first unmapped the rest -
leaving the rest of the loops as no-ops.

regards.

-a
-- 
my religion is very simple.  my religion is kindness. -- the dalai lama