require 'thread' module Skylight class GC METHODS = [ :enable, :total_time ] TH_KEY = :SK_GC_CURR_WINDOW include Util::Logging def self.update if win = Thread.current[TH_KEY] win.update end end def self.time if win = Thread.current[TH_KEY] win.time else 0 end end attr_reader :config def initialize(config, profiler) @listeners = [] @config = config @lock = Mutex.new @time = 0 if METHODS.all? { |m| profiler.respond_to?(m) } @profiler = profiler @time = @profiler.total_time else debug "disabling GC profiling" end end def enable @profiler.enable if @profiler end def start_track return if Thread.current[TH_KEY] unless @profiler win = Window.new(nil) else win = Window.new(self) @lock.synchronize do __update @listeners << win end end Thread.current[TH_KEY] = win end def stop_track if win = Thread.current[TH_KEY] Thread.current[TH_KEY] = nil win.release end end def track return unless block_given? start_track begin yield ensure stop_track end end def release(win) @lock.synchronize do @listeners.delete(win) end end def update @lock.synchronize do __update end nil end private def __update time = @profiler.total_time diff = time - @time @time = time if diff > 0 @listeners.each do |l| l.add(diff) end end end class Window attr_reader :time def initialize(global) @global = global @time = 0 end def update @global.update if @global end def add(time) @time += time end def release @global.release(self) if @global end end end end