class MyMonitor
  attr_reader :mon_owner, :mon_count

  def initialize
    @mon_owner = nil
    @mon_count = 0
    @mon_mutex = Mutex.new
  end

  def mon_enter
    if @mon_owner != Thread.current
      @mon_mutex.lock
      @mon_owner = Thread.current
    end
    @mon_count += 1
  end

  def mon_exit
    @mon_count -= 1
    if @mon_count == 0
      @mon_owner = nil
      @mon_mutex.unlock
    end
  end

  def stuff
    mon_enter
    print
    mon_exit
  end
end

monitor = MyMonitor.new

set_trace_func proc { |event, file, line, id, binding, classname|
  info = sprintf("%s %8s %s:%-2d %10s %8s %s %d", Thread.current, event, file, line, id, classname, monitor.mon_owner, monitor.mon_count)
  color = 1 + Thread.current.object_id / 4 % 256
  puts "\e[38;5;#{color}m #{info} \e[39m"
}

1_000.times do
  thread = Thread.new do
    monitor.stuff
    sleep
  end
  monitor.stuff
  thread.kill
  thread.join
end
