require 'process_shared' class ProcessShareWrapper attr_accessor :data attr_accessor :need_process def parse_value(v) if v[0] == Fixnum v[1].read_int64 elsif v[0] == Float v[1].read_float else byte_size = v[3].read_int64 if v[0] == String v[1].read_string(byte_size).force_encoding('utf-8') else Marshal.load(v[1].read_bytes(byte_size)) end end end def save_value(h,v) if h[0] == Fixnum h[1].write_int64(v) elsif h[0] == Float h[1].write_float(v) else if h[0] == String tmp_obj = "#{v}\0" else tmp_obj = Marshal.dump(v) end str_len = h[2].read_int64 if tmp_obj.bytesize > str_len h[1].write_string("\0") puts "#{v.class}: out of memory" puts v # puts "-------------------------------" else begin h[1].write_string(tmp_obj) rescue => e puts "#{v.class}: #{e.to_s}" puts v puts "-------------------------------" end h[3].write_int64(tmp_obj.bytesize) end end end def initialize(data, min_byte_size=256) self.need_process = true def process_string(tmp_obj, str_len) pointer = ProcessShared::SharedMemory.new(:uint8, str_len) pointer.write_string(tmp_obj) pointer end def process_value(v, min_byte_size) case v when String str_len = v.bytesize * 2 str_len = min_byte_size if str_len < min_byte_size str_len_obj = ProcessShared::SharedMemory.new(:int64) str_len_obj.write_int64(str_len) byte_size_obj = ProcessShared::SharedMemory.new(:int64) byte_size_obj.write_int64(v.bytesize) [String, process_string(v, str_len), str_len_obj, byte_size_obj] when Fixnum tmp = ProcessShared::SharedMemory.new(:int64) tmp.write_int64(v) [Fixnum,tmp] when Float tmp = ProcessShared::SharedMemory.new(:float) tmp.write_float(v) [Float,tmp] else tmp_obj = Marshal.dump(v) str_len = tmp_obj.bytesize*2 if v.respond_to?(:min_memory) str_len = [str_len, v.min_memory].max else str_len = [str_len, 1000].max end str_len_obj = ProcessShared::SharedMemory.new(:int64) str_len_obj.write_int64(str_len) byte_size_obj = ProcessShared::SharedMemory.new(:int64) byte_size_obj.write_int64(tmp_obj.bytesize) [Object, process_string(tmp_obj, str_len), str_len_obj, byte_size_obj] end end case data when Hash self.data = data.map do |k,v| [k,process_value(v, min_byte_size)] end.to_h when Array self.data = data.map{|v| process_value(v, min_byte_size)} else self.need_process = false self.data = process_value(data, min_byte_size) end end def value if self.need_process case self.data when Hash self.data.map{|k,v| [k,parse_value(v)]}.to_h when Array self.data.map{|v| parse_value(v)} end else parse_value(self.data) end end def value=(v) if self.need_process raise 'You cannot change value.' else save_value(self.data,v) end end def [](k) parse_value(self.data[k]) end def []=(k,v) save_value(self.data[k],v) end end