Остановить поток, убедившись, что выполняется определенный окончательный код

Для этого ответа Я написал код типа:

def show_wait_spinner
  dirty = false
  spinner = Thread.new{
    loop{
      print "*"
      dirty = true
      sleep 0.1
      print "\b"  
      dirty = false
    }    
  }
  yield
  spinner.kill
  print "\b" if dirty
end

print "A"
show_wait_spinner{ sleep rand }
puts "B"

Цель состоит в том, чтобы конечный вывод был "AB"— напечатать окончательный "\b"если он еще не был напечатан нитью. Этот код кажется мне беспорядочным в Ruby, где существует begin/rescue/ensure. Поэтому я попробовал некоторые другие реализации show_wait_spinner; все они не гарантируют, что "AB"всегда является выходом, и никогда "A*B"или "AB*".

Есть уборщица,больше Ruby -esque способ реализовать эту логику?

Остановка в конце цикла с помощью мьютекса

def show_wait_spinner
  stop = false
  stopm = Mutex.new
  spinner = Thread.new{
    loop{
      print "*"
      sleep 0.1
      print "\b"
      stopm.synchronize{ break if stop }
    }    
  }
  yield
  stopm.synchronize{ stop = true }
  STDOUT.flush
end

…но моя логика должна быть отключена, так как это всегда приводит к «A *B».

Остановка в конце цикла через локальную переменную Thread -

Эта вторая попытка приводит к тому, что иногда печатается «A *B», иногда «AB»:

def show_wait_spinner
  stop = false
  spinner = Thread.new{
    Thread.current[:stop] = false
    loop{
      print "*"
      sleep 0.1
      print "\b"
      stopm.synchronize{ break if Thread.current[:stop] }
    }    
  }
  yield
  spinner[:stop] = true
  STDOUT.flush
end

Убить и убедиться, что поток

def show_wait_spinner
  spinner = Thread.new{
    dirty = false
    begin
      loop{
        print "*"
        dirty = true
        sleep 0.1
        print "\b"
        dirty = false
      }    
    ensure
      print "\b" if dirty
    end
  }
  yield
  spinner.kill
  STDOUT.flush
end

Поднять и Спасите нить

def show_wait_spinner
  spinner = Thread.new{
    dirty = false
    begin
      loop{
        print "*"
        dirty = true
        sleep 0.1
        print "\b"
        dirty = false
      }    
    rescue
      puts "YAY"
      print "\b" if dirty
    end
  }
  yield
  spinner.raise
  STDOUT.flush
end

5
задан Community 23 May 2017 в 11:55
поделиться