class Delayer

ブロックを、後で時間があいたときに順次実行する。 名前deferのほうがよかったんじゃね

Constants

CRITICAL
FASTER
LAST
LATER
NORMAL

Attributes

exception[RW]
idle_handler[RW]
backtrace[R]
status[R]

Public Class Methods

busy?() click to toggle source

Delayerのタスクを消化中ならtrueを返す

# File core/delayer.rb, line 56
def busy?
  @busy end
empty?() click to toggle source

仕事がなければtrue

# File core/delayer.rb, line 60
def empty?
  @@routines.all?{|r| r.empty? } end
event_lock() { || ... } click to toggle source
# File core/plugin/gtk/delayer.rb, line 11
def event_lock
  @event_lock = true
  result = yield
  @event_lock = false
  @idle_handler = nil
  on_regist(nil)
  result end
freeze() click to toggle source

このメソッドが呼ばれたら、以後 ::run が呼ばれても、Delayerオブジェクト を実行せずにすぐにreturnするようになる。

# File core/delayer.rb, line 69
def freeze
  @frozen = true end
idle_handler_lock() click to toggle source
# File core/plugin/gtk/delayer.rb, line 8
def idle_handler_lock
  @idle_handler_lock ||= Mutex.new end
melt() click to toggle source

freezeのはんたい

# File core/delayer.rb, line 73
def melt
  @frozen = false end
new(prio = NORMAL, *args, &block) click to toggle source

あとで実行するブロックを登録する。

# File core/delayer.rb, line 80
def initialize(prio = NORMAL, *args, &block)
  @routine = block
  @args = args
  @backtrace = caller
  @status = :wait
  regist(prio)
  Delayer.on_regist(self)
end
on_regist(delayer) click to toggle source
# File core/plugin/gtk/delayer.rb, line 19
def on_regist(delayer)
  idle_handler_lock.synchronize {
    if not(defined?(@event_lock) and @event_lock)
      @idle_handler ||= Gtk.idle_add_priority(GLib::PRIORITY_LOW) {
        next true if @event_lock
        begin
          Delayer.run
        rescue => e
          into_debug_mode(e)
          Gtk.main_quit end
        idle_handler_lock.synchronize {
          if Delayer.empty?
            @idle_handler = nil
            false
          else
            true end } } end } end
run() click to toggle source

登録されたDelayerオブジェクトをいくつか実行する。 0.1秒以内に実行が終わらなければ、残りは保留してとりあえず処理を戻す。

# File core/delayer.rb, line 22
def run
  return if @frozen
  debugging_wait
  begin
    @busy = true
    @st = Process.times.utime
    3.times{ |cnt|
      procs = []
      if not @@routines[cnt].empty? then
        procs = @@routines[cnt].clone
        procs.each{ |routine|
          @@routines[cnt].delete(routine)
          if Mopt.debug
            r_start = Process.times.utime
            routine.run
            if (r_end = Process.times.utime - r_start) > 0.1
              bt = routine.backtrace.find{ |bt| not bt.include?('delayer') }
              bt = routine.backtrace.first if not bt
              Plugin.call(:processtime, :delayer, "#{"%.2f" % r_end},#{bt.gsub(FOLLOW_DIR, '{MIKUTTER_DIR}')}")
            end
          else
            routine.run end
          return if time_limit? } end }
  rescue => e
    Delayer.exception = e
    raise e
  ensure
    @busy = false end end
size() click to toggle source

残っているDelayerの数を返す

# File core/delayer.rb, line 64
def size
  @@routines.map(&:size).reduce(:+)end
time_limit?() click to toggle source
# File core/delayer.rb, line 52
def time_limit?
  (Process.times.utime - @st) > 0.02 end

Public Instance Methods

reject() click to toggle source

このDelayerを取り消す。処理が呼ばれる前に呼べば、処理をキャンセルできる

# File core/delayer.rb, line 90
def reject
  @status = nil
end
run() click to toggle source

このブロックを実行する。内部で呼ぶためにあるので、明示的に呼ばないこと

# File core/delayer.rb, line 95
def run
  return if @status != :wait
  @status = :run
  begin
    @routine.call(*@args)
  rescue Exception => e
    now = caller.size + 1     # @routine.callのぶんスタックが1つ多い
    $@ = e.backtrace[0, e.backtrace.size - now] + @backtrace
    raise e
  end
  @routine = nil
  @status = nil
end