1
1
require 'thread'
2
+ require 'concurrent/delay'
2
3
require 'concurrent/executor/thread_pool_executor'
3
4
require 'concurrent/executor/timer_set'
4
5
require 'concurrent/utility/processor_count'
@@ -8,57 +9,28 @@ module Concurrent
8
9
# An error class to be raised when errors occur during configuration.
9
10
ConfigurationError = Class . new ( StandardError )
10
11
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
-
30
12
# A gem-level configuration object.
31
13
class Configuration
32
14
33
15
# Create a new configuration object.
34
16
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 }
36
20
end
37
21
38
22
# Global thread pool optimized for short *tasks*.
39
23
#
40
24
# @return [ThreadPoolExecutor] the thread pool
41
25
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
49
27
end
50
28
51
29
# Global thread pool optimized for long *operations*.
52
30
#
53
31
# @return [ThreadPoolExecutor] the thread pool
54
32
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
62
34
end
63
35
64
36
# Global thread pool optimized for *timers*
@@ -67,7 +39,7 @@ def global_operation_pool
67
39
#
68
40
# @see Concurrent::timer
69
41
def global_timer_set
70
- @global_timer_set ||= Concurrent :: TimerSet . new
42
+ @global_timer_set . value
71
43
end
72
44
73
45
# Global thread pool optimized for short *tasks*.
@@ -85,8 +57,8 @@ def global_timer_set
85
57
#
86
58
# @raise [ConfigurationError] if this thread pool has already been set
87
59
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' )
90
62
end
91
63
92
64
# Global thread pool optimized for long *operations*.
@@ -104,9 +76,41 @@ def global_task_pool=(executor)
104
76
#
105
77
# @raise [ConfigurationError] if this thread pool has already been set
106
78
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' )
109
81
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 )
110
114
end
111
115
112
116
private
@@ -129,8 +133,6 @@ def self.finalize_executor(executor)
129
133
false
130
134
end
131
135
132
- # create the default configuration on load
133
- self . configuration = Configuration . new
134
136
135
137
# set exit hook to shutdown global thread pools
136
138
at_exit do
0 commit comments