zoidberg 0.2.2 → 0.3.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 32acff92e97fb082892e250a4e672adf569a2648
4
- data.tar.gz: bda6511a8e52e778d0aefc0b7ca3485321cd5aac
3
+ metadata.gz: 63955382f221d56234b75d3e1993cb559975d767
4
+ data.tar.gz: 3039f9fd4a011778e47f4f5aa49e8ba25adf5083
5
5
  SHA512:
6
- metadata.gz: 07941b9b12c199d8d0ecd87992ccefd1bbf2794006e2b1d980306b683f260b362c6d9e9359ea6da68bdbb94aef9580ed76725429b65192ea2610d591669def79
7
- data.tar.gz: 949f2f5f6e5886da400828ca3b1eef2f4c556f6d0e748e6dc6fa77a0a0a2c6111260c67b6fcf7c7f7a57675ac52d145eeb7fd456fbb3512212c216f770ad8259
6
+ metadata.gz: 34a88ecf7b4d6bd6c97d7199eac16a4f3dab30e3e1747d1be07049ec29e3924d48f3b520abcc95115d3a4272f0e9142b7c88bab994a1c5347183e9ce9dda5861
7
+ data.tar.gz: 8931326058903b2a82fc0b517bee6e22174a3037b444b6e4c2ae88807470170bb5a1a71eb2c4d26ca3d521a9685310e372a47129f141f0f46d3d10243a058d29
@@ -1,3 +1,6 @@
1
+ # v0.3.0
2
+ * Initial internal refactor utilizing ruby-concurrent
3
+
1
4
  # v0.2.2
2
5
  * Remove async threads once they have reached completion
3
6
  * Attempt to locate free worker in pool for async, random pick if none
@@ -1,6 +1,8 @@
1
1
  require 'bogo'
2
- require 'thread'
3
2
  require 'securerandom'
3
+ require 'concurrent'
4
+ require 'concurrent-edge'
5
+
4
6
  require 'zoidberg/version'
5
7
 
6
8
  # Why not Zoidberg!?
@@ -24,7 +26,9 @@ module Zoidberg
24
26
 
25
27
  class << self
26
28
 
27
- attr_accessor :signal_shutdown
29
+ # @return [TrueClass, FalseClass]
30
+ attr_reader :signal_shutdown
31
+ # @return [Module]
28
32
  attr_accessor :default_shell
29
33
 
30
34
  # @return [Zoidberg::Logger]
@@ -48,10 +52,28 @@ module Zoidberg
48
52
  SecureRandom.uuid
49
53
  end
50
54
 
55
+ # Flag shutdown state
56
+ #
57
+ # @param val [Truthy, Falsey]
58
+ # @return [TrueClass, FalseClass]
59
+ def signal_shutdown=(val)
60
+ @signal_shutdown = !!val
61
+ # NOTE: Manually call registered at exit items to force
62
+ # global thread pools and related structures to be shut
63
+ # down. Wrapped in a thread to prevent locking issues
64
+ # when set within trap context
65
+ Thread.new{ Concurrent.const_get(:AtExit).run } if val
66
+ @signal_shutdown
67
+ end
68
+
69
+ # Reset shutdown state
70
+ #
71
+ # @return [FalseClass]
51
72
  def signal_reset
52
73
  self.signal_shutdown = false
53
74
  end
54
75
 
76
+ # @return [TrueClass, FalseClass]
55
77
  def in_shutdown?
56
78
  !!self.signal_shutdown
57
79
  end
@@ -4,21 +4,21 @@ module Zoidberg
4
4
  # Perform action and fetch result in the future
5
5
  class Future
6
6
 
7
- # @return [Thread] underlying thread running task
8
- attr_reader :thread
7
+ # @return [Concurrent::Future] underlying thread running task
8
+ attr_reader :future
9
9
 
10
10
  # Create a new instance
11
11
  #
12
12
  # @yield block to execute
13
13
  # @return [self]
14
14
  def initialize(&block)
15
- @thread = Thread.new(&block)
15
+ @future = Concurrent::Future.execute(&block)
16
16
  end
17
17
 
18
18
  # @return [Object] result value
19
19
  def value
20
20
  unless(@value)
21
- @value = @thread.value
21
+ @value = @future.value
22
22
  end
23
23
  @value
24
24
  end
@@ -27,7 +27,7 @@ module Zoidberg
27
27
  #
28
28
  # @return [TrueClass, FalseClass]
29
29
  def available?
30
- !thread.alive?
30
+ future.fulfilled?
31
31
  end
32
32
 
33
33
  end
@@ -76,7 +76,7 @@ module Zoidberg
76
76
  end
77
77
 
78
78
  # Proxy async to prevent synchronized access
79
- def async(*args,&block)
79
+ def async(*args, &block)
80
80
  worker = _workers.detect(&:_zoidberg_available?) || _workers.sample
81
81
  worker.send(:async, *args, &block)
82
82
  end
@@ -10,8 +10,8 @@ module Zoidberg
10
10
 
11
11
  # @return [Thread] current owner of lock
12
12
  attr_reader :_locker
13
- # @return [Hash<Integer:Thread>]
14
- attr_reader :_raw_threads
13
+ # @return [Concurrent::CachedThreadPool]
14
+ attr_reader :_thread_pool
15
15
 
16
16
  # Create a new proxy instance, new real instance, and link them
17
17
  #
@@ -24,7 +24,7 @@ module Zoidberg
24
24
  @_locker = nil
25
25
  @_locker_count = 0
26
26
  @_zoidberg_signal = nil
27
- @_raw_threads = []
27
+ @_thread_pool = ::Concurrent::CachedThreadPool.new
28
28
  @_supervised = klass.ancestors.include?(::Zoidberg::Supervise)
29
29
  end
30
30
 
@@ -85,25 +85,6 @@ module Zoidberg
85
85
  !_zoidberg_locked?
86
86
  end
87
87
 
88
- # Register a running thread for this instance. Registered
89
- # threads are tracked and killed on cleanup
90
- #
91
- # @param thread [Thread]
92
- # @return [TrueClass]
93
- def _zoidberg_thread(thread)
94
- _raw_threads.push(thread)
95
- true
96
- end
97
-
98
- # Deregister a thread once it has completed
99
- #
100
- # @param thread [Thread]
101
- # @return [TrueClass]
102
- def _zoidberg_unthread(thread)
103
- _raw_threads.delete(thread)
104
- true
105
- end
106
-
107
88
  # Aquire the lock to access real instance. If already locked, will
108
89
  # wait until lock can be aquired.
109
90
  #
@@ -151,16 +132,9 @@ module Zoidberg
151
132
  oid = _raw_instance.object_id
152
133
  ::Zoidberg.logger.debug "*** Destroying zoidberg instance #{object_string}"
153
134
  super do
154
- _raw_threads.map do |thread|
155
- thread.raise ::Zoidberg::DeadException.new('Instance in terminated state!', oid)
156
- ::Thread.new(thread) do |thread|
157
- next if thread == ::Thread.current
158
- thread.join(::Zoidberg::Proxy::Liberated::THREAD_KILL_AFTER)
159
- if(thread.alive?)
160
- ::Zoidberg.logger.error "Failed to halt async thread, killing: #{thread.inspect}"
161
- thread.kill
162
- end
163
- end
135
+ _thread_pool.shutdown
136
+ unless(_thread_pool.wait_for_termination(2))
137
+ _thread_pool.kill
164
138
  end
165
139
  @_accessing_threads.each do |thread|
166
140
  if(thread.alive?)
@@ -37,27 +37,24 @@ module Zoidberg
37
37
  @target = proxy._raw_instance
38
38
  end
39
39
  def method_missing(*args, &block)
40
- target._zoidberg_thread(
41
- Thread.new{
42
- got_lock = false
43
- begin
44
- origin_proxy._aquire_lock! if locked
45
- got_lock = locked
46
- target.send(*args, &block)
47
- rescue Zoidberg::DeadException => e
48
- if(e.origin_object_id == target.object_id)
49
- got_lock = false
50
- end
51
- raise
52
- rescue StandardError, ScriptError => e
53
- origin_proxy._zoidberg_unexpected_error(e)
54
- raise
55
- ensure
56
- origin_proxy._release_lock! if got_lock
57
- origin_proxy._zoidberg_unthread(Thread.current)
40
+ origin_proxy._thread_pool << lambda{
41
+ got_lock = false
42
+ begin
43
+ origin_proxy._aquire_lock! if locked
44
+ got_lock = locked
45
+ target.send(*args, &block)
46
+ rescue Zoidberg::DeadException => e
47
+ if(e.origin_object_id == target.object_id)
48
+ got_lock = false
58
49
  end
59
- }
60
- )
50
+ raise
51
+ rescue StandardError, ScriptError => e
52
+ origin_proxy._zoidberg_unexpected_error(e)
53
+ raise
54
+ ensure
55
+ origin_proxy._release_lock! if got_lock
56
+ end
57
+ }
61
58
  nil
62
59
  end
63
60
  end
@@ -89,7 +86,7 @@ module Zoidberg
89
86
  def async(locked=false, &block)
90
87
  if(block_given?)
91
88
  unless(locked)
92
- thread = ::Thread.new do
89
+ _zoidberg_proxy._thread_pool << lambda{
93
90
  begin
94
91
  self.instance_exec(&block)
95
92
  rescue Zoidberg::DeadException => e
@@ -103,9 +100,9 @@ module Zoidberg
103
100
  _zoidberg_proxy._zoidberg_unexpected_error(e)
104
101
  raise
105
102
  end
106
- end
103
+ }
107
104
  else
108
- thread = ::Thread.new do
105
+ _zoidberg_proxy._thread_pool << lambda{
109
106
  _zoidberg_proxy._aquire_lock!
110
107
  begin
111
108
  got_lock = true
@@ -123,25 +120,14 @@ module Zoidberg
123
120
  ensure
124
121
  _zoidberg_proxy._release_lock! if got_lock
125
122
  end
126
- end
123
+ }
127
124
  end
128
- _zoidberg_thread(thread)
129
125
  nil
130
126
  else
131
127
  ::Zoidberg::SoftShell::AsyncProxy.new(locked, _zoidberg_proxy)
132
128
  end
133
129
  end
134
130
 
135
- # Register a running thread for this instance. Registered
136
- # threads are tracked and killed on cleanup
137
- #
138
- # @param thread [Thread]
139
- # @return [TrueClass]
140
- def _zoidberg_thread(thread)
141
- _zoidberg_proxy._zoidberg_thread(thread)
142
- true
143
- end
144
-
145
131
  # Provide a customized sleep behavior which will unlock the real
146
132
  # instance while sleeping
147
133
  #
@@ -66,6 +66,11 @@ module Zoidberg
66
66
  )
67
67
  end
68
68
 
69
+ # @return [Float] reset the action
70
+ def reset
71
+ @last_run = Time.now.to_f
72
+ end
73
+
69
74
  end
70
75
 
71
76
  include Zoidberg::SoftShell
@@ -1,4 +1,4 @@
1
1
  module Zoidberg
2
2
  # Current library version
3
- VERSION = Gem::Version.new('0.2.2')
3
+ VERSION = Gem::Version.new('0.3.0')
4
4
  end
@@ -11,6 +11,8 @@ Gem::Specification.new do |s|
11
11
  s.require_path = 'lib'
12
12
  s.license = 'Apache 2.0'
13
13
  s.add_runtime_dependency 'bogo'
14
+ s.add_runtime_dependency 'concurrent-ruby', '~> 1.0.0'
15
+ s.add_runtime_dependency 'concurrent-ruby-edge', '~> 0.2.0'
14
16
  s.add_runtime_dependency 'mono_logger'
15
17
  s.add_development_dependency 'pry'
16
18
  s.add_development_dependency 'minitest'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zoidberg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Roberts
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-27 00:00:00.000000000 Z
11
+ date: 2016-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bogo
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: concurrent-ruby
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: concurrent-ruby-edge
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.2.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.2.0
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: mono_logger
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -119,3 +147,4 @@ signing_key:
119
147
  specification_version: 4
120
148
  summary: Why not?
121
149
  test_files: []
150
+ has_rdoc: