zoidberg 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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: