concurrent-ruby 1.1.5 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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