require 'thread'

module Rex
module Sync

###
#
# This class wraps the logical ConditionVariable class to make it an easier to
# work with interface that is similar to Windows' synchronization events.
#
###
class Event

	Infinite = 10000

	#
	# Initializes a waitable event.  The state parameter initializes the
	# default state of the event.  If auto_reset is true, any calls to set()
	# will automatically reset the event back to an unset state.
	#
	def initialize(state = false, auto_reset = true, param = nil)
		self.state      = state
		self.auto_reset = auto_reset
		self.param      = param
		self.mutex      = Mutex.new
		self.cond       = ConditionVariable.new
	end

	#
	# Sets the event and wakes up anyone who was waiting.
	#
	def set(param = nil)
		self.param = param

		self.mutex.synchronize {
			# If this event does not automatically reset its state,
			# set the state to true
			if (auto_reset == false)
				self.state = true
			end

			self.cond.broadcast
		}
	end

	#
	# Resets the signaled state to false.
	#
	def reset
		self.param = nil
		self.state = false
	end

	#
	# Alias notify with set.
	#
	alias notify set

	#
	# Waits for the event to become signaled.  Timeout is measured in
	# seconds.  Raises TimeoutError if the condition does not become signaled.
	#

	begin
		# XXX: we need to replace this code
		#      continuations slow down YARV
		require "continuation" if not defined? callcc
	rescue ::LoadError
	end

	def wait(t = Infinite)
		callcc { |ctx|
			self.mutex.synchronize {
				ctx.call if (self.state == true)

				Timeout.timeout(t) {
					self.cond.wait(self.mutex)
				}
			}
		}

		return self.param
	end

protected

	attr_accessor :state, :auto_reset # :nodoc:
	attr_accessor :param, :mutex, :cond # :nodoc:

end

end
end

