lib/elevate/operation.rb in elevate-0.5.0 vs lib/elevate/operation.rb in elevate-0.6.0

- old
+ new

@@ -1,47 +1,85 @@ module Elevate + # Executes an Elevate task, firing callbacks along the way. + # class ElevateOperation < NSOperation + # Designated initializer. + # + # @return [ElevateOperation] + # newly initialized instance + # + # @api private def initWithTarget(target, args:args) - if init() + if init @coordinator = IOCoordinator.new @context = TaskContext.new(args, &target) + @timeout_callback = nil + @timer = nil @update_callback = nil @finish_callback = nil setCompletionBlock(lambda do if @finish_callback @finish_callback.call(@result, @exception) unless isCancelled end Dispatch::Queue.main.sync do @context = nil + + if @timer + @timer.invalidate + @timer = nil + end + + @timeout_callback = nil @update_callback = nil @finish_callback = nil end end) end self end + # Cancels the currently running task. + # + # @return [void] + # + # @api public def cancel @coordinator.cancel super end + # Returns information about this task. + # + # @return [String] + # String suitable for debugging purposes. + # + # @api public def inspect details = [] details << "<canceled>" if @coordinator.cancelled? "#<#{self.class.name}: #{details.join(" ")}>" end + # Logs debugging information in certain configurations. + # + # @return [void] + # + # @api private def log(line) puts line unless RUBYMOTION_ENV == "test" end + # Runs the specified task. + # + # @return [void] + # + # @api private def main log " START: #{inspect}" @coordinator.install @@ -52,34 +90,129 @@ end end rescue Exception => e @exception = e + + if e.is_a?(TimeoutError) + @timeout_callback.call if @timeout_callback + end end @coordinator.uninstall log "FINISH: #{inspect}" end + # Returns the exception that terminated this task, if any. + # + # If the task has not finished, returns nil. + # + # @return [Exception, nil] + # exception that terminated the task + # + # @api public attr_reader :exception + + # Returns the result of the task block. + # + # If the task has not finished, returns nil. + # + # @return [Object, nil] + # result of the task block + # + # @api public attr_reader :result + # Sets the callback to be run upon completion of this task. Do not call + # this method after the task has started. + # + # @param callback [Elevate::Callback] + # completion callback + # + # @return [void] + # + # @api private def on_finish=(callback) @finish_callback = callback end + # Sets the callback to be run when this task is queued. + # + # Do not call this method after the task has started. + # + # @param callback [Elevate::Callback] + # callback to be invoked when queueing + # + # @return [void] + # + # @api private def on_start=(callback) start_callback = callback start_callback.retain Dispatch::Queue.main.async do start_callback.call unless isCancelled start_callback.release end end + # Handles timeout expiration. + # + # @return [void] + # + # @api private + def on_timeout_elapsed(timer) + @coordinator.cancel(TimeoutError) + end + + # Sets the timeout callback. + # + # @param callback [Elevate::Callback] + # callback to run on timeout + # + # @return [void] + # + # @api private + def on_timeout=(callback) + @timeout_callback = callback + end + + # Sets the update callback, which is invoked for any yield statements in the task. + # + # @param callback [Elevate::Callback] + # @return [void] + # + # @api private def on_update=(callback) @update_callback = callback + end + + # Sets the timeout interval for this task. + # + # The timeout starts when the task is queued, not when it is started. + # + # @param interval [Fixnum] + # seconds to allow for task completion + # + # @return [void] + # + # @api private + def timeout=(interval) + @timer = NSTimer.scheduledTimerWithTimeInterval(interval, + target: self, + selector: :"on_timeout_elapsed:", + userInfo: nil, + repeats: false) + end + + # Returns whether this task timed out. + # + # @return [Boolean] + # true if this task was aborted due to a time out. + # + # @api public + def timed_out? + @exception.class == TimeoutError end end end