Class: Zoidberg::Proxy::Confined

Inherits:
Zoidberg::Proxy show all
Defined in:
lib/zoidberg/proxy/confined.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Zoidberg::Proxy

#_aquire_lock!, #_release_lock!, #_zoidberg_destroy!, #_zoidberg_handle_unexpected_error, #_zoidberg_link, #_zoidberg_link=, #_zoidberg_locked?, #_zoidberg_object, #_zoidberg_set_instance, #_zoidberg_signal, #_zoidberg_signal=, #_zoidberg_signal_interface, #_zoidberg_timer, #_zoidberg_unexpected_error, #_zoidberg_unsupervise, #async, inherited, register, registry, scrub!, #signal, #terminate

Constructor Details

#initialize(klass, *args, &block) ⇒ self

Create a new isolation wrapper

Parameters:

  • object (Object)

    object to wrap



21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/zoidberg/proxy/confined.rb', line 21

def initialize(klass, *args, &block)
  @_requests = ::Queue.new
  @_results = ::Queue.new
  @_blocked = false
  @_source_thread = ::Thread.new do
    ::Zoidberg.logger.debug 'Starting the isolation request processor'
    ::Thread.current[:root_fiber] = ::Fiber.current
    _isolate!
  end
  @_build_args = [klass, *args, block]
  @_supervised = klass.include?(::Zoidberg::Supervise)
  ::Zoidberg.logger.debug "Zoidberg object isolation wrap: #{@_build_args.inspect}"
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(*args, &block) ⇒ Object

Wrapping for provided object



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/zoidberg/proxy/confined.rb', line 52

def method_missing(*args, &block)
  res = nil
  begin
    if(::ENV['ZOIDBERG_TESTING'])
      ::Kernel.require 'timeout'
      ::Timeout.timeout(::ENV.fetch('ZOIDBERG_TESTING_TIMEOUT', 5).to_i) do
        res = _isolated_request(*args, &block)
      end
    else
      res = _isolated_request(*args, &block)
    end
  rescue ::Zoidberg::AbortException => e
    ::Kernel.raise e.original_exception
  rescue ::Exception => e
    _zoidberg_unexpected_error(e)
    ::Zoidberg.logger.debug "Exception on: #{_raw_instance.class}##{args.first}(#{args.slice(1, args.size).map(&:inspect).join(', ')})"
    ::Kernel.raise e
  end
  res
end

Instance Attribute Details

#_blockedTrueClass, FalseClass (readonly)

Returns blocked running task.

Returns:

  • (TrueClass, FalseClass)

    blocked running task



15
16
17
# File 'lib/zoidberg/proxy/confined.rb', line 15

def _blocked
  @_blocked
end

#_requestsQueue (readonly)

Returns current request queue.

Returns:

  • (Queue)

    current request queue



11
12
13
# File 'lib/zoidberg/proxy/confined.rb', line 11

def _requests
  @_requests
end

#_resultsQueue (readonly)

Returns result queue.

Returns:

  • (Queue)

    result queue



13
14
15
# File 'lib/zoidberg/proxy/confined.rb', line 13

def _results
  @_results
end

#_source_threadThread (readonly)

Returns container thread.

Returns:

  • (Thread)

    container thread



9
10
11
# File 'lib/zoidberg/proxy/confined.rb', line 9

def _source_thread
  @_source_thread
end

Instance Method Details

#_async_request(blocking, method_name, *args, &block) ⇒ Object

Note:

use caution with shared data using this method

Call into instance asynchronously



38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/zoidberg/proxy/confined.rb', line 38

def _async_request(blocking, method_name, *args, &block)
  ::Zoidberg.logger.debug "Received async request from remote thread. Added to queue: #{_raw_instance.class}##{method_name}(#{args.map(&:inspect).join(', ')})"
  _requests << ::Smash.new(
    :uuid => ::Zoidberg.uuid,
    :arguments => [method_name, *args],
    :block => block,
    :response => nil,
    :async => true,
    :blocked => !!blocking
  )
  nil
end

#_isolated_request(method_name, *args) { ... } ⇒ Object

Send the method request to the wrapped instance

Parameters:

  • method_name (String, Symbol)

    method to call on instance

  • args (Object)

    arguments for call

Yields:

  • block for call

Returns:

  • (Object)

    result



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/zoidberg/proxy/confined.rb', line 79

def _isolated_request(method_name, *args, &block)
  if(_source_thread == ::Thread.current)
    ::Zoidberg.logger.debug "Received request from source thread: #{_raw_instance.class}##{method_name}(#{args.map(&:inspect).join(', ')})"
    _raw_instance.__send__(method_name, *args, &block)
  else
    unless(_source_thread.alive?)
      ::Kernel.raise ::Zoidberg::DeadException.new('Instance in terminated state!', object_id)
    end
    ::Zoidberg.logger.debug "Received request from remote thread. Added to queue: #{_raw_instance.class}##{method_name}(#{args.map(&:inspect).join(', ')})"
    response_queue = ::Queue.new
    _requests << ::Smash.new(
      :uuid => ::Zoidberg.uuid,
      :arguments => [method_name, *args],
      :block => block,
      :response => response_queue
    )
    result = response_queue.pop
    if(result.is_a?(::Exception))
      ::Kernel.raise result
    else
      result
    end
  end
end

#_zoidberg_available?TrueClass, FalseClass

Returns:

  • (TrueClass, FalseClass)


105
106
107
# File 'lib/zoidberg/proxy/confined.rb', line 105

def _zoidberg_available?
  !_blocked
end

#inspectObject



118
119
120
# File 'lib/zoidberg/proxy/confined.rb', line 118

def inspect
  _raw_instance.inspect
end

#task_defer(wait_task) ⇒ Object



114
115
116
# File 'lib/zoidberg/proxy/confined.rb', line 114

def task_defer(wait_task)
  _results << wait_task
end

#threaded?TrueClass, FalseClass

Returns:

  • (TrueClass, FalseClass)


110
111
112
# File 'lib/zoidberg/proxy/confined.rb', line 110

def threaded?
  ::Thread.current != _source_thread
end

#to_sObject



122
123
124
# File 'lib/zoidberg/proxy/confined.rb', line 122

def to_s
  _raw_inspect.to_s
end