lib/elevate/io_coordinator.rb in elevate-0.5.0 vs lib/elevate/io_coordinator.rb in elevate-0.6.0
- old
+ new
@@ -1,69 +1,134 @@
module Elevate
+ # Implements task cancellation.
+ #
+ # Compliant I/O mechanisms (such as HTTP requests) register long-running
+ # operations with a well-known instance of this class. When a cancellation
+ # request is received from another thread, the long-running operation is
+ # cancelled.
class IOCoordinator
+ # Retrieves the current IOCoordinator for this thread.
+ #
+ # @return [IOCoordinator,nil]
+ # IOCoordinator previously installed to this thread
+ #
+ # @api public
def self.for_thread
Thread.current[:io_coordinator]
end
+ # Initializes a new IOCoordinator with the default state.
+ #
+ # @api private
def initialize
@lock = NSLock.alloc.init
@blocking_operation = nil
@cancelled = false
+ @exception_class = nil
end
- def cancel
+ # Cancels the I/O operation (if any), raising an exception of type
+ # +exception_class+ in the worker thread.
+ #
+ # If the thread is not currently blocked, then set a flag requesting cancellation.
+ #
+ # @return [void]
+ #
+ # @api private
+ def cancel(exception_class = CancelledError)
blocking_operation = nil
- @lock.lock()
+ @lock.lock
@cancelled = true
+ @exception_class = exception_class
blocking_operation = @blocking_operation
- @lock.unlock()
+ @lock.unlock
if blocking_operation
- blocking_operation.cancel()
+ blocking_operation.cancel
end
end
+ # Returns the cancelled flag.
+ #
+ # @return [Boolean]
+ # true if this coordinator has been +cancel+ed previously.
+ #
+ # @api private
def cancelled?
cancelled = nil
- @lock.lock()
+ @lock.lock
cancelled = @cancelled
- @lock.unlock()
+ @lock.unlock
cancelled
end
+ # Installs this IOCoordinator to a well-known thread-local.
+ #
+ # @return [void]
+ #
+ # @api private
def install
Thread.current[:io_coordinator] = self
end
+ # Marks the specified operation as one that will potentially block the
+ # worker thread for a significant amount of time.
+ #
+ # @param operation [#cancel]
+ # operation responsible for blocking
+ #
+ # @return [void]
+ #
+ # @api public
def signal_blocked(operation)
check_for_cancellation
- @lock.lock()
+ @lock.lock
@blocking_operation = operation
- @lock.unlock()
+ @lock.unlock
end
+ # Signals that the specified operation has completed, and is no longer
+ # responsible for blocking the worker thread.
+ #
+ # @return [void]
+ #
+ # @api public
def signal_unblocked(operation)
- @lock.lock()
+ @lock.lock
@blocking_operation = nil
- @lock.unlock()
+ @lock.unlock
check_for_cancellation
end
+ # Removes the thread-local for the calling thread.
+ #
+ # @return [void]
+ #
+ # @api private
def uninstall
Thread.current[:io_coordinator] = nil
end
private
def check_for_cancellation
- raise CancelledError if cancelled?
+ raise @exception_class if cancelled?
end
end
+ # Raised when a task is cancelled.
+ #
+ # @api public
class CancelledError < StandardError
+ end
+
+ # Raised when a task's timeout expires
+ #
+ # @api public
+ class TimeoutError < CancelledError
end
end