concurrent-ruby 1.1.5 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +84 -1
  3. data/Gemfile +5 -10
  4. data/{LICENSE.md → LICENSE.txt} +18 -20
  5. data/README.md +55 -31
  6. data/Rakefile +84 -92
  7. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +0 -0
  8. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +52 -22
  9. data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +10 -25
  10. data/lib/{concurrent → concurrent-ruby/concurrent}/agent.rb +2 -1
  11. data/lib/{concurrent → concurrent-ruby/concurrent}/array.rb +6 -16
  12. data/lib/{concurrent → concurrent-ruby/concurrent}/async.rb +10 -20
  13. data/lib/{concurrent → concurrent-ruby/concurrent}/atom.rb +2 -2
  14. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_boolean.rb +7 -6
  15. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_fixnum.rb +5 -4
  16. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_markable_reference.rb +3 -0
  17. data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +135 -0
  18. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/cyclic_barrier.rb +1 -1
  19. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/event.rb +3 -3
  20. data/lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb +109 -0
  21. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_count_down_latch.rb +1 -0
  22. data/lib/concurrent-ruby/concurrent/atomic/locals.rb +189 -0
  23. data/lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb +28 -0
  24. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_boolean.rb +11 -5
  25. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_fixnum.rb +11 -5
  26. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_count_down_latch.rb +1 -1
  27. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_semaphore.rb +19 -3
  28. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/read_write_lock.rb +2 -1
  29. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/reentrant_read_write_lock.rb +9 -9
  30. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/semaphore.rb +32 -14
  31. data/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb +111 -0
  32. data/lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb +37 -0
  33. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/mutex_atomic.rb +15 -4
  34. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_notify_observer_set.rb +1 -1
  35. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_write_observer_set.rb +1 -1
  36. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/lock_free_stack.rb +2 -0
  37. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/mri_map_backend.rb +3 -3
  38. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/non_concurrent_map_backend.rb +16 -8
  39. data/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb +14 -0
  40. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/ruby_non_concurrent_priority_queue.rb +11 -1
  41. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/dereferenceable.rb +2 -2
  42. data/lib/concurrent-ruby/concurrent/concern/logging.rb +116 -0
  43. data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
  44. data/lib/concurrent-ruby/concurrent/configuration.rb +105 -0
  45. data/lib/{concurrent → concurrent-ruby/concurrent}/delay.rb +2 -2
  46. data/lib/{concurrent → concurrent-ruby/concurrent}/errors.rb +5 -0
  47. data/lib/{concurrent → concurrent-ruby/concurrent}/exchanger.rb +1 -0
  48. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/abstract_executor_service.rb +34 -37
  49. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/cached_thread_pool.rb +4 -4
  50. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/executor_service.rb +2 -2
  51. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/fixed_thread_pool.rb +29 -15
  52. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_executor_service.rb +21 -9
  53. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_single_thread_executor.rb +4 -3
  54. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_thread_pool_executor.rb +19 -2
  55. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_executor_service.rb +10 -6
  56. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_single_thread_executor.rb +0 -1
  57. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_thread_pool_executor.rb +46 -42
  58. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/safe_task_executor.rb +6 -6
  59. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution.rb +1 -1
  60. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/simple_executor_service.rb +5 -2
  61. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/single_thread_executor.rb +1 -0
  62. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/thread_pool_executor.rb +2 -1
  63. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/timer_set.rb +0 -1
  64. data/lib/{concurrent → concurrent-ruby/concurrent}/hash.rb +1 -10
  65. data/lib/{concurrent → concurrent-ruby/concurrent}/immutable_struct.rb +10 -2
  66. data/lib/{concurrent → concurrent-ruby/concurrent}/ivar.rb +2 -1
  67. data/lib/{concurrent → concurrent-ruby/concurrent}/map.rb +44 -31
  68. data/lib/{concurrent → concurrent-ruby/concurrent}/maybe.rb +1 -1
  69. data/lib/{concurrent → concurrent-ruby/concurrent}/mutable_struct.rb +13 -3
  70. data/lib/{concurrent → concurrent-ruby/concurrent}/mvar.rb +1 -1
  71. data/lib/{concurrent → concurrent-ruby/concurrent}/promise.rb +2 -1
  72. data/lib/{concurrent → concurrent-ruby/concurrent}/promises.rb +7 -6
  73. data/lib/{concurrent → concurrent-ruby/concurrent}/re_include.rb +2 -0
  74. data/lib/{concurrent → concurrent-ruby/concurrent}/scheduled_task.rb +30 -17
  75. data/lib/{concurrent → concurrent-ruby/concurrent}/set.rb +17 -19
  76. data/lib/{concurrent → concurrent-ruby/concurrent}/settable_struct.rb +13 -3
  77. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_lockable_object.rb +5 -1
  78. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_object.rb +1 -3
  79. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_struct.rb +11 -0
  80. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/condition.rb +2 -0
  81. data/lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb +29 -0
  82. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_lockable_object.rb +3 -1
  83. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lock.rb +2 -0
  84. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lockable_object.rb +8 -7
  85. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mutex_lockable_object.rb +18 -5
  86. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/object.rb +12 -44
  87. data/lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb +36 -0
  88. data/lib/concurrent-ruby/concurrent/synchronization/volatile.rb +101 -0
  89. data/lib/concurrent-ruby/concurrent/synchronization.rb +13 -0
  90. data/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb +47 -0
  91. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/cheap_lockable.rb +2 -39
  92. data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +52 -0
  93. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/striped64.rb +1 -1
  94. data/lib/{concurrent → concurrent-ruby/concurrent}/timer_task.rb +11 -34
  95. data/lib/{concurrent → concurrent-ruby/concurrent}/tuple.rb +1 -5
  96. data/lib/{concurrent → concurrent-ruby/concurrent}/tvar.rb +21 -57
  97. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/engine.rb +5 -16
  98. data/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb +19 -0
  99. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_extension_loader.rb +8 -10
  100. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_integer.rb +1 -0
  101. data/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +110 -0
  102. data/lib/concurrent-ruby/concurrent/version.rb +3 -0
  103. data/lib/concurrent-ruby/concurrent-ruby.rb +5 -0
  104. metadata +127 -129
  105. data/lib/concurrent/atomic/abstract_thread_local_var.rb +0 -66
  106. data/lib/concurrent/atomic/atomic_reference.rb +0 -204
  107. data/lib/concurrent/atomic/java_thread_local_var.rb +0 -37
  108. data/lib/concurrent/atomic/ruby_thread_local_var.rb +0 -161
  109. data/lib/concurrent/atomic/thread_local_var.rb +0 -104
  110. data/lib/concurrent/concern/logging.rb +0 -32
  111. data/lib/concurrent/concurrent_ruby.jar +0 -0
  112. data/lib/concurrent/configuration.rb +0 -184
  113. data/lib/concurrent/synchronization/jruby_object.rb +0 -45
  114. data/lib/concurrent/synchronization/mri_object.rb +0 -44
  115. data/lib/concurrent/synchronization/rbx_lockable_object.rb +0 -65
  116. data/lib/concurrent/synchronization/rbx_object.rb +0 -49
  117. data/lib/concurrent/synchronization/truffleruby_object.rb +0 -47
  118. data/lib/concurrent/synchronization/volatile.rb +0 -36
  119. data/lib/concurrent/synchronization.rb +0 -30
  120. data/lib/concurrent/thread_safe/synchronized_delegator.rb +0 -50
  121. data/lib/concurrent/thread_safe/util/data_structures.rb +0 -63
  122. data/lib/concurrent/utility/at_exit.rb +0 -97
  123. data/lib/concurrent/utility/monotonic_time.rb +0 -58
  124. data/lib/concurrent/utility/processor_counter.rb +0 -158
  125. data/lib/concurrent/version.rb +0 -3
  126. data/lib/concurrent-ruby.rb +0 -1
  127. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/count_down_latch.rb +1 -1
  128. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/numeric_cas_wrapper.rb +0 -0
  129. data/lib/{concurrent → concurrent-ruby/concurrent}/atomics.rb +0 -0
  130. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/java_non_concurrent_priority_queue.rb +0 -0
  131. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/atomic_reference_map_backend.rb +0 -0
  132. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/synchronized_map_backend.rb +0 -0
  133. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/non_concurrent_priority_queue.rb +1 -1
  134. /data/lib/{concurrent → concurrent-ruby/concurrent}/concern/deprecation.rb +0 -0
  135. /data/lib/{concurrent → concurrent-ruby/concurrent}/concern/obligation.rb +0 -0
  136. /data/lib/{concurrent → concurrent-ruby/concurrent}/concern/observable.rb +0 -0
  137. /data/lib/{concurrent → concurrent-ruby/concurrent}/constants.rb +0 -0
  138. /data/lib/{concurrent → concurrent-ruby/concurrent}/dataflow.rb +0 -0
  139. /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/immediate_executor.rb +0 -0
  140. /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/indirect_immediate_executor.rb +0 -0
  141. /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serial_executor_service.rb +0 -0
  142. /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution_delegator.rb +0 -0
  143. /data/lib/{concurrent → concurrent-ruby/concurrent}/executors.rb +0 -0
  144. /data/lib/{concurrent → concurrent-ruby/concurrent}/future.rb +0 -0
  145. /data/lib/{concurrent → concurrent-ruby/concurrent}/options.rb +0 -0
  146. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/adder.rb +0 -0
  147. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/power_of_two_tuple.rb +0 -0
  148. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/volatile.rb +0 -0
  149. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/xor_shift_random.rb +0 -0
  150. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util.rb +0 -0
  151. /data/lib/{concurrent.rb → concurrent-ruby/concurrent.rb} +0 -0
@@ -1,161 +0,0 @@
1
- require 'thread'
2
- require 'concurrent/atomic/abstract_thread_local_var'
3
-
4
- module Concurrent
5
-
6
- # @!visibility private
7
- # @!macro internal_implementation_note
8
- class RubyThreadLocalVar < AbstractThreadLocalVar
9
-
10
- # Each thread has a (lazily initialized) array of thread-local variable values
11
- # Each time a new thread-local var is created, we allocate an "index" for it
12
- # For example, if the allocated index is 1, that means slot #1 in EVERY
13
- # thread's thread-local array will be used for the value of that TLV
14
- #
15
- # The good thing about using a per-THREAD structure to hold values, rather
16
- # than a per-TLV structure, is that no synchronization is needed when
17
- # reading and writing those values (since the structure is only ever
18
- # accessed by a single thread)
19
- #
20
- # Of course, when a TLV is GC'd, 1) we need to recover its index for use
21
- # by other new TLVs (otherwise the thread-local arrays could get bigger
22
- # and bigger with time), and 2) we need to null out all the references
23
- # held in the now-unused slots (both to avoid blocking GC of those objects,
24
- # and also to prevent "stale" values from being passed on to a new TLV
25
- # when the index is reused)
26
- # Because we need to null out freed slots, we need to keep references to
27
- # ALL the thread-local arrays -- ARRAYS is for that
28
- # But when a Thread is GC'd, we need to drop the reference to its thread-local
29
- # array, so we don't leak memory
30
-
31
- # @!visibility private
32
- FREE = []
33
- LOCK = Mutex.new
34
- ARRAYS = {} # used as a hash set
35
- @@next = 0
36
- private_constant :FREE, :LOCK, :ARRAYS
37
-
38
- # @!macro thread_local_var_method_get
39
- def value
40
- if array = get_threadlocal_array
41
- value = array[@index]
42
- if value.nil?
43
- default
44
- elsif value.equal?(NULL)
45
- nil
46
- else
47
- value
48
- end
49
- else
50
- default
51
- end
52
- end
53
-
54
- # @!macro thread_local_var_method_set
55
- def value=(value)
56
- me = Thread.current
57
- # We could keep the thread-local arrays in a hash, keyed by Thread
58
- # But why? That would require locking
59
- # Using Ruby's built-in thread-local storage is faster
60
- unless array = get_threadlocal_array(me)
61
- array = set_threadlocal_array([], me)
62
- LOCK.synchronize { ARRAYS[array.object_id] = array }
63
- ObjectSpace.define_finalizer(me, self.class.thread_finalizer(array))
64
- end
65
- array[@index] = (value.nil? ? NULL : value)
66
- value
67
- end
68
-
69
- protected
70
-
71
- # @!visibility private
72
- def allocate_storage
73
- @index = LOCK.synchronize do
74
- FREE.pop || begin
75
- result = @@next
76
- @@next += 1
77
- result
78
- end
79
- end
80
- ObjectSpace.define_finalizer(self, self.class.threadlocal_finalizer(@index))
81
- end
82
-
83
- # @!visibility private
84
- def self.threadlocal_finalizer(index)
85
- proc do
86
- Thread.new do # avoid error: can't be called from trap context
87
- LOCK.synchronize do
88
- FREE.push(index)
89
- # The cost of GC'ing a TLV is linear in the number of threads using TLVs
90
- # But that is natural! More threads means more storage is used per TLV
91
- # So naturally more CPU time is required to free more storage
92
- ARRAYS.each_value do |array|
93
- array[index] = nil
94
- end
95
- end
96
- end
97
- end
98
- end
99
-
100
- # @!visibility private
101
- def self.thread_finalizer(array)
102
- proc do
103
- Thread.new do # avoid error: can't be called from trap context
104
- LOCK.synchronize do
105
- # The thread which used this thread-local array is now gone
106
- # So don't hold onto a reference to the array (thus blocking GC)
107
- ARRAYS.delete(array.object_id)
108
- end
109
- end
110
- end
111
- end
112
-
113
- private
114
-
115
- if Thread.instance_methods.include?(:thread_variable_get)
116
-
117
- def get_threadlocal_array(thread = Thread.current)
118
- thread.thread_variable_get(:__threadlocal_array__)
119
- end
120
-
121
- def set_threadlocal_array(array, thread = Thread.current)
122
- thread.thread_variable_set(:__threadlocal_array__, array)
123
- end
124
-
125
- else
126
-
127
- def get_threadlocal_array(thread = Thread.current)
128
- thread[:__threadlocal_array__]
129
- end
130
-
131
- def set_threadlocal_array(array, thread = Thread.current)
132
- thread[:__threadlocal_array__] = array
133
- end
134
- end
135
-
136
- # This exists only for use in testing
137
- # @!visibility private
138
- def value_for(thread)
139
- if array = get_threadlocal_array(thread)
140
- value = array[@index]
141
- if value.nil?
142
- default_for(thread)
143
- elsif value.equal?(NULL)
144
- nil
145
- else
146
- value
147
- end
148
- else
149
- default_for(thread)
150
- end
151
- end
152
-
153
- def default_for(thread)
154
- if @default_block
155
- raise "Cannot use default_for with default block"
156
- else
157
- @default
158
- end
159
- end
160
- end
161
- end
@@ -1,104 +0,0 @@
1
- require 'concurrent/atomic/ruby_thread_local_var'
2
- require 'concurrent/atomic/java_thread_local_var'
3
- require 'concurrent/utility/engine'
4
-
5
- module Concurrent
6
-
7
- ###################################################################
8
-
9
- # @!macro thread_local_var_method_initialize
10
- #
11
- # Creates a thread local variable.
12
- #
13
- # @param [Object] default the default value when otherwise unset
14
- # @param [Proc] default_block Optional block that gets called to obtain the
15
- # default value for each thread
16
-
17
- # @!macro thread_local_var_method_get
18
- #
19
- # Returns the value in the current thread's copy of this thread-local variable.
20
- #
21
- # @return [Object] the current value
22
-
23
- # @!macro thread_local_var_method_set
24
- #
25
- # Sets the current thread's copy of this thread-local variable to the specified value.
26
- #
27
- # @param [Object] value the value to set
28
- # @return [Object] the new value
29
-
30
- # @!macro thread_local_var_method_bind
31
- #
32
- # Bind the given value to thread local storage during
33
- # execution of the given block.
34
- #
35
- # @param [Object] value the value to bind
36
- # @yield the operation to be performed with the bound variable
37
- # @return [Object] the value
38
-
39
-
40
- ###################################################################
41
-
42
- # @!macro thread_local_var_public_api
43
- #
44
- # @!method initialize(default = nil, &default_block)
45
- # @!macro thread_local_var_method_initialize
46
- #
47
- # @!method value
48
- # @!macro thread_local_var_method_get
49
- #
50
- # @!method value=(value)
51
- # @!macro thread_local_var_method_set
52
- #
53
- # @!method bind(value, &block)
54
- # @!macro thread_local_var_method_bind
55
-
56
- ###################################################################
57
-
58
- # @!visibility private
59
- # @!macro internal_implementation_note
60
- ThreadLocalVarImplementation = case
61
- when Concurrent.on_jruby?
62
- JavaThreadLocalVar
63
- else
64
- RubyThreadLocalVar
65
- end
66
- private_constant :ThreadLocalVarImplementation
67
-
68
- # @!macro thread_local_var
69
- #
70
- # A `ThreadLocalVar` is a variable where the value is different for each thread.
71
- # Each variable may have a default value, but when you modify the variable only
72
- # the current thread will ever see that change.
73
- #
74
- # @!macro thread_safe_variable_comparison
75
- #
76
- # @example
77
- # v = ThreadLocalVar.new(14)
78
- # v.value #=> 14
79
- # v.value = 2
80
- # v.value #=> 2
81
- #
82
- # @example
83
- # v = ThreadLocalVar.new(14)
84
- #
85
- # t1 = Thread.new do
86
- # v.value #=> 14
87
- # v.value = 1
88
- # v.value #=> 1
89
- # end
90
- #
91
- # t2 = Thread.new do
92
- # v.value #=> 14
93
- # v.value = 2
94
- # v.value #=> 2
95
- # end
96
- #
97
- # v.value #=> 14
98
- #
99
- # @see https://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html Java ThreadLocal
100
- #
101
- # @!macro thread_local_var_public_api
102
- class ThreadLocalVar < ThreadLocalVarImplementation
103
- end
104
- end
@@ -1,32 +0,0 @@
1
- require 'logger'
2
-
3
- module Concurrent
4
- module Concern
5
-
6
- # Include where logging is needed
7
- #
8
- # @!visibility private
9
- module Logging
10
- include Logger::Severity
11
-
12
- # Logs through {Concurrent.global_logger}, it can be overridden by setting @logger
13
- # @param [Integer] level one of Logger::Severity constants
14
- # @param [String] progname e.g. a path of an Actor
15
- # @param [String, nil] message when nil block is used to generate the message
16
- # @yieldreturn [String] a message
17
- def log(level, progname, message = nil, &block)
18
- #NOTE: Cannot require 'concurrent/configuration' above due to circular references.
19
- # Assume that the gem has been initialized if we've gotten this far.
20
- logger = if defined?(@logger) && @logger
21
- @logger
22
- else
23
- Concurrent.global_logger
24
- end
25
- logger.call level, progname, message, &block
26
- rescue => error
27
- $stderr.puts "`Concurrent.configuration.logger` failed to log #{[level, progname, message, block]}\n" +
28
- "#{error.message} (#{error.class})\n#{error.backtrace.join "\n"}"
29
- end
30
- end
31
- end
32
- end
Binary file
@@ -1,184 +0,0 @@
1
- require 'thread'
2
- require 'concurrent/delay'
3
- require 'concurrent/errors'
4
- require 'concurrent/atomic/atomic_reference'
5
- require 'concurrent/concern/logging'
6
- require 'concurrent/executor/immediate_executor'
7
- require 'concurrent/executor/cached_thread_pool'
8
- require 'concurrent/utility/at_exit'
9
- require 'concurrent/utility/processor_counter'
10
-
11
- module Concurrent
12
- extend Concern::Logging
13
-
14
- autoload :Options, 'concurrent/options'
15
- autoload :TimerSet, 'concurrent/executor/timer_set'
16
- autoload :ThreadPoolExecutor, 'concurrent/executor/thread_pool_executor'
17
-
18
- # @return [Logger] Logger with provided level and output.
19
- def self.create_simple_logger(level = Logger::FATAL, output = $stderr)
20
- # TODO (pitr-ch 24-Dec-2016): figure out why it had to be replaced, stdlogger was deadlocking
21
- lambda do |severity, progname, message = nil, &block|
22
- return false if severity < level
23
-
24
- message = block ? block.call : message
25
- formatted_message = case message
26
- when String
27
- message
28
- when Exception
29
- format "%s (%s)\n%s",
30
- message.message, message.class, (message.backtrace || []).join("\n")
31
- else
32
- message.inspect
33
- end
34
-
35
- output.print format "[%s] %5s -- %s: %s\n",
36
- Time.now.strftime('%Y-%m-%d %H:%M:%S.%L'),
37
- Logger::SEV_LABEL[severity],
38
- progname,
39
- formatted_message
40
- true
41
- end
42
- end
43
-
44
- # Use logger created by #create_simple_logger to log concurrent-ruby messages.
45
- def self.use_simple_logger(level = Logger::FATAL, output = $stderr)
46
- Concurrent.global_logger = create_simple_logger level, output
47
- end
48
-
49
- # @return [Logger] Logger with provided level and output.
50
- # @deprecated
51
- def self.create_stdlib_logger(level = Logger::FATAL, output = $stderr)
52
- logger = Logger.new(output)
53
- logger.level = level
54
- logger.formatter = lambda do |severity, datetime, progname, msg|
55
- formatted_message = case msg
56
- when String
57
- msg
58
- when Exception
59
- format "%s (%s)\n%s",
60
- msg.message, msg.class, (msg.backtrace || []).join("\n")
61
- else
62
- msg.inspect
63
- end
64
- format "[%s] %5s -- %s: %s\n",
65
- datetime.strftime('%Y-%m-%d %H:%M:%S.%L'),
66
- severity,
67
- progname,
68
- formatted_message
69
- end
70
-
71
- lambda do |loglevel, progname, message = nil, &block|
72
- logger.add loglevel, message, progname, &block
73
- end
74
- end
75
-
76
- # Use logger created by #create_stdlib_logger to log concurrent-ruby messages.
77
- # @deprecated
78
- def self.use_stdlib_logger(level = Logger::FATAL, output = $stderr)
79
- Concurrent.global_logger = create_stdlib_logger level, output
80
- end
81
-
82
- # TODO (pitr-ch 27-Dec-2016): remove deadlocking stdlib_logger methods
83
-
84
- # Suppresses all output when used for logging.
85
- NULL_LOGGER = lambda { |level, progname, message = nil, &block| }
86
-
87
- # @!visibility private
88
- GLOBAL_LOGGER = AtomicReference.new(create_simple_logger(Logger::WARN))
89
- private_constant :GLOBAL_LOGGER
90
-
91
- def self.global_logger
92
- GLOBAL_LOGGER.value
93
- end
94
-
95
- def self.global_logger=(value)
96
- GLOBAL_LOGGER.value = value
97
- end
98
-
99
- # @!visibility private
100
- GLOBAL_FAST_EXECUTOR = Delay.new { Concurrent.new_fast_executor(auto_terminate: true) }
101
- private_constant :GLOBAL_FAST_EXECUTOR
102
-
103
- # @!visibility private
104
- GLOBAL_IO_EXECUTOR = Delay.new { Concurrent.new_io_executor(auto_terminate: true) }
105
- private_constant :GLOBAL_IO_EXECUTOR
106
-
107
- # @!visibility private
108
- GLOBAL_TIMER_SET = Delay.new { TimerSet.new(auto_terminate: true) }
109
- private_constant :GLOBAL_TIMER_SET
110
-
111
- # @!visibility private
112
- GLOBAL_IMMEDIATE_EXECUTOR = ImmediateExecutor.new
113
- private_constant :GLOBAL_IMMEDIATE_EXECUTOR
114
-
115
- # Disables AtExit handlers including pool auto-termination handlers.
116
- # When disabled it will be the application programmer's responsibility
117
- # to ensure that the handlers are shutdown properly prior to application
118
- # exit by calling {AtExit.run} method.
119
- #
120
- # @note this option should be needed only because of `at_exit` ordering
121
- # issues which may arise when running some of the testing frameworks.
122
- # E.g. Minitest's test-suite runs itself in `at_exit` callback which
123
- # executes after the pools are already terminated. Then auto termination
124
- # needs to be disabled and called manually after test-suite ends.
125
- # @note This method should *never* be called
126
- # from within a gem. It should *only* be used from within the main
127
- # application and even then it should be used only when necessary.
128
- # @see AtExit
129
- def self.disable_at_exit_handlers!
130
- AtExit.enabled = false
131
- end
132
-
133
- # Global thread pool optimized for short, fast *operations*.
134
- #
135
- # @return [ThreadPoolExecutor] the thread pool
136
- def self.global_fast_executor
137
- GLOBAL_FAST_EXECUTOR.value
138
- end
139
-
140
- # Global thread pool optimized for long, blocking (IO) *tasks*.
141
- #
142
- # @return [ThreadPoolExecutor] the thread pool
143
- def self.global_io_executor
144
- GLOBAL_IO_EXECUTOR.value
145
- end
146
-
147
- def self.global_immediate_executor
148
- GLOBAL_IMMEDIATE_EXECUTOR
149
- end
150
-
151
- # Global thread pool user for global *timers*.
152
- #
153
- # @return [Concurrent::TimerSet] the thread pool
154
- def self.global_timer_set
155
- GLOBAL_TIMER_SET.value
156
- end
157
-
158
- # General access point to global executors.
159
- # @param [Symbol, Executor] executor_identifier symbols:
160
- # - :fast - {Concurrent.global_fast_executor}
161
- # - :io - {Concurrent.global_io_executor}
162
- # - :immediate - {Concurrent.global_immediate_executor}
163
- # @return [Executor]
164
- def self.executor(executor_identifier)
165
- Options.executor(executor_identifier)
166
- end
167
-
168
- def self.new_fast_executor(opts = {})
169
- FixedThreadPool.new(
170
- [2, Concurrent.processor_count].max,
171
- auto_terminate: opts.fetch(:auto_terminate, true),
172
- idletime: 60, # 1 minute
173
- max_queue: 0, # unlimited
174
- fallback_policy: :abort # shouldn't matter -- 0 max queue
175
- )
176
- end
177
-
178
- def self.new_io_executor(opts = {})
179
- CachedThreadPool.new(
180
- auto_terminate: opts.fetch(:auto_terminate, true),
181
- fallback_policy: :abort # shouldn't matter -- 0 max queue
182
- )
183
- end
184
- end
@@ -1,45 +0,0 @@
1
- module Concurrent
2
- module Synchronization
3
-
4
- if Concurrent.on_jruby? && Concurrent.java_extensions_loaded?
5
-
6
- # @!visibility private
7
- module JRubyAttrVolatile
8
- def self.included(base)
9
- base.extend(ClassMethods)
10
- end
11
-
12
- module ClassMethods
13
- def attr_volatile(*names)
14
- names.each do |name|
15
-
16
- ivar = :"@volatile_#{name}"
17
-
18
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
19
- def #{name}
20
- instance_variable_get_volatile(:#{ivar})
21
- end
22
-
23
- def #{name}=(value)
24
- instance_variable_set_volatile(:#{ivar}, value)
25
- end
26
- RUBY
27
-
28
- end
29
- names.map { |n| [n, :"#{n}="] }.flatten
30
- end
31
- end
32
- end
33
-
34
- # @!visibility private
35
- # @!macro internal_implementation_note
36
- class JRubyObject < AbstractObject
37
- include JRubyAttrVolatile
38
-
39
- def initialize
40
- # nothing to do
41
- end
42
- end
43
- end
44
- end
45
- end
@@ -1,44 +0,0 @@
1
- module Concurrent
2
- module Synchronization
3
-
4
- # @!visibility private
5
- module MriAttrVolatile
6
- def self.included(base)
7
- base.extend(ClassMethods)
8
- end
9
-
10
- module ClassMethods
11
- def attr_volatile(*names)
12
- names.each do |name|
13
- ivar = :"@volatile_#{name}"
14
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
15
- def #{name}
16
- #{ivar}
17
- end
18
-
19
- def #{name}=(value)
20
- #{ivar} = value
21
- end
22
- RUBY
23
- end
24
- names.map { |n| [n, :"#{n}="] }.flatten
25
- end
26
- end
27
-
28
- def full_memory_barrier
29
- # relying on undocumented behavior of CRuby, GVL acquire has lock which ensures visibility of ivars
30
- # https://github.com/ruby/ruby/blob/ruby_2_2/thread_pthread.c#L204-L211
31
- end
32
- end
33
-
34
- # @!visibility private
35
- # @!macro internal_implementation_note
36
- class MriObject < AbstractObject
37
- include MriAttrVolatile
38
-
39
- def initialize
40
- # nothing to do
41
- end
42
- end
43
- end
44
- end
@@ -1,65 +0,0 @@
1
- module Concurrent
2
- module Synchronization
3
-
4
- # @!visibility private
5
- # @!macro internal_implementation_note
6
- class RbxLockableObject < AbstractLockableObject
7
- safe_initialization!
8
-
9
- def initialize(*defaults)
10
- super(*defaults)
11
- @__Waiters__ = []
12
- @__owner__ = nil
13
- end
14
-
15
- protected
16
-
17
- def synchronize(&block)
18
- if @__owner__ == Thread.current
19
- yield
20
- else
21
- result = nil
22
- Rubinius.synchronize(self) do
23
- begin
24
- @__owner__ = Thread.current
25
- result = yield
26
- ensure
27
- @__owner__ = nil
28
- end
29
- end
30
- result
31
- end
32
- end
33
-
34
- def ns_wait(timeout = nil)
35
- wchan = Rubinius::Channel.new
36
-
37
- begin
38
- @__Waiters__.push wchan
39
- Rubinius.unlock(self)
40
- signaled = wchan.receive_timeout timeout
41
- ensure
42
- Rubinius.lock(self)
43
-
44
- if !signaled && !@__Waiters__.delete(wchan)
45
- # we timed out, but got signaled afterwards,
46
- # so pass that signal on to the next waiter
47
- @__Waiters__.shift << true unless @__Waiters__.empty?
48
- end
49
- end
50
-
51
- self
52
- end
53
-
54
- def ns_signal
55
- @__Waiters__.shift << true unless @__Waiters__.empty?
56
- self
57
- end
58
-
59
- def ns_broadcast
60
- @__Waiters__.shift << true until @__Waiters__.empty?
61
- self
62
- end
63
- end
64
- end
65
- end
@@ -1,49 +0,0 @@
1
- module Concurrent
2
- module Synchronization
3
-
4
- # @!visibility private
5
- module RbxAttrVolatile
6
- def self.included(base)
7
- base.extend(ClassMethods)
8
- end
9
-
10
- module ClassMethods
11
-
12
- def attr_volatile(*names)
13
- names.each do |name|
14
- ivar = :"@volatile_#{name}"
15
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
16
- def #{name}
17
- Rubinius.memory_barrier
18
- #{ivar}
19
- end
20
-
21
- def #{name}=(value)
22
- #{ivar} = value
23
- Rubinius.memory_barrier
24
- end
25
- RUBY
26
- end
27
- names.map { |n| [n, :"#{n}="] }.flatten
28
- end
29
-
30
- end
31
-
32
- def full_memory_barrier
33
- # Rubinius instance variables are not volatile so we need to insert barrier
34
- # TODO (pitr 26-Nov-2015): check comments like ^
35
- Rubinius.memory_barrier
36
- end
37
- end
38
-
39
- # @!visibility private
40
- # @!macro internal_implementation_note
41
- class RbxObject < AbstractObject
42
- include RbxAttrVolatile
43
-
44
- def initialize
45
- # nothing to do
46
- end
47
- end
48
- end
49
- end