concurrent-ruby 1.1.10 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -1
  3. data/Gemfile +0 -1
  4. data/README.md +21 -20
  5. data/Rakefile +46 -57
  6. data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +10 -25
  7. data/lib/concurrent-ruby/concurrent/agent.rb +2 -1
  8. data/lib/concurrent-ruby/concurrent/array.rb +0 -10
  9. data/lib/concurrent-ruby/concurrent/atom.rb +1 -1
  10. data/lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb +5 -4
  11. data/lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb +5 -4
  12. data/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb +3 -0
  13. data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +81 -151
  14. data/lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb +1 -1
  15. data/lib/concurrent-ruby/concurrent/atomic/event.rb +1 -1
  16. data/lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb +109 -0
  17. data/lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb +1 -0
  18. data/lib/concurrent-ruby/concurrent/atomic/locals.rb +188 -0
  19. data/lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb +28 -0
  20. data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb +11 -5
  21. data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb +11 -5
  22. data/lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb +1 -1
  23. data/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb +1 -1
  24. data/lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb +2 -1
  25. data/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb +5 -3
  26. data/lib/concurrent-ruby/concurrent/atomic/semaphore.rb +6 -9
  27. data/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb +96 -89
  28. data/lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb +37 -0
  29. data/lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb +15 -4
  30. data/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb +1 -1
  31. data/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb +1 -1
  32. data/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb +2 -0
  33. data/lib/concurrent-ruby/concurrent/concern/logging.rb +86 -2
  34. data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
  35. data/lib/concurrent-ruby/concurrent/configuration.rb +4 -87
  36. data/lib/concurrent-ruby/concurrent/delay.rb +2 -2
  37. data/lib/concurrent-ruby/concurrent/errors.rb +5 -0
  38. data/lib/concurrent-ruby/concurrent/exchanger.rb +1 -0
  39. data/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb +1 -1
  40. data/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb +2 -2
  41. data/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb +1 -1
  42. data/lib/concurrent-ruby/concurrent/executor/serialized_execution.rb +1 -1
  43. data/lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb +4 -1
  44. data/lib/concurrent-ruby/concurrent/hash.rb +0 -9
  45. data/lib/concurrent-ruby/concurrent/immutable_struct.rb +1 -1
  46. data/lib/concurrent-ruby/concurrent/ivar.rb +2 -1
  47. data/lib/concurrent-ruby/concurrent/map.rb +9 -8
  48. data/lib/concurrent-ruby/concurrent/maybe.rb +1 -1
  49. data/lib/concurrent-ruby/concurrent/mutable_struct.rb +1 -1
  50. data/lib/concurrent-ruby/concurrent/mvar.rb +1 -1
  51. data/lib/concurrent-ruby/concurrent/promise.rb +1 -1
  52. data/lib/concurrent-ruby/concurrent/promises.rb +7 -6
  53. data/lib/concurrent-ruby/concurrent/re_include.rb +2 -0
  54. data/lib/concurrent-ruby/concurrent/scheduled_task.rb +1 -1
  55. data/lib/concurrent-ruby/concurrent/set.rb +0 -10
  56. data/lib/concurrent-ruby/concurrent/settable_struct.rb +2 -2
  57. data/lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb +5 -1
  58. data/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb +1 -3
  59. data/lib/concurrent-ruby/concurrent/synchronization/condition.rb +2 -0
  60. data/lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb +29 -0
  61. data/lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb +3 -1
  62. data/lib/concurrent-ruby/concurrent/synchronization/lock.rb +2 -0
  63. data/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb +5 -2
  64. data/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb +6 -5
  65. data/lib/concurrent-ruby/concurrent/synchronization/object.rb +12 -44
  66. data/lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb +36 -0
  67. data/lib/concurrent-ruby/concurrent/synchronization/volatile.rb +77 -12
  68. data/lib/concurrent-ruby/concurrent/synchronization.rb +1 -18
  69. data/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb +36 -39
  70. data/lib/concurrent-ruby/concurrent/thread_safe/util/cheap_lockable.rb +2 -39
  71. data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +1 -37
  72. data/lib/concurrent-ruby/concurrent/tuple.rb +1 -5
  73. data/lib/concurrent-ruby/concurrent/tvar.rb +2 -1
  74. data/lib/concurrent-ruby/concurrent/utility/engine.rb +5 -16
  75. data/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb +3 -74
  76. data/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb +8 -10
  77. data/lib/concurrent-ruby/concurrent/utility/native_integer.rb +1 -0
  78. data/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +34 -54
  79. data/lib/concurrent-ruby/concurrent/version.rb +1 -1
  80. metadata +13 -15
  81. data/lib/concurrent-ruby/concurrent/atomic/abstract_thread_local_var.rb +0 -66
  82. data/lib/concurrent-ruby/concurrent/atomic/java_thread_local_var.rb +0 -37
  83. data/lib/concurrent-ruby/concurrent/atomic/ruby_thread_local_var.rb +0 -181
  84. data/lib/concurrent-ruby/concurrent/synchronization/jruby_object.rb +0 -45
  85. data/lib/concurrent-ruby/concurrent/synchronization/mri_object.rb +0 -44
  86. data/lib/concurrent-ruby/concurrent/synchronization/rbx_lockable_object.rb +0 -71
  87. data/lib/concurrent-ruby/concurrent/synchronization/rbx_object.rb +0 -49
  88. data/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb +0 -47
@@ -1,7 +1,8 @@
1
1
  require 'thread'
2
2
  require 'concurrent/atomic/atomic_fixnum'
3
3
  require 'concurrent/errors'
4
- require 'concurrent/synchronization'
4
+ require 'concurrent/synchronization/object'
5
+ require 'concurrent/synchronization/lock'
5
6
 
6
7
  module Concurrent
7
8
 
@@ -1,8 +1,10 @@
1
1
  require 'thread'
2
2
  require 'concurrent/atomic/atomic_reference'
3
+ require 'concurrent/atomic/atomic_fixnum'
3
4
  require 'concurrent/errors'
4
- require 'concurrent/synchronization'
5
- require 'concurrent/atomic/thread_local_var'
5
+ require 'concurrent/synchronization/object'
6
+ require 'concurrent/synchronization/lock'
7
+ require 'concurrent/atomic/lock_local_var'
6
8
 
7
9
  module Concurrent
8
10
 
@@ -109,7 +111,7 @@ module Concurrent
109
111
  @Counter = AtomicFixnum.new(0) # single integer which represents lock state
110
112
  @ReadQueue = Synchronization::Lock.new # used to queue waiting readers
111
113
  @WriteQueue = Synchronization::Lock.new # used to queue waiting writers
112
- @HeldCount = ThreadLocalVar.new(0) # indicates # of R & W locks held by this thread
114
+ @HeldCount = LockLocalVar.new(0) # indicates # of R & W locks held by this thread
113
115
  end
114
116
 
115
117
  # Execute a block operation within a read lock.
@@ -1,5 +1,4 @@
1
1
  require 'concurrent/atomic/mutex_semaphore'
2
- require 'concurrent/synchronization'
3
2
 
4
3
  module Concurrent
5
4
 
@@ -11,7 +10,7 @@ module Concurrent
11
10
  #
12
11
  # @param [Fixnum] count the initial count
13
12
  #
14
- # @raise [ArgumentError] if `count` is not an integer or is less than zero
13
+ # @raise [ArgumentError] if `count` is not an integer
15
14
 
16
15
  # @!macro semaphore_method_acquire
17
16
  #
@@ -21,8 +20,7 @@ module Concurrent
21
20
  #
22
21
  # @param [Fixnum] permits Number of permits to acquire
23
22
  #
24
- # @raise [ArgumentError] if `permits` is not an integer or is less than
25
- # one
23
+ # @raise [ArgumentError] if `permits` is not an integer or is less than zero
26
24
  #
27
25
  # @return [nil, BasicObject] Without a block, `nil` is returned. If a block
28
26
  # is given, its return value is returned.
@@ -52,8 +50,7 @@ module Concurrent
52
50
  # @param [Fixnum] timeout the number of seconds to wait for the counter
53
51
  # or `nil` to return immediately
54
52
  #
55
- # @raise [ArgumentError] if `permits` is not an integer or is less than
56
- # one
53
+ # @raise [ArgumentError] if `permits` is not an integer or is less than zero
57
54
  #
58
55
  # @return [true, false, nil, BasicObject] `false` if no permits are
59
56
  # available, `true` when acquired a permit. If a block is given, the
@@ -66,7 +63,7 @@ module Concurrent
66
63
  #
67
64
  # @param [Fixnum] permits Number of permits to return to the semaphore.
68
65
  #
69
- # @raise [ArgumentError] if `permits` is not a number or is less than one
66
+ # @raise [ArgumentError] if `permits` is not a number or is less than zero
70
67
  #
71
68
  # @return [nil]
72
69
 
@@ -96,8 +93,8 @@ module Concurrent
96
93
 
97
94
  # @!visibility private
98
95
  # @!macro internal_implementation_note
99
- SemaphoreImplementation = case
100
- when defined?(JavaSemaphore)
96
+ SemaphoreImplementation = if Concurrent.on_jruby?
97
+ require 'concurrent/utility/native_extension_loader'
101
98
  JavaSemaphore
102
99
  else
103
100
  MutexSemaphore
@@ -1,104 +1,111 @@
1
- require 'concurrent/utility/engine'
2
- require 'concurrent/atomic/ruby_thread_local_var'
3
- require 'concurrent/atomic/java_thread_local_var'
1
+ require 'concurrent/constants'
2
+ require_relative 'locals'
4
3
 
5
4
  module Concurrent
6
5
 
7
- ###################################################################
8
-
9
- # @!macro thread_local_var_method_initialize
6
+ # A `ThreadLocalVar` is a variable where the value is different for each thread.
7
+ # Each variable may have a default value, but when you modify the variable only
8
+ # the current thread will ever see that change.
9
+ #
10
+ # This is similar to Ruby's built-in thread-local variables (`Thread#thread_variable_get`),
11
+ # but with these major advantages:
12
+ # * `ThreadLocalVar` has its own identity, it doesn't need a Symbol.
13
+ # * Each Ruby's built-in thread-local variable leaks some memory forever (it's a Symbol held forever on the thread),
14
+ # so it's only OK to create a small amount of them.
15
+ # `ThreadLocalVar` has no such issue and it is fine to create many of them.
16
+ # * Ruby's built-in thread-local variables leak forever the value set on each thread (unless set to nil explicitly).
17
+ # `ThreadLocalVar` automatically removes the mapping for each thread once the `ThreadLocalVar` instance is GC'd.
18
+ #
19
+ # @!macro thread_safe_variable_comparison
20
+ #
21
+ # @example
22
+ # v = ThreadLocalVar.new(14)
23
+ # v.value #=> 14
24
+ # v.value = 2
25
+ # v.value #=> 2
26
+ #
27
+ # @example
28
+ # v = ThreadLocalVar.new(14)
29
+ #
30
+ # t1 = Thread.new do
31
+ # v.value #=> 14
32
+ # v.value = 1
33
+ # v.value #=> 1
34
+ # end
10
35
  #
11
- # Creates a thread local variable.
36
+ # t2 = Thread.new do
37
+ # v.value #=> 14
38
+ # v.value = 2
39
+ # v.value #=> 2
40
+ # end
12
41
  #
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
42
+ # v.value #=> 14
43
+ class ThreadLocalVar
44
+ LOCALS = ThreadLocals.new
16
45
 
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
46
+ # Creates a thread local variable.
47
+ #
48
+ # @param [Object] default the default value when otherwise unset
49
+ # @param [Proc] default_block Optional block that gets called to obtain the
50
+ # default value for each thread
51
+ def initialize(default = nil, &default_block)
52
+ if default && block_given?
53
+ raise ArgumentError, "Cannot use both value and block as default value"
54
+ end
22
55
 
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
56
+ if block_given?
57
+ @default_block = default_block
58
+ @default = nil
59
+ else
60
+ @default_block = nil
61
+ @default = default
62
+ end
29
63
 
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
64
+ @index = LOCALS.next_index(self)
65
+ end
38
66
 
67
+ # Returns the value in the current thread's copy of this thread-local variable.
68
+ #
69
+ # @return [Object] the current value
70
+ def value
71
+ LOCALS.fetch(@index) { default }
72
+ end
39
73
 
40
- ###################################################################
74
+ # Sets the current thread's copy of this thread-local variable to the specified value.
75
+ #
76
+ # @param [Object] value the value to set
77
+ # @return [Object] the new value
78
+ def value=(value)
79
+ LOCALS.set(@index, value)
80
+ end
41
81
 
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
82
+ # Bind the given value to thread local storage during
83
+ # execution of the given block.
84
+ #
85
+ # @param [Object] value the value to bind
86
+ # @yield the operation to be performed with the bound variable
87
+ # @return [Object] the value
88
+ def bind(value)
89
+ if block_given?
90
+ old_value = self.value
91
+ self.value = value
92
+ begin
93
+ yield
94
+ ensure
95
+ self.value = old_value
96
+ end
97
+ end
98
+ end
55
99
 
56
- ###################################################################
100
+ protected
57
101
 
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
102
+ # @!visibility private
103
+ def default
104
+ if @default_block
105
+ self.value = @default_block.call
106
+ else
107
+ @default
108
+ end
109
+ end
103
110
  end
104
111
  end
@@ -0,0 +1,37 @@
1
+ require 'concurrent/errors'
2
+
3
+ module Concurrent
4
+
5
+ # Define update methods that use direct paths
6
+ #
7
+ # @!visibility private
8
+ # @!macro internal_implementation_note
9
+ module AtomicDirectUpdate
10
+ def update
11
+ true until compare_and_set(old_value = get, new_value = yield(old_value))
12
+ new_value
13
+ end
14
+
15
+ def try_update
16
+ old_value = get
17
+ new_value = yield old_value
18
+
19
+ return unless compare_and_set old_value, new_value
20
+
21
+ new_value
22
+ end
23
+
24
+ def try_update!
25
+ old_value = get
26
+ new_value = yield old_value
27
+ unless compare_and_set(old_value, new_value)
28
+ if $VERBOSE
29
+ raise ConcurrentUpdateError, "Update failed"
30
+ else
31
+ raise ConcurrentUpdateError, "Update failed", ConcurrentUpdateError::CONC_UP_ERR_BACKTRACE
32
+ end
33
+ end
34
+ new_value
35
+ end
36
+ end
37
+ end
@@ -1,8 +1,13 @@
1
+ require 'concurrent/atomic_reference/atomic_direct_update'
2
+ require 'concurrent/atomic_reference/numeric_cas_wrapper'
3
+ require 'concurrent/synchronization/safe_initialization'
4
+
1
5
  module Concurrent
2
6
 
3
7
  # @!visibility private
4
8
  # @!macro internal_implementation_note
5
- class MutexAtomicReference < Synchronization::LockableObject
9
+ class MutexAtomicReference
10
+ extend Concurrent::Synchronization::SafeInitialization
6
11
  include AtomicDirectUpdate
7
12
  include AtomicNumericCompareAndSetWrapper
8
13
  alias_method :compare_and_swap, :compare_and_set
@@ -10,7 +15,8 @@ module Concurrent
10
15
  # @!macro atomic_reference_method_initialize
11
16
  def initialize(value = nil)
12
17
  super()
13
- synchronize { ns_initialize(value) }
18
+ @Lock = ::Mutex.new
19
+ @value = value
14
20
  end
15
21
 
16
22
  # @!macro atomic_reference_method_get
@@ -49,8 +55,13 @@ module Concurrent
49
55
 
50
56
  protected
51
57
 
52
- def ns_initialize(value)
53
- @value = value
58
+ # @!visibility private
59
+ def synchronize
60
+ if @Lock.owned?
61
+ yield
62
+ else
63
+ @Lock.synchronize { yield }
64
+ end
54
65
  end
55
66
  end
56
67
  end
@@ -1,4 +1,4 @@
1
- require 'concurrent/synchronization'
1
+ require 'concurrent/synchronization/lockable_object'
2
2
 
3
3
  module Concurrent
4
4
  module Collection
@@ -1,4 +1,4 @@
1
- require 'concurrent/synchronization'
1
+ require 'concurrent/synchronization/lockable_object'
2
2
 
3
3
  module Concurrent
4
4
  module Collection
@@ -1,3 +1,5 @@
1
+ require 'concurrent/synchronization/object'
2
+
1
3
  module Concurrent
2
4
 
3
5
  # @!macro warn.edge
@@ -1,4 +1,5 @@
1
1
  require 'logger'
2
+ require 'concurrent/atomic/atomic_reference'
2
3
 
3
4
  module Concurrent
4
5
  module Concern
@@ -15,8 +16,6 @@ module Concurrent
15
16
  # @param [String, nil] message when nil block is used to generate the message
16
17
  # @yieldreturn [String] a message
17
18
  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
19
  logger = if defined?(@logger) && @logger
21
20
  @logger
22
21
  else
@@ -30,3 +29,88 @@ module Concurrent
30
29
  end
31
30
  end
32
31
  end
32
+
33
+ module Concurrent
34
+ extend Concern::Logging
35
+
36
+ # @return [Logger] Logger with provided level and output.
37
+ def self.create_simple_logger(level = Logger::FATAL, output = $stderr)
38
+ # TODO (pitr-ch 24-Dec-2016): figure out why it had to be replaced, stdlogger was deadlocking
39
+ lambda do |severity, progname, message = nil, &block|
40
+ return false if severity < level
41
+
42
+ message = block ? block.call : message
43
+ formatted_message = case message
44
+ when String
45
+ message
46
+ when Exception
47
+ format "%s (%s)\n%s",
48
+ message.message, message.class, (message.backtrace || []).join("\n")
49
+ else
50
+ message.inspect
51
+ end
52
+
53
+ output.print format "[%s] %5s -- %s: %s\n",
54
+ Time.now.strftime('%Y-%m-%d %H:%M:%S.%L'),
55
+ Logger::SEV_LABEL[severity],
56
+ progname,
57
+ formatted_message
58
+ true
59
+ end
60
+ end
61
+
62
+ # Use logger created by #create_simple_logger to log concurrent-ruby messages.
63
+ def self.use_simple_logger(level = Logger::FATAL, output = $stderr)
64
+ Concurrent.global_logger = create_simple_logger level, output
65
+ end
66
+
67
+ # @return [Logger] Logger with provided level and output.
68
+ # @deprecated
69
+ def self.create_stdlib_logger(level = Logger::FATAL, output = $stderr)
70
+ logger = Logger.new(output)
71
+ logger.level = level
72
+ logger.formatter = lambda do |severity, datetime, progname, msg|
73
+ formatted_message = case msg
74
+ when String
75
+ msg
76
+ when Exception
77
+ format "%s (%s)\n%s",
78
+ msg.message, msg.class, (msg.backtrace || []).join("\n")
79
+ else
80
+ msg.inspect
81
+ end
82
+ format "[%s] %5s -- %s: %s\n",
83
+ datetime.strftime('%Y-%m-%d %H:%M:%S.%L'),
84
+ severity,
85
+ progname,
86
+ formatted_message
87
+ end
88
+
89
+ lambda do |loglevel, progname, message = nil, &block|
90
+ logger.add loglevel, message, progname, &block
91
+ end
92
+ end
93
+
94
+ # Use logger created by #create_stdlib_logger to log concurrent-ruby messages.
95
+ # @deprecated
96
+ def self.use_stdlib_logger(level = Logger::FATAL, output = $stderr)
97
+ Concurrent.global_logger = create_stdlib_logger level, output
98
+ end
99
+
100
+ # TODO (pitr-ch 27-Dec-2016): remove deadlocking stdlib_logger methods
101
+
102
+ # Suppresses all output when used for logging.
103
+ NULL_LOGGER = lambda { |level, progname, message = nil, &block| }
104
+
105
+ # @!visibility private
106
+ GLOBAL_LOGGER = AtomicReference.new(create_simple_logger(Logger::WARN))
107
+ private_constant :GLOBAL_LOGGER
108
+
109
+ def self.global_logger
110
+ GLOBAL_LOGGER.value
111
+ end
112
+
113
+ def self.global_logger=(value)
114
+ GLOBAL_LOGGER.value = value
115
+ end
116
+ end
@@ -1,102 +1,19 @@
1
1
  require 'thread'
2
2
  require 'concurrent/delay'
3
3
  require 'concurrent/errors'
4
- require 'concurrent/atomic/atomic_reference'
5
- require 'concurrent/concern/logging'
6
4
  require 'concurrent/concern/deprecation'
7
5
  require 'concurrent/executor/immediate_executor'
6
+ require 'concurrent/executor/fixed_thread_pool'
8
7
  require 'concurrent/executor/cached_thread_pool'
9
8
  require 'concurrent/utility/processor_counter'
10
9
 
11
10
  module Concurrent
12
- extend Concern::Logging
13
11
  extend Concern::Deprecation
14
12
 
15
13
  autoload :Options, 'concurrent/options'
16
14
  autoload :TimerSet, 'concurrent/executor/timer_set'
17
15
  autoload :ThreadPoolExecutor, 'concurrent/executor/thread_pool_executor'
18
16
 
19
- # @return [Logger] Logger with provided level and output.
20
- def self.create_simple_logger(level = Logger::FATAL, output = $stderr)
21
- # TODO (pitr-ch 24-Dec-2016): figure out why it had to be replaced, stdlogger was deadlocking
22
- lambda do |severity, progname, message = nil, &block|
23
- return false if severity < level
24
-
25
- message = block ? block.call : message
26
- formatted_message = case message
27
- when String
28
- message
29
- when Exception
30
- format "%s (%s)\n%s",
31
- message.message, message.class, (message.backtrace || []).join("\n")
32
- else
33
- message.inspect
34
- end
35
-
36
- output.print format "[%s] %5s -- %s: %s\n",
37
- Time.now.strftime('%Y-%m-%d %H:%M:%S.%L'),
38
- Logger::SEV_LABEL[severity],
39
- progname,
40
- formatted_message
41
- true
42
- end
43
- end
44
-
45
- # Use logger created by #create_simple_logger to log concurrent-ruby messages.
46
- def self.use_simple_logger(level = Logger::FATAL, output = $stderr)
47
- Concurrent.global_logger = create_simple_logger level, output
48
- end
49
-
50
- # @return [Logger] Logger with provided level and output.
51
- # @deprecated
52
- def self.create_stdlib_logger(level = Logger::FATAL, output = $stderr)
53
- logger = Logger.new(output)
54
- logger.level = level
55
- logger.formatter = lambda do |severity, datetime, progname, msg|
56
- formatted_message = case msg
57
- when String
58
- msg
59
- when Exception
60
- format "%s (%s)\n%s",
61
- msg.message, msg.class, (msg.backtrace || []).join("\n")
62
- else
63
- msg.inspect
64
- end
65
- format "[%s] %5s -- %s: %s\n",
66
- datetime.strftime('%Y-%m-%d %H:%M:%S.%L'),
67
- severity,
68
- progname,
69
- formatted_message
70
- end
71
-
72
- lambda do |loglevel, progname, message = nil, &block|
73
- logger.add loglevel, message, progname, &block
74
- end
75
- end
76
-
77
- # Use logger created by #create_stdlib_logger to log concurrent-ruby messages.
78
- # @deprecated
79
- def self.use_stdlib_logger(level = Logger::FATAL, output = $stderr)
80
- Concurrent.global_logger = create_stdlib_logger level, output
81
- end
82
-
83
- # TODO (pitr-ch 27-Dec-2016): remove deadlocking stdlib_logger methods
84
-
85
- # Suppresses all output when used for logging.
86
- NULL_LOGGER = lambda { |level, progname, message = nil, &block| }
87
-
88
- # @!visibility private
89
- GLOBAL_LOGGER = AtomicReference.new(create_simple_logger(Logger::WARN))
90
- private_constant :GLOBAL_LOGGER
91
-
92
- def self.global_logger
93
- GLOBAL_LOGGER.value
94
- end
95
-
96
- def self.global_logger=(value)
97
- GLOBAL_LOGGER.value = value
98
- end
99
-
100
17
  # @!visibility private
101
18
  GLOBAL_FAST_EXECUTOR = Delay.new { Concurrent.new_fast_executor }
102
19
  private_constant :GLOBAL_FAST_EXECUTOR
@@ -136,14 +53,14 @@ module Concurrent
136
53
  #
137
54
  # @return [ThreadPoolExecutor] the thread pool
138
55
  def self.global_fast_executor
139
- GLOBAL_FAST_EXECUTOR.value
56
+ GLOBAL_FAST_EXECUTOR.value!
140
57
  end
141
58
 
142
59
  # Global thread pool optimized for long, blocking (IO) *tasks*.
143
60
  #
144
61
  # @return [ThreadPoolExecutor] the thread pool
145
62
  def self.global_io_executor
146
- GLOBAL_IO_EXECUTOR.value
63
+ GLOBAL_IO_EXECUTOR.value!
147
64
  end
148
65
 
149
66
  def self.global_immediate_executor
@@ -154,7 +71,7 @@ module Concurrent
154
71
  #
155
72
  # @return [Concurrent::TimerSet] the thread pool
156
73
  def self.global_timer_set
157
- GLOBAL_TIMER_SET.value
74
+ GLOBAL_TIMER_SET.value!
158
75
  end
159
76
 
160
77
  # General access point to global executors.
@@ -1,7 +1,7 @@
1
1
  require 'thread'
2
2
  require 'concurrent/concern/obligation'
3
3
  require 'concurrent/executor/immediate_executor'
4
- require 'concurrent/synchronization'
4
+ require 'concurrent/synchronization/lockable_object'
5
5
 
6
6
  module Concurrent
7
7
 
@@ -67,7 +67,7 @@ module Concurrent
67
67
 
68
68
  # Return the value this object represents after applying the options
69
69
  # specified by the `#set_deref_options` method. If the delayed operation
70
- # raised an exception this method will return nil. The execption object
70
+ # raised an exception this method will return nil. The exception object
71
71
  # can be accessed via the `#reason` method.
72
72
  #
73
73
  # @param [Numeric] timeout the maximum number of seconds to wait
@@ -66,4 +66,9 @@ module Concurrent
66
66
  end
67
67
  end
68
68
 
69
+ # @!macro internal_implementation_note
70
+ class ConcurrentUpdateError < ThreadError
71
+ # frozen pre-allocated backtrace to speed ConcurrentUpdateError
72
+ CONC_UP_ERR_BACKTRACE = ['backtrace elided; set verbose to enable'].freeze
73
+ end
69
74
  end
@@ -289,6 +289,7 @@ module Concurrent
289
289
  end
290
290
 
291
291
  if Concurrent.on_jruby?
292
+ require 'concurrent/utility/native_extension_loader'
292
293
 
293
294
  # @!macro internal_implementation_note
294
295
  # @!visibility private
@@ -1,7 +1,7 @@
1
1
  require 'concurrent/errors'
2
2
  require 'concurrent/concern/deprecation'
3
3
  require 'concurrent/executor/executor_service'
4
- require 'concurrent/synchronization'
4
+ require 'concurrent/synchronization/lockable_object'
5
5
 
6
6
  module Concurrent
7
7