class Proco
module MT
# @private
class Worker
  include Proco::MT::Threaded

  attr_reader :counter

  def initialize logger
    super()

    @logger  = logger
    @block   = nil
    @counter = 0

    spawn do
      work while running?
    end
  end

  def work
    # Not using do_when makes the code around the task block about 10% faster
    @mtx.lock
    while true
      break if @block
      return unless running?
      @cv.wait @mtx
    end
    block = @block
    @counter += 1
    @block = nil

    # Release lock here, so that a new task can be assigned during the execution
    # 50 -> 30
    @cv.broadcast
    @mtx.unlock

    # Work!
    block.call
  end

  # Blocks when working
  def assign &block
    #do_when(Proc.new { return unless running?; @block.nil? }) do
    #  @block = block
    #end
    @mtx.lock
    while true
      break unless @block
      return unless running?
      @cv.wait @mtx
    end
    @block = block
  ensure
    @cv.broadcast
    @mtx.unlock
  end

  # Returns nil when working
  def try_assign &block
    #try_when(Proc.new { return unless running?; @block.nil? }) do
    #  @block = block
    #end
    return unless @mtx.try_lock

    begin
      return if !running? || @block
      @block = block
    ensure
      @cv.broadcast
      @mtx.unlock
    end
  end

  def exit
    wait_until { @block.nil? }
    super
  end
end#Worker
end#MT
end#Proco
