Class: RubyProcess::ClassProxy

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_process/class_proxy.rb

Overview

This class is used to seamlessly use leaky classes without working through ‘RubyProcess’.

Examples

RubyProcess::ClassProxy.run do |data|
  data[:subproc].static(:Object, :require, "rubygems")
  data[:subproc].static(:Object, :require, "rexml/document")

  doc = RubyProcess::ClassProxy::REXML::Document.new("test")
  strio = StringIO.new
  doc.write(strio)
  puts strio.string #=> "<test/>"
  raise "REXML shouldnt be defined?" if Kernel.const_defined?(:REXML)

Constant Summary collapse

@@lock =

Lock is used to to create new Ruby-process-instances and not doing double-counts.

Mutex.new
@@instances =

Counts how many instances are using the Cproxy-module. This way it can be safely unset once no-body is using it again.

0
@@subproc =

This variable will hold the ‘RubyProcess’-object where sub-objects will be created.

nil

Class Method Summary collapse

Class Method Details

.const_missing(name) ⇒ Object

Creates the new constant under the ‘RubyProcess::ClassProxy’-namespace.



76
77
78
79
80
# File 'lib/ruby_process/class_proxy.rb', line 76

def self.const_missing(name)
  RubyProcess::ClassProxy.load_class(self, name) unless const_defined?(name)
  raise "Still not created on const: '#{name}'." unless const_defined?(name)
  return self.const_get(name)
end

.destroy_loaded_constantsObject

Destroy all loaded sub-process-constants.



69
70
71
72
73
# File 'lib/ruby_process/class_proxy.rb', line 69

def self.destroy_loaded_constants
  self.constants.each do |constant|
    self.__send__(:remove_const, constant)
  end
end

.load_class(const, name) ⇒ Object

Loads a new class to the given constants namespace for recursive creating of missing classes.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/ruby_process/class_proxy.rb', line 83

def self.load_class(const, name)
  const.const_set(name, Class.new{
    #Use 'const_missing' to auto-create missing sub-constants recursivly.
    def self.const_missing(name)
      RubyProcess::ClassProxy.load_class(self, name) unless const_defined?(name)
      raise "Still not created on const: '#{name}'." unless self.const_defined?(name)
      return self.const_get(name)
    end

    #Manipulate 'new'-method return proxy-objects instead of real objects.
    def self.new(*args, &blk)
      name_match = self.name.to_s.match(/^RubyProcess::ClassProxy::(.+)$/)
      class_name = name_match[1]
      return RubyProcess::ClassProxy.subproc.new(class_name, *args, &blk)
    end

    def self.method_missing(method_name, *args, &blk)
      name_match = self.name.to_s.match(/^RubyProcess::ClassProxy::(.+)$/)
      class_name = name_match[1]
      return RubyProcess::ClassProxy.subproc.static(class_name, method_name, *args, &blk)
    end
  })
end

.runObject

All use should go through this method to automatically destroy sub-processes and keep track of ressources.



23
24
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
57
58
59
60
# File 'lib/ruby_process/class_proxy.rb', line 23

def self.run
  #Increase count of instances that are using Cproxy and set the subproc-object if not already set.
  @@lock.synchronize do
    #Check if the sub-process is alive.
    if @@subproc && (!@@subproc.alive? || @@subproc.destroyed?)
      raise "Cant destroy sub-process because instances are running: '#{@@instances}'." if @@instances > 0
      @@subproc.destroy
      @@subproc = nil
    end

    #Start a new subprocess if none is defined and active.
    unless @@subproc
      subproc = RubyProcess.new(title: "ruby_process_cproxy", debug: false)
      subproc.spawn_process
      @@subproc = subproc
    end

    @@instances += 1
  end

  begin
    yield(subproc: @@subproc)
    raise "'run'-caller destroyed sub-process. This shouldn't happen." if @@subproc.destroyed?
  ensure
    @@lock.synchronize do
      @@instances -= 1

      if @@instances <= 0
        begin
          @@subproc.destroy
        ensure
          @@subproc = nil
          self.destroy_loaded_constants
        end
      end
    end
  end
end

.subprocObject

Returns the ‘RubyProcess’-object or raises an error if it has not been set.



63
64
65
66
# File 'lib/ruby_process/class_proxy.rb', line 63

def self.subproc
  raise "CProxy process not set for some reason?" unless @@subproc
  return @@subproc
end