Class: ProcessShared::SharedMemory

Inherits:
FFI::Pointer
  • Object
show all
Includes:
WithSelf
Defined in:
lib/process_shared/shared_memory.rb

Overview

Memory block shared across processes.

Direct Known Subclasses

SharedArray

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from WithSelf

#with_self

Constructor Details

#initialize(type_or_count = 1, count = 1) ⇒ SharedMemory

Returns a new instance of SharedMemory.



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/process_shared/shared_memory.rb', line 25

def initialize(type_or_count = 1, count = 1)
  @type, @count = case type_or_count
                  when Symbol
                    [type_or_count, count]
                  else
                    [:uchar, type_or_count]
                  end

  @type_size = FFI.type_size(@type)
  @size = @type_size * @count

  name = "/ps-shm#{rand(10000)}"
  @fd = RT.shm_open(name,
                    LibC::O_CREAT | LibC::O_RDWR | LibC::O_EXCL,
                    0777)
  RT.shm_unlink(name)
  
  LibC.ftruncate(@fd, @size)
  @pointer = LibC.mmap(nil,
                       @size,
                       LibC::PROT_READ | LibC::PROT_WRITE,
                       LibC::MAP_SHARED,
                       @fd,
                       0).
    slice(0, size) # slice to get FFI::Pointer that knows its size
                   # (and thus does bounds checking)

  @finalize = self.class.make_finalizer(@pointer.address, @size, @fd)
  ObjectSpace.define_finalizer(self, @finalize)

  super(@pointer)
end

Instance Attribute Details

#countObject (readonly)

Returns the value of attribute count.



11
12
13
# File 'lib/process_shared/shared_memory.rb', line 11

def count
  @count
end

#fdObject (readonly)

Returns the value of attribute fd.



11
12
13
# File 'lib/process_shared/shared_memory.rb', line 11

def fd
  @fd
end

#sizeObject (readonly)

Returns the value of attribute size.



11
12
13
# File 'lib/process_shared/shared_memory.rb', line 11

def size
  @size
end

#typeObject (readonly)

Returns the value of attribute type.



11
12
13
# File 'lib/process_shared/shared_memory.rb', line 11

def type
  @type
end

#type_sizeObject (readonly)

Returns the value of attribute type_size.



11
12
13
# File 'lib/process_shared/shared_memory.rb', line 11

def type_size
  @type_size
end

Class Method Details

.make_finalizer(addr, size, fd) ⇒ Object



17
18
19
20
21
22
23
# File 'lib/process_shared/shared_memory.rb', line 17

def self.make_finalizer(addr, size, fd)
  proc do
    pointer = FFI::Pointer.new(addr)
    LibC.munmap(pointer, size)
    LibC.close(fd)
  end
end

.open(size, &block) ⇒ Object



13
14
15
# File 'lib/process_shared/shared_memory.rb', line 13

def self.open(size, &block)
  new(size).with_self(&block)
end

Instance Method Details

#closeObject



102
103
104
105
# File 'lib/process_shared/shared_memory.rb', line 102

def close
  ObjectSpace.undefine_finalizer(self)
  @finalize.call
end

#get_object(offset) ⇒ Object

Read the serialized object at offset (in bytes) using Marshal.load.

Returns:

  • (Object)


84
85
86
87
88
# File 'lib/process_shared/shared_memory.rb', line 84

def get_object(offset)
  io = to_shm_io
  io.seek(offset)
  Marshal.load(io)
end

#put_object(offset, obj) ⇒ Object

Write the serialization of obj (using Marshal.dump) to this shared memory object at offset (in bytes).

Raises IndexError if there is insufficient space.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/process_shared/shared_memory.rb', line 62

def put_object(offset, obj)
  # FIXME: This is a workaround to an issue I'm seeing in
  # 1.8.7-p352 (not tested in other 1.8's).  If I used the code
  # below that works in 1.9, then inside SharedMemoryIO#write, the
  # passed string object is 'terminated' (garbage collected?) and
  # won't respond to any methods...  This way is less efficient
  # since it involves the creation of an intermediate string, but
  # it works in 1.8.7-p352.
  if RUBY_VERSION =~ /^1.8/
    str = Marshal.dump(obj)
    return put_bytes(offset, str, 0, str.size)
  end

  io = SharedMemoryIO.new(self)
  io.seek(offset)
  Marshal.dump(obj, io)
end

#read_objectObject

Equivalent to obj)

Returns:

  • (Object)


98
99
100
# File 'lib/process_shared/shared_memory.rb', line 98

def read_object
  Marshal.load(to_shm_io)
end

#write_object(obj) ⇒ Object

Equivalent to obj)



91
92
93
# File 'lib/process_shared/shared_memory.rb', line 91

def write_object(obj)
  put_object(0, obj)
end