Skip to content

Commit 4ad4619

Browse files
committed
Fix configuration to be thread safe
by replacing ||= operator with Delay instances
1 parent 360c774 commit 4ad4619

File tree

1 file changed

+31
-20
lines changed

1 file changed

+31
-20
lines changed

lib/concurrent/configuration.rb

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
require 'thread'
2+
require 'concurrent/delay'
23
require 'concurrent/executor/thread_pool_executor'
34
require 'concurrent/executor/timer_set'
45
require 'concurrent/utility/processor_count'
@@ -32,33 +33,43 @@ class Configuration
3233

3334
# Create a new configuration object.
3435
def initialize
35-
@cores ||= Concurrent::processor_count
36+
@cores = Concurrent::processor_count
37+
38+
@global_task_pool = Delay.new do
39+
Concurrent::ThreadPoolExecutor.new(
40+
min_threads: [2, @cores].max,
41+
max_threads: [20, @cores * 15].max,
42+
idletime: 2 * 60, # 2 minutes
43+
max_queue: 0, # unlimited
44+
overflow_policy: :abort # raise an exception
45+
)
46+
end
47+
48+
@global_operation_pool = Delay.new do
49+
Concurrent::ThreadPoolExecutor.new(
50+
min_threads: [2, @cores].max,
51+
max_threads: [2, @cores].max,
52+
idletime: 10 * 60, # 10 minutes
53+
max_queue: [20, @cores * 15].max,
54+
overflow_policy: :abort # raise an exception
55+
)
56+
end
57+
58+
@global_timer_set = Delay.new { Concurrent::TimerSet.new }
3659
end
3760

3861
# Global thread pool optimized for short *tasks*.
3962
#
4063
# @return [ThreadPoolExecutor] the thread pool
4164
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-
)
65+
@global_task_pool.value
4966
end
5067

5168
# Global thread pool optimized for long *operations*.
5269
#
5370
# @return [ThreadPoolExecutor] the thread pool
5471
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-
)
72+
@global_operation_pool.value
6273
end
6374

6475
# Global thread pool optimized for *timers*
@@ -67,7 +78,7 @@ def global_operation_pool
6778
#
6879
# @see Concurrent::timer
6980
def global_timer_set
70-
@global_timer_set ||= Concurrent::TimerSet.new
81+
@global_timer_set.value
7182
end
7283

7384
# Global thread pool optimized for short *tasks*.
@@ -85,8 +96,8 @@ def global_timer_set
8596
#
8697
# @raise [ConfigurationError] if this thread pool has already been set
8798
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
99+
@global_task_pool.reconfigure { executor } or
100+
raise ConfigurationError.new('global task pool was already set')
90101
end
91102

92103
# Global thread pool optimized for long *operations*.
@@ -104,8 +115,8 @@ def global_task_pool=(executor)
104115
#
105116
# @raise [ConfigurationError] if this thread pool has already been set
106117
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
118+
@global_operation_pool.reconfigure { executor } or
119+
raise ConfigurationError.new('global operation pool was already set')
109120
end
110121
end
111122

0 commit comments

Comments
 (0)