11require 'thread'
2+ require 'concurrent/delay'
23require 'concurrent/executor/thread_pool_executor'
34require 'concurrent/executor/timer_set'
45require 'concurrent/utility/processor_count'
@@ -8,57 +9,28 @@ module Concurrent
89 # An error class to be raised when errors occur during configuration.
910 ConfigurationError = Class . new ( StandardError )
1011
11- class << self
12- attr_accessor :configuration
13- end
14-
15- # Perform gem-level configuration.
16- #
17- # @yield the configuration commands
18- # @yieldparam [Configuration] the current configuration object
19- def self . configure
20- ( @mutex ||= Mutex . new ) . synchronize do
21- yield ( configuration )
22-
23- # initialize the global thread pools if necessary
24- configuration . global_task_pool
25- configuration . global_operation_pool
26- configuration . global_timer_set
27- end
28- end
29-
3012 # A gem-level configuration object.
3113 class Configuration
3214
3315 # Create a new configuration object.
3416 def initialize
35- @cores ||= Concurrent ::processor_count
17+ @global_task_pool = Delay . new { new_task_pool }
18+ @global_operation_pool = Delay . new { new_operation_pool }
19+ @global_timer_set = Delay . new { Concurrent ::TimerSet . new }
3620 end
3721
3822 # Global thread pool optimized for short *tasks*.
3923 #
4024 # @return [ThreadPoolExecutor] the thread pool
4125 def global_task_pool
42- @global_task_pool ||= Concurrent ::ThreadPoolExecutor . new (
43- min_threads : [ 2 , @cores ] . max ,
44- max_threads : [ 20 , @cores * 15 ] . max ,
45- idletime : 2 * 60 , # 2 minutes
46- max_queue : 0 , # unlimited
47- overflow_policy : :abort # raise an exception
48- )
26+ @global_task_pool . value
4927 end
5028
5129 # Global thread pool optimized for long *operations*.
5230 #
5331 # @return [ThreadPoolExecutor] the thread pool
5432 def global_operation_pool
55- @global_operation_pool ||= Concurrent ::ThreadPoolExecutor . new (
56- min_threads : [ 2 , @cores ] . max ,
57- max_threads : [ 2 , @cores ] . max ,
58- idletime : 10 * 60 , # 10 minutes
59- max_queue : [ 20 , @cores * 15 ] . max ,
60- overflow_policy : :abort # raise an exception
61- )
33+ @global_operation_pool . value
6234 end
6335
6436 # Global thread pool optimized for *timers*
@@ -67,7 +39,7 @@ def global_operation_pool
6739 #
6840 # @see Concurrent::timer
6941 def global_timer_set
70- @global_timer_set ||= Concurrent :: TimerSet . new
42+ @global_timer_set . value
7143 end
7244
7345 # Global thread pool optimized for short *tasks*.
@@ -85,8 +57,8 @@ def global_timer_set
8557 #
8658 # @raise [ConfigurationError] if this thread pool has already been set
8759 def global_task_pool = ( executor )
88- raise ConfigurationError . new ( 'global task pool was already set' ) unless @global_task_pool . nil?
89- @global_task_pool = executor
60+ @global_task_pool . reconfigure { executor } or
61+ raise ConfigurationError . new ( 'global task pool was already set' )
9062 end
9163
9264 # Global thread pool optimized for long *operations*.
@@ -104,9 +76,41 @@ def global_task_pool=(executor)
10476 #
10577 # @raise [ConfigurationError] if this thread pool has already been set
10678 def global_operation_pool = ( executor )
107- raise ConfigurationError . new ( 'global operation pool was already set' ) unless @global_operation_pool . nil?
108- @global_operation_pool = executor
79+ @global_operation_pool . reconfigure { executor } or
80+ raise ConfigurationError . new ( 'global operation pool was already set' )
10981 end
82+
83+ def new_task_pool
84+ Concurrent ::ThreadPoolExecutor . new (
85+ min_threads : [ 2 , Concurrent . processor_count ] . max ,
86+ max_threads : [ 20 , Concurrent . processor_count * 15 ] . max ,
87+ idletime : 2 * 60 , # 2 minutes
88+ max_queue : 0 , # unlimited
89+ overflow_policy : :abort # raise an exception
90+ )
91+ end
92+
93+ def new_operation_pool
94+ Concurrent ::ThreadPoolExecutor . new (
95+ min_threads : [ 2 , Concurrent . processor_count ] . max ,
96+ max_threads : [ 2 , Concurrent . processor_count ] . max ,
97+ idletime : 10 * 60 , # 10 minutes
98+ max_queue : [ 20 , Concurrent . processor_count * 15 ] . max ,
99+ overflow_policy : :abort # raise an exception
100+ )
101+ end
102+ end
103+
104+ # create the default configuration on load
105+ @configuration = Configuration . new
106+ singleton_class . send :attr_reader , :configuration
107+
108+ # Perform gem-level configuration.
109+ #
110+ # @yield the configuration commands
111+ # @yieldparam [Configuration] the current configuration object
112+ def self . configure
113+ yield ( configuration )
110114 end
111115
112116 private
@@ -129,8 +133,6 @@ def self.finalize_executor(executor)
129133 false
130134 end
131135
132- # create the default configuration on load
133- self . configuration = Configuration . new
134136
135137 # set exit hook to shutdown global thread pools
136138 at_exit do
0 commit comments