class Async::Task

def self.current

def self.current
	Thread.current[:async_task] or raise RuntimeError, "No async task available!"
end

def self.current?

def self.current?
	Thread.current[:async_task]
end

def self.yield

def self.yield
	if block_given?
		result = yield
	else
		result = Fiber.yield
	end
	
	if result.is_a? Exception
		raise result
	else
		return result
	end
end

def bind(io)

def bind(io)
	@ios[io.fileno] ||= reactor.wrap(io, self)
end

def close

def close
	@ios.each_value(&:close)
	@ios = []
	
	consume
	
	if @condition
		@condition.signal(@result)
	end
end

def finished?

Whether we can remove this node from the reactor graph.
def finished?
	super && @status != :running
end

def initialize(ios, reactor)

def initialize(ios, reactor)
	if parent = Task.current?
		super(parent)
	else
		super(reactor)
	end
	
	@ios = Hash[
		ios.collect{|io| [io.fileno, reactor.wrap(io, self)]}
	]
	
	@reactor = reactor
	
	@status = :running
	@result = nil
	
	@condition = nil
	
	@fiber = Fiber.new do
		set!
		
		begin
			@result = yield(*@ios.values, self)
			@status = :complete
			# Async.logger.debug("Task #{self} completed normally.")
		rescue Interrupt
			@status = :interrupted
			# Async.logger.debug("Task #{self} interrupted: #{$!}")
		rescue Exception => error
			@result = error
			@status = :failed
			# Async.logger.debug("Task #{self} failed: #{$!}")
			raise
		ensure
			# Async.logger.debug("Task #{self} closing: #{$!}")
			close
		end
	end
end

def register(io, interests)

def register(io, interests)
	@reactor.register(io, interests)
end

def result

def result
	raise RuntimeError.new("Cannot wait on own fiber") if Fiber.current.equal?(@fiber)
	
	if running?
		@condition ||= Condition.new
		@condition.wait
	else
		Task.yield {@result}
	end
end

def run

def run
	@fiber.resume
end

def running?

def running?
	@status == :running
end

def set!

def set!
	# This is actually fiber-local:
	Thread.current[:async_task] = self
end

def stop

def stop
	@children.each(&:stop)
	
	if @fiber.alive?
		exception = Interrupt.new("Stop right now!")
		@fiber.resume(exception)
	end
end

def to_s

def to_s
	"#{super}[#{@status}]"
end

def with(io)

def with(io)
	wrapper = @reactor.wrap(io, self)
	
	yield wrapper
ensure
	wrapper.close
	io.close
end