Methods
A
E
I
J
K
N
P
S
T
W
Class Public methods
activate(pc)
# File lib/shell/process-controller.rb, line 34
def activate(pc)
  process_controllers_exclusive do
    @ProcessControllers[pc] ||= 0
    @ProcessControllers[pc] += 1
  end
end
each_active_object()
# File lib/shell/process-controller.rb, line 51
def each_active_object
  process_controllers_exclusive do
    for ref in @ProcessControllers.keys
      yield ref
    end
  end
end
inactivate(pc)
# File lib/shell/process-controller.rb, line 41
def inactivate(pc)
  process_controllers_exclusive do
    if @ProcessControllers[pc]
      if (@ProcessControllers[pc] -= 1) == 0
        @ProcessControllers.delete(pc)
      end
    end
  end
end
new(shell)
# File lib/shell/process-controller.rb, line 60
def initialize(shell)
  @shell = shell
  @waiting_jobs = []
  @active_jobs = []
  @jobs_sync = Sync.new
  @job_monitor = Mutex.new
  @job_condition = ConditionVariable.new
end
process_controllers_exclusive()
# File lib/shell/process-controller.rb, line 25
def process_controllers_exclusive
  begin
    @ProcessControllers.lock unless Thread.critical
    yield
  ensure
    @ProcessControllers.unlock unless Thread.critical
  end
end
Instance Public methods
active_job?(job)
# File lib/shell/process-controller.rb, line 143
def active_job?(job)
  @jobs_sync.synchronize(:SH) do
    @active_jobs.include?(job)
  end
end
active_jobs()
# File lib/shell/process-controller.rb, line 79
def active_jobs
  @active_jobs
end
active_jobs_exist?()
# File lib/shell/process-controller.rb, line 93
def active_jobs_exist?
  @jobs_sync.synchronize(:SH) do
    @active_jobs.empty?
  end
end
add_schedule(command)

schedule a command

# File lib/shell/process-controller.rb, line 106
def add_schedule(command)
  @jobs_sync.synchronize(:EX) do
    ProcessController.activate(self)
    if @active_jobs.empty?
      start_job command
    else
      @waiting_jobs.push(command)
    end
  end
end
jobs()
# File lib/shell/process-controller.rb, line 70
def jobs
  jobs = []
  @jobs_sync.synchronize(:SH) do
    jobs.concat @waiting_jobs
    jobs.concat @active_jobs
  end
  jobs
end
jobs_exist?()
# File lib/shell/process-controller.rb, line 87
def jobs_exist?
  @jobs_sync.synchronize(:SH) do
    @active_jobs.empty? or @waiting_jobs.empty?
  end
end
kill_job(sig, command)

kill a job

# File lib/shell/process-controller.rb, line 161
def kill_job(sig, command)
  @jobs_sync.synchronize(:SH) do
    if @waiting_jobs.delete command
      ProcessController.inactivate(self)
      return
    elsif @active_jobs.include?(command)
      begin
        r = command.kill(sig)
        ProcessController.inactivate(self)
      rescue
        print "Shell: Warn: $!\n" if @shell.verbose?
        return nil
      end
      @active_jobs.delete command
      r
    end
  end
end
sfork(command, &block)

simple fork

# File lib/shell/process-controller.rb, line 194
def sfork(command, &block)
  pipe_me_in, pipe_peer_out = IO.pipe
  pipe_peer_in, pipe_me_out = IO.pipe
  Thread.critical = true
  STDOUT.flush
  ProcessController.each_active_object do |pc|
    for jobs in pc.active_jobs
      jobs.flush
    end
  end
  pid = fork {
    Thread.critical = true
    Thread.list.each do |th|
      th.kill unless [Thread.main, Thread.current].include?(th)
    end
    STDIN.reopen(pipe_peer_in)
    STDOUT.reopen(pipe_peer_out)
    ObjectSpace.each_object(IO) do |io|
      if ![STDIN, STDOUT, STDERR].include?(io)
        io.close unless io.closed?
      end
    end
    yield
  }
  pipe_peer_in.close
  pipe_peer_out.close
  command.notify "job(%name:##{pid}) start", @shell.debug?
  Thread.critical = false
  th = Thread.start {
    Thread.critical = true
    begin
      _pid = nil
      command.notify("job(%id) start to waiting finish.", @shell.debug?)
      Thread.critical = false
      _pid = Process.waitpid(pid, nil)
    rescue Errno::ECHILD
      command.notify "warn: job(%id) was done already waitipd."
      _pid = true
    ensure
      # when the process ends, wait until the command termintes
      if _pid
      else
        command.notify("notice: Process finishing...",
                       "wait for Job[%id] to finish.",
                       "You can use Shell#transact or Shell#check_point for more safe execution.")
        redo
      end
      Thread.exclusive do
        @job_monitor.synchronize do
          terminate_job(command)
          @job_condition.signal
          command.notify "job(%id) finish.", @shell.debug?
        end
      end
    end
  }
  return pid, pipe_me_in, pipe_me_out
end
start_job(command = nil)

start a job

# File lib/shell/process-controller.rb, line 118
def start_job(command = nil)
  @jobs_sync.synchronize(:EX) do
    if command
      return if command.active?
      @waiting_jobs.delete command
    else
      command = @waiting_jobs.shift
      return unless command
    end
    @active_jobs.push command
    command.start
    # start all jobs that input from the job
    for job in @waiting_jobs
      start_job(job) if job.input == command
    end
  end
end
terminate_job(command)

terminate a job

# File lib/shell/process-controller.rb, line 150
def terminate_job(command)
  @jobs_sync.synchronize(:EX) do
    @active_jobs.delete command
    ProcessController.inactivate(self)
    if @active_jobs.empty?
      start_job
    end
  end
end
wait_all_jobs_execution()

wait for all jobs to terminate

# File lib/shell/process-controller.rb, line 181
def wait_all_jobs_execution
  @job_monitor.synchronize do
    begin
      while !jobs.empty?
        @job_condition.wait(@job_monitor)
      end
    ensure
      redo unless jobs.empty?
    end
  end
end
waiting_job?(job)
# File lib/shell/process-controller.rb, line 137
def waiting_job?(job)
  @jobs_sync.synchronize(:SH) do
    @waiting_jobs.include?(job)
  end
end
waiting_jobs()
# File lib/shell/process-controller.rb, line 83
def waiting_jobs
  @waiting_jobs
end
waiting_jobs_exist?()
# File lib/shell/process-controller.rb, line 99
def waiting_jobs_exist?
  @jobs_sync.synchronize(:SH) do
    @waiting_jobs.empty?
  end
end