class Backtor

Constants

MAIN

Attributes

name[R]

Public Class Methods

current() click to toggle source
# File lib/backtor.rb, line 72
def self.current
  if Thread.current == Thread.main
    Backtor::MAIN
  elsif !Thread.current.instance_variable_get(:@backtor).nil?
    Thread.current.instance_variable_get(:@backtor)
  else
    raise 'current thread is not main nor a backtor'
  end
end
new(*args, name: nil, __backtor_special_main: false, &block) click to toggle source
# File lib/backtor.rb, line 11
def initialize(*args, name: nil, __backtor_special_main: false, &block)
  raise ArgumentError, 'must be called with a block' if block.nil?
  raise TypeError, "no implicit conversion of #{name.class} into String" \
    unless name.nil? || name.is_a?(String)
  
  @name = name
  @backtor_id = Backtor.new_id
  @__backtor_special_main = __backtor_special_main

  @thread = Thread.new do
    unless __backtor_special_main
      # TODO: send parameters the proper way, see spec
      # TODO: exceptions
      Backtor.yield(self.instance_exec(*args, &block))
    end
  end
  @thread.abort_on_exception = true
  @thread.instance_variable_set(:@backtor, self)

  @incoming_queue = []
  @incoming_queue_mutex = Mutex.new
  @incoming_queue_cv = ConditionVariable.new
  @outgoing_port = Concurrent::Channel.new
end
new_id() click to toggle source
# File lib/backtor.rb, line 5
def self.new_id
  @last_id ||= 0
  @last_id += 1
  @last_id
end
recv() click to toggle source
# File lib/backtor.rb, line 48
def self.recv
  mutex = Thread.current.instance_variable_get(:@backtor).instance_variable_get(:@incoming_queue_mutex)

  mutex.synchronize do
    queue = Thread.current.instance_variable_get(:@backtor).instance_variable_get(:@incoming_queue)
    cv = Thread.current.instance_variable_get(:@backtor).instance_variable_get(:@incoming_queue_cv)

    cv.wait(mutex) if queue.empty?
    queue.shift
  end
end
yield(obj) click to toggle source
# File lib/backtor.rb, line 64
def self.yield(obj)
  Thread.current.instance_variable_get(:@backtor).instance_variable_get(:@outgoing_port).put(obj)
end

Public Instance Methods

<<(obj)
Alias for: send
inspect() click to toggle source
# File lib/backtor.rb, line 68
def inspect
  "#<Backtor:##{@backtor_id} #{status}>"
end
send(obj) click to toggle source

TODO: proper clone behaviour like real ractors

# File lib/backtor.rb, line 40
def send(obj)
  @incoming_queue_mutex.synchronize do
    @incoming_queue << obj
    @incoming_queue_cv.signal
  end
end
Also aliased as: <<
status() click to toggle source
# File lib/backtor.rb, line 82
def status
  return "running" if @__backtor_special_main
  
  case @thread.status
  when "run"
    "running"
  when false
    "terminated"
  else
    "unimplemented"
  end
end
take() click to toggle source
# File lib/backtor.rb, line 60
def take
  @outgoing_port.take
end