lib/async/container/thread.rb in async-container-0.16.6 vs lib/async/container/thread.rb in async-container-0.16.7

- old
+ new

@@ -26,26 +26,37 @@ require 'async/logger' module Async module Container + # Represents a running child thread from the point of view of the parent container. class Thread < Channel + # Used to propagate the exit status of a child process invoked by {Instance#exec}. class Exit < Exception + # Initialize the exit status. + # @parameter status [::Process::Status] The process exit status. def initialize(status) @status = status end + # The process exit status. + # @attribute [::Process::Status] attr :status + # The process exit status if it was an error. + # @returns [::Process::Status | Nil] def error unless status.success? status end end end + # Represents a running child thread from the point of view of the child thread. class Instance < Notify::Pipe + # Wrap an instance around the {Thread} instance from within the threaded child. + # @parameter thread [Thread] The thread intance to wrap. def self.for(thread) instance = self.new(thread.out) return instance end @@ -55,18 +66,24 @@ @thread = ::Thread.current super end + # Set the name of the thread. + # @parameter value [String] The name to set. def name= value @thread.name = value end + # Get the name of the thread. + # @returns [String] def name @thread.name end + # Execute a child process using {::Process.spawn}. In order to simulate {::Process.exec}, an {Exit} instance is raised to propagage exit status. + # This creates the illusion that this method does not return (normally). def exec(*arguments, ready: true, **options) if ready self.ready!(status: "(spawn)") if ready else self.before_spawn(arguments, options) @@ -89,10 +106,12 @@ yield Instance.for(thread) end end end + # Initialize the thread. + # @parameter name [String] The name to use for the child thread. def initialize(name: nil) super() @status = nil @@ -114,61 +133,79 @@ finished end end end + # Set the name of the thread. + # @parameter value [String] The name to set. def name= value @thread.name = value end + # Get the name of the thread. + # @returns [String] def name @thread.name end + # A human readable representation of the thread. + # @returns [String] def to_s "\#<#{self.class} #{@thread.name}>" end + # Invoke {#terminate!} and then {#wait} for the child thread to exit. def close self.terminate! self.wait ensure super end + # Raise {Interrupt} in the child thread. def interrupt! @thread.raise(Interrupt) end + # Raise {Terminate} in the child thread. def terminate! @thread.raise(Terminate) end + # Wait for the thread to exit and return he exit status. + # @returns [Status] def wait if @waiter @waiter.join @waiter = nil end return @status end + # A pseudo exit-status wrapper. class Status - def initialize(result = nil) - @result = result + # Initialise the status. + # @parameter error [::Process::Status] The exit status of the child thread. + def initialize(error = nil) + @error = error end + # Whether the status represents a successful outcome. + # @returns [Boolean] def success? - @result.nil? + @error.nil? end + # A human readable representation of the status. def to_s "\#<#{self.class} #{success? ? "success" : "failure"}>" end end protected + # Invoked by the @waiter thread to indicate the outcome of the child thread. def finished(error = nil) if error Async.logger.error(self) {error} end