aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support/execution_wrapper.rb
diff options
context:
space:
mode:
authorMatthew Draper <matthew@trebex.net>2016-03-02 02:56:53 +1030
committerMatthew Draper <matthew@trebex.net>2016-03-02 02:56:53 +1030
commit541e4abb4b3710a384aefac83cafd0ab878c60bf (patch)
tree55603da9b6f9407a24c68e1d1fd53e109c4131e7 /activesupport/lib/active_support/execution_wrapper.rb
parentecdc0fbc872ea734adf29b3f9f3463b916235286 (diff)
parent60b53e9883bfd9f4edb640dbe2de89227b875e09 (diff)
downloadrails-541e4abb4b3710a384aefac83cafd0ab878c60bf.tar.gz
rails-541e4abb4b3710a384aefac83cafd0ab878c60bf.tar.bz2
rails-541e4abb4b3710a384aefac83cafd0ab878c60bf.zip
Merge pull request #23807 from matthewd/executor
Publish AS::Executor and AS::Reloader APIs
Diffstat (limited to 'activesupport/lib/active_support/execution_wrapper.rb')
-rw-r--r--activesupport/lib/active_support/execution_wrapper.rb69
1 files changed, 69 insertions, 0 deletions
diff --git a/activesupport/lib/active_support/execution_wrapper.rb b/activesupport/lib/active_support/execution_wrapper.rb
new file mode 100644
index 0000000000..e784556abf
--- /dev/null
+++ b/activesupport/lib/active_support/execution_wrapper.rb
@@ -0,0 +1,69 @@
+require 'active_support/callbacks'
+
+module ActiveSupport
+ class ExecutionWrapper
+ include ActiveSupport::Callbacks
+
+ define_callbacks :run
+ define_callbacks :complete
+
+ def self.to_run(*args, &block)
+ set_callback(:run, *args, &block)
+ end
+
+ def self.to_complete(*args, &block)
+ set_callback(:complete, *args, &block)
+ end
+
+ # Run this execution.
+ #
+ # Returns an instance, whose +complete!+ method *must* be invoked
+ # after the work has been performed.
+ #
+ # Where possible, prefer +wrap+.
+ def self.run!
+ new.tap(&:run!)
+ end
+
+ # Perform the work in the supplied block as an execution.
+ def self.wrap
+ return yield if active?
+
+ state = run!
+ begin
+ yield
+ ensure
+ state.complete!
+ end
+ end
+
+ class << self # :nodoc:
+ attr_accessor :active
+ end
+
+ def self.inherited(other) # :nodoc:
+ super
+ other.active = Concurrent::Hash.new(0)
+ end
+
+ self.active = Concurrent::Hash.new(0)
+
+ def self.active? # :nodoc:
+ @active[Thread.current] > 0
+ end
+
+ def run! # :nodoc:
+ self.class.active[Thread.current] += 1
+ run_callbacks(:run)
+ end
+
+ # Complete this in-flight execution. This method *must* be called
+ # exactly once on the result of any call to +run!+.
+ #
+ # Where possible, prefer +wrap+.
+ def complete!
+ run_callbacks(:complete)
+ self.class.active.delete Thread.current if (self.class.active[Thread.current] -= 1) == 0
+ end
+ end
+end