summaryrefslogtreecommitdiff
path: root/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/lib/em/deferrable.rb
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/lib/em/deferrable.rb')
-rw-r--r--vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/lib/em/deferrable.rb210
1 files changed, 210 insertions, 0 deletions
diff --git a/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/lib/em/deferrable.rb b/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/lib/em/deferrable.rb
new file mode 100644
index 0000000..18a6d31
--- /dev/null
+++ b/vendor/bundle/ruby/3.4.0/gems/eventmachine-1.2.7/lib/em/deferrable.rb
@@ -0,0 +1,210 @@
+#--
+#
+# Author:: Francis Cianfrocca (gmail: blackhedd)
+# Homepage:: http://rubyeventmachine.com
+# Date:: 16 Jul 2006
+#
+# See EventMachine and EventMachine::Connection for documentation and
+# usage examples.
+#
+#----------------------------------------------------------------------------
+#
+# Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
+# Gmail: blackhedd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of either: 1) the GNU General Public License
+# as published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version; or 2) Ruby's License.
+#
+# See the file COPYING for complete licensing information.
+#
+#---------------------------------------------------------------------------
+#
+#
+
+module EventMachine
+ module Deferrable
+ autoload :Pool, 'em/deferrable/pool'
+
+ # Specify a block to be executed if and when the Deferrable object receives
+ # a status of :succeeded. See #set_deferred_status for more information.
+ #
+ # Calling this method on a Deferrable object whose status is not yet known
+ # will cause the callback block to be stored on an internal list.
+ # If you call this method on a Deferrable whose status is :succeeded, the
+ # block will be executed immediately, receiving the parameters given to the
+ # prior #set_deferred_status call.
+ #
+ #--
+ # If there is no status, add a callback to an internal list.
+ # If status is succeeded, execute the callback immediately.
+ # If status is failed, do nothing.
+ #
+ def callback &block
+ return unless block
+ @deferred_status ||= :unknown
+ if @deferred_status == :succeeded
+ block.call(*@deferred_args)
+ elsif @deferred_status != :failed
+ @callbacks ||= []
+ @callbacks.unshift block # << block
+ end
+ self
+ end
+
+ # Cancels an outstanding callback to &block if any. Undoes the action of #callback.
+ #
+ def cancel_callback block
+ @callbacks ||= []
+ @callbacks.delete block
+ end
+
+ # Specify a block to be executed if and when the Deferrable object receives
+ # a status of :failed. See #set_deferred_status for more information.
+ #--
+ # If there is no status, add an errback to an internal list.
+ # If status is failed, execute the errback immediately.
+ # If status is succeeded, do nothing.
+ #
+ def errback &block
+ return unless block
+ @deferred_status ||= :unknown
+ if @deferred_status == :failed
+ block.call(*@deferred_args)
+ elsif @deferred_status != :succeeded
+ @errbacks ||= []
+ @errbacks.unshift block # << block
+ end
+ self
+ end
+
+ # Cancels an outstanding errback to &block if any. Undoes the action of #errback.
+ #
+ def cancel_errback block
+ @errbacks ||= []
+ @errbacks.delete block
+ end
+
+ # Sets the "disposition" (status) of the Deferrable object. See also the large set of
+ # sugarings for this method.
+ # Note that if you call this method without arguments,
+ # no arguments will be passed to the callback/errback.
+ # If the user has coded these with arguments, then the
+ # user code will throw an argument exception.
+ # Implementors of deferrable classes <b>must</b>
+ # document the arguments they will supply to user callbacks.
+ #
+ # OBSERVE SOMETHING VERY SPECIAL here: you may call this method even
+ # on the INSIDE of a callback. This is very useful when a previously-registered
+ # callback wants to change the parameters that will be passed to subsequently-registered
+ # ones.
+ #
+ # You may give either :succeeded or :failed as the status argument.
+ #
+ # If you pass :succeeded, then all of the blocks passed to the object using the #callback
+ # method (if any) will be executed BEFORE the #set_deferred_status method returns. All of the blocks
+ # passed to the object using #errback will be discarded.
+ #
+ # If you pass :failed, then all of the blocks passed to the object using the #errback
+ # method (if any) will be executed BEFORE the #set_deferred_status method returns. All of the blocks
+ # passed to the object using # callback will be discarded.
+ #
+ # If you pass any arguments to #set_deferred_status in addition to the status argument,
+ # they will be passed as arguments to any callbacks or errbacks that are executed.
+ # It's your responsibility to ensure that the argument lists specified in your callbacks and
+ # errbacks match the arguments given in calls to #set_deferred_status, otherwise Ruby will raise
+ # an ArgumentError.
+ #
+ #--
+ # We're shifting callbacks off and discarding them as we execute them.
+ # This is valid because by definition callbacks are executed no more than
+ # once. It also has the magic effect of permitting recursive calls, which
+ # means that a callback can call #set_deferred_status and change the parameters
+ # that will be sent to subsequent callbacks down the chain.
+ #
+ # Changed @callbacks and @errbacks from push/shift to unshift/pop, per suggestion
+ # by Kirk Haines, to work around the memory leak bug that still exists in many Ruby
+ # versions.
+ #
+ # Changed 15Sep07: after processing callbacks or errbacks, CLEAR the other set of
+ # handlers. This gets us a little closer to the behavior of Twisted's "deferred,"
+ # which only allows status to be set once. Prior to making this change, it was possible
+ # to "succeed" a Deferrable (triggering its callbacks), and then immediately "fail" it,
+ # triggering its errbacks! That is clearly undesirable, but it's just as undesirable
+ # to raise an exception is status is set more than once on a Deferrable. The latter
+ # behavior would invalidate the idiom of resetting arguments by setting status from
+ # within a callback or errback, but more seriously it would cause spurious errors
+ # if a Deferrable was timed out and then an attempt was made to succeed it. See the
+ # comments under the new method #timeout.
+ #
+ def set_deferred_status status, *args
+ cancel_timeout
+ @errbacks ||= nil
+ @callbacks ||= nil
+ @deferred_status = status
+ @deferred_args = args
+ case @deferred_status
+ when :succeeded
+ if @callbacks
+ while cb = @callbacks.pop
+ cb.call(*@deferred_args)
+ end
+ end
+ @errbacks.clear if @errbacks
+ when :failed
+ if @errbacks
+ while eb = @errbacks.pop
+ eb.call(*@deferred_args)
+ end
+ end
+ @callbacks.clear if @callbacks
+ end
+ end
+
+
+ # Setting a timeout on a Deferrable causes it to go into the failed state after
+ # the Timeout expires (passing no arguments to the object's errbacks).
+ # Setting the status at any time prior to a call to the expiration of the timeout
+ # will cause the timer to be cancelled.
+ def timeout seconds, *args
+ cancel_timeout
+ me = self
+ @deferred_timeout = EventMachine::Timer.new(seconds) {me.fail(*args)}
+ self
+ end
+
+ # Cancels an outstanding timeout if any. Undoes the action of #timeout.
+ #
+ def cancel_timeout
+ @deferred_timeout ||= nil
+ if @deferred_timeout
+ @deferred_timeout.cancel
+ @deferred_timeout = nil
+ end
+ end
+
+
+ # Sugar for set_deferred_status(:succeeded, ...)
+ #
+ def succeed *args
+ set_deferred_status :succeeded, *args
+ end
+ alias set_deferred_success succeed
+
+ # Sugar for set_deferred_status(:failed, ...)
+ #
+ def fail *args
+ set_deferred_status :failed, *args
+ end
+ alias set_deferred_failure fail
+ end
+
+
+ # DefaultDeferrable is an otherwise empty class that includes Deferrable.
+ # This is very useful when you just need to return a Deferrable object
+ # as a way of communicating deferred status to some other part of a program.
+ class DefaultDeferrable
+ include Deferrable
+ end
+end \ No newline at end of file