Thread Completion

What? Registering for a notification upon thread completion, either at end of block or thread being terminated.

Why? To perform any clean-up of resources used and bound to the thread, e.g. open connections maintained by the Thread.

require 'set'

class Thread

    @@override = {
        :initialize => instance_method(:initialize),
        :exit => instance_method(:exit)
    }

    @@on_completion = Set.new

    def initialize *args, &block
        @@override[:initialize].bind(self).call *args do
            instance_eval *args, &block
            on_completion true
        end
    end

    def exit
        @@override[:exit].bind(self).call
        on_completion false
    end

    def on_completion_add listener
        @@on_completion.add listener
        nil
    end

    def on_completion_remove listener
        @@on_completion.delete listener
        nil
    end

protected
    def on_completion successful
        @@on_completion.each do |listener|
            begin
                if listener.respond_to?(:on_completion)
                    listener.on_completion self, successful
                else
                    listener.call self, successful
                end
            rescue Exception=>error
                # Log the error?
            end
        end
    end

end

You can also use ObjectSpace.define_finalizer to wait for the thread to be garbage collected. The downside is that garbage collection occurs after completion, and there are cases where the application may hold on to a thread long after it's done processing.