zoidberg 0.1.10 → 0.1.12

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: 2bbdb961e871a0119977fa6b936a00ba8c0799ec
4
- data.tar.gz: 8c83222944c0a2a60f0452d02dc72ce5b6b51bf1
3
+ metadata.gz: 99176e505b497b0889a91f059c260a8b1ef45645
4
+ data.tar.gz: 52260a78198f95b9babc69b92af2ac00e43e9769
5
5
  SHA512:
6
- metadata.gz: d3e02732c39a3611c5e17224b6b27b6303c19fd7eeb884cf0215dec496b8d38a494ea322c1c4840d237831581afb70c17a74f422e0131f04d10ff08e310014d9
7
- data.tar.gz: 7f9d18e3ad68bd304a00581a807b929e05d9c472a5761734bac8b525c232189c2dd40e38a3d25fdf767de12c3c5a00e064d6ff0cc00b8356b867b3a25670001a
6
+ metadata.gz: 6823ccd0afece4a93c2b4533dc301ffe75bc8344d4bba9409428cfedd8d10d5930f11a67c119accc05f4384cee6ae56b85d4891b938011c87f781acff22e971c
7
+ data.tar.gz: 7fd4eb56fbdf12be7e007f7fabf1cba8e6b8c850b3de906432330d89f559738c2a9d2d0b7038f3024d55fe4e4e1cc57515b69c1fa20adfbdd3ae3f1b145d1f9e
@@ -1,3 +1,10 @@
1
+ # v0.1.12
2
+ * Move event signal to abstract proxy
3
+ * Update timeout library usage
4
+ * Remove defer usage fetching worker within pool
5
+ * Clean locking usage to prevent miscounts
6
+ * Fix async style locking to ensure expected behavior
7
+
1
8
  # v0.1.10
2
9
  * Handle unexpected errors from asyncs while supervised
3
10
  * Pool releases lock once worker has been aquired
@@ -70,3 +70,7 @@ Zoidberg.default_shell = Zoidberg::SoftShell
70
70
  Zoidberg.signal_shutdown = true
71
71
  end
72
72
  end
73
+
74
+ if(::ENV['ZOIDBERG_TESTING'])
75
+ ::Kernel.require 'timeout'
76
+ end
@@ -86,8 +86,8 @@ module Zoidberg
86
86
  #
87
87
  # @return [Object]
88
88
  def _zoidberg_free_worker
89
- until(worker = @_workers.detect(&:_zoidberg_available?))
90
- defer{ _signal.wait_for(:unlocked) }
89
+ unless(worker = _workers.detect(&:_zoidberg_available?))
90
+ until((worker = _signal.wait_for(:unlocked))._zoidberg_available?); end
91
91
  end
92
92
  worker
93
93
  end
@@ -69,13 +69,17 @@ module Zoidberg
69
69
  end
70
70
 
71
71
  # @return [TrueClass]
72
- def _aquire_lock!
73
- true
72
+ def _aquire_lock!(&block)
73
+ result = block ? block.call : true
74
+ _zoidberg_signal(:locked)
75
+ result
74
76
  end
75
77
 
76
78
  # @return [TrueClass]
77
- def _release_lock!
78
- true
79
+ def _release_lock!(&block)
80
+ result = block ? block.call : true
81
+ _zoidberg_signal(:unlocked, self) if _zoidberg_available?
82
+ result
79
83
  end
80
84
 
81
85
  # @return [TrueClass, FalseClass] currently unlocked
@@ -105,9 +109,9 @@ module Zoidberg
105
109
  #
106
110
  # @param sig [Symbol]
107
111
  # @return [TrueClass, FalseClass] signal was sent
108
- def _zoidberg_signal(sig)
112
+ def _zoidberg_signal(*args)
109
113
  if(@_zoidberg_signal)
110
- @_zoidberg_signal.signal(sig)
114
+ @_zoidberg_signal.signal(*args)
111
115
  true
112
116
  else
113
117
  false
@@ -162,13 +166,16 @@ module Zoidberg
162
166
  end
163
167
  _zoidberg_destroy!
164
168
  _aquire_lock!
165
- args = _build_args.dup
166
- inst = args.shift.unshelled_new(*args.first, &args.last)
167
- _zoidberg_set_instance(inst)
168
- if(_raw_instance.respond_to?(:restarted!))
169
- _raw_instance.restarted!
169
+ begin
170
+ args = _build_args.dup
171
+ inst = args.shift.unshelled_new(*args.first, &args.last)
172
+ _zoidberg_set_instance(inst)
173
+ if(_raw_instance.respond_to?(:restarted!))
174
+ _raw_instance.restarted!
175
+ end
176
+ ensure
177
+ _release_lock!
170
178
  end
171
- _release_lock!
172
179
  end
173
180
  true
174
181
  end
@@ -188,7 +195,7 @@ module Zoidberg
188
195
  _raw_instance.terminate(error)
189
196
  end
190
197
  end
191
- death_from_above = ::Proc.new do
198
+ death_from_above = ::Proc.new do |*_|
192
199
  ::Kernel.raise ::Zoidberg::DeadException.new('Instance in terminated state!')
193
200
  end
194
201
  death_from_above_display = ::Proc.new do
@@ -219,6 +226,24 @@ module Zoidberg
219
226
  self
220
227
  end
221
228
 
229
+ # Override to directly output object stringification
230
+ def to_s
231
+ _raw_instance.to_s
232
+ end
233
+
234
+ # Override to directly output object inspection
235
+ def inspect
236
+ _raw_instance.inspect
237
+ end
238
+
239
+ def signal(*args)
240
+ _raw_instance.signal(*args)
241
+ end
242
+
243
+ def async(*args, &block)
244
+ _raw_instance.async(*args, &block)
245
+ end
246
+
222
247
  end
223
248
  end
224
249
 
@@ -31,10 +31,27 @@ module Zoidberg
31
31
  @_accessing_threads << ::Thread.current
32
32
  begin
33
33
  _aquire_lock!
34
+ @got_lock = true
34
35
  if(::ENV['ZOIDBERG_TESTING'])
35
- ::Kernel.require 'timeout'
36
- ::Timeout.timeout(::ENV.fetch('ZOIDBERG_TESTING_TIMEOUT', 5).to_i) do
37
- res = @_raw_instance.__send__(*args, &block)
36
+ timer = ::Thread.new(::Thread.current) do |origin|
37
+ begin
38
+ time = ::ENV.fetch('ZOIDBERG_TESTING_TIMEOUT', 5).to_i
39
+ ::Timeout.timeout(time) do
40
+ ::Kernel.sleep(time)
41
+ end
42
+ nil
43
+ rescue => error
44
+ error
45
+ end
46
+ end
47
+ res = @_raw_instance.__send__(*args, &block)
48
+ if(timer.alive?)
49
+ timer.kill
50
+ else
51
+ val = timer.value
52
+ if(val.is_a?(Exception))
53
+ raise val
54
+ end
38
55
  end
39
56
  else
40
57
  res = @_raw_instance.__send__(*args, &block)
@@ -51,9 +68,11 @@ module Zoidberg
51
68
  ::Kernel.raise e
52
69
  end
53
70
  ensure
54
- _release_lock!
55
- t_idx = @_accessing_threads.index(::Thread.current)
56
- @_accessing_threads.delete_at(t_idx) if t_idx
71
+ if(@got_lock)
72
+ _release_lock!
73
+ t_idx = @_accessing_threads.index(::Thread.current)
74
+ @_accessing_threads.delete_at(t_idx) if t_idx
75
+ end
57
76
  end
58
77
  res
59
78
  end
@@ -68,41 +87,52 @@ module Zoidberg
68
87
  !_zoidberg_locked?
69
88
  end
70
89
 
90
+ # Register a running thread for this instance. Registered
91
+ # threads are tracked and killed on cleanup
92
+ #
93
+ # @param thread [Thread]
94
+ # @return [TrueClass]
95
+ def _zoidberg_thread(thread)
96
+ _raw_threads[self.object_id].push(thread)
97
+ true
98
+ end
99
+
71
100
  # Aquire the lock to access real instance. If already locked, will
72
101
  # wait until lock can be aquired.
73
102
  #
74
103
  # @return [TrueClas]
75
104
  def _aquire_lock!
76
- if(@_lock)
77
- if(::ENV['ZOIDBERG_DEBUG'] == 'true')
78
- ::Timeout.timeout(::ENV.fetch('ZOIDBERG_DEBUG_TIMEOUT', 10).to_i) do
105
+ super do
106
+ if(@_lock)
107
+ if(::ENV['ZOIDBERG_DEBUG'] == 'true')
108
+ ::Timeout.timeout(::ENV.fetch('ZOIDBERG_DEBUG_TIMEOUT', 10).to_i) do
109
+ @_lock.lock unless @_locker == ::Thread.current
110
+ end
111
+ else
79
112
  @_lock.lock unless @_locker == ::Thread.current
80
113
  end
81
- else
82
- @_lock.lock unless @_locker == ::Thread.current
114
+ @_locker = ::Thread.current
115
+ @_locker_count += 1
83
116
  end
84
- @_locker = ::Thread.current
85
- @_locker_count += 1
86
- _zoidberg_signal(:locked)
117
+ true
87
118
  end
88
- true
89
119
  end
90
120
 
91
121
  # Release the lock to access real instance
92
122
  #
93
123
  # @return [TrueClass]
94
124
  def _release_lock!
95
- if(@_lock)
96
- if(@_locker == ::Thread.current)
125
+ super do
126
+ if(@_lock && @_locker == ::Thread.current)
97
127
  @_locker_count -= 1
98
128
  if(@_locker_count < 1)
99
129
  @_locker = nil
100
130
  @_lock.unlock if @_lock.locked?
101
131
  end
132
+ else
133
+ false
102
134
  end
103
- _zoidberg_signal(:unlocked)
104
135
  end
105
- true
106
136
  end
107
137
 
108
138
  # Ensure any async threads are killed and accessing threads are
@@ -9,20 +9,26 @@ module Zoidberg
9
9
  module SoftShell
10
10
 
11
11
  class AsyncProxy
12
+ attr_reader :locked
12
13
  attr_reader :target
13
14
  attr_reader :origin_proxy
14
- def initialize(instance, proxy)
15
- @target = instance
15
+ def initialize(locked_async, proxy)
16
+ @locked = locked_async
16
17
  @origin_proxy = proxy
18
+ @target = proxy._raw_instance
17
19
  end
18
20
  def method_missing(*args, &block)
19
21
  target._zoidberg_thread(
20
22
  Thread.new{
23
+ origin_proxy._aquire_lock! if locked
24
+ got_lock = locked
21
25
  begin
22
26
  target.send(*args, &block)
23
27
  rescue StandardError, ScriptError => e
24
28
  origin_proxy._zoidberg_unexpected_error(e)
25
29
  raise
30
+ ensure
31
+ origin_proxy._release_lock! if got_lock
26
32
  end
27
33
  }
28
34
  )
@@ -36,14 +42,14 @@ module Zoidberg
36
42
  # @yield block to execute without lock
37
43
  # @return [Object] result of block
38
44
  def defer
39
- _zoidberg_proxy._release_lock!
45
+ re_lock = _zoidberg_proxy._release_lock!
40
46
  begin
41
47
  result = yield if block_given?
42
- _zoidberg_proxy._aquire_lock!
43
48
  result
44
49
  rescue ::StandardError, ::ScriptError => e
45
- _zoidberg_proxy._aquire_lock!
46
50
  raise e
51
+ ensure
52
+ _zoidberg_proxy._aquire_lock! if re_lock
47
53
  end
48
54
  end
49
55
 
@@ -58,24 +64,28 @@ module Zoidberg
58
64
  begin
59
65
  self.instance_exec(&block)
60
66
  rescue ::StandardError, ::ScriptError => e
61
- current_self._zoidberg_unexpected_error(e)
67
+ _zoidberg_proxy._zoidberg_unexpected_error(e)
62
68
  raise
63
69
  end
64
70
  end
65
71
  else
66
72
  thread = ::Thread.new do
73
+ _zoidberg_proxy._aquire_lock!
67
74
  begin
68
- current_self.instance_exec(&block)
75
+ got_lock = true
76
+ self.instance_exec(&block)
69
77
  rescue ::StandardError, ::ScriptError => e
70
- current_self._zoidberg_unexpected_error(e)
78
+ _zoidberg_proxy._zoidberg_unexpected_error(e)
71
79
  raise
80
+ ensure
81
+ _zoidberg_proxy._release_lock! if got_lock
72
82
  end
73
83
  end
74
84
  end
75
85
  _zoidberg_thread(thread)
76
86
  nil
77
87
  else
78
- ::Zoidberg::SoftShell::AsyncProxy.new(locked ? current_self : self, current_self)
88
+ ::Zoidberg::SoftShell::AsyncProxy.new(locked, _zoidberg_proxy)
79
89
  end
80
90
  end
81
91
 
@@ -85,7 +95,7 @@ module Zoidberg
85
95
  # @param thread [Thread]
86
96
  # @return [TrueClass]
87
97
  def _zoidberg_thread(thread)
88
- _zoidberg_proxy._raw_threads[self.object_id].push(thread)
98
+ _zoidberg_proxy._zoidberg_thread(thread)
89
99
  true
90
100
  end
91
101
 
@@ -255,7 +265,7 @@ module Zoidberg
255
265
  # @param arg [Object] optional argument to transmit
256
266
  # @return [TrueClass, FalseClass]
257
267
  def broadcast(name, arg=nil)
258
- current_self._zoidberg_signal_interface.broadcast(*[name, arg].compact)
268
+ _zoidberg_signal_interface.broadcast(*[name, arg].compact)
259
269
  end
260
270
 
261
271
  # Wait for a given signal
@@ -263,7 +273,7 @@ module Zoidberg
263
273
  # @param name [String, Symbol] name of signal
264
274
  # @return [Object]
265
275
  def wait_for(name)
266
- defer{ current_self._zoidberg_signal_interface.wait_for(name) }
276
+ defer{ _zoidberg_signal_interface.wait_for(name) }
267
277
  end
268
278
  alias_method :wait, :wait_for
269
279
 
@@ -1,4 +1,4 @@
1
1
  module Zoidberg
2
2
  # Current library version
3
- VERSION = Gem::Version.new('0.1.10')
3
+ VERSION = Gem::Version.new('0.1.12')
4
4
  end
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.1.10
4
+ version: 0.1.12
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-09-29 00:00:00.000000000 Z
11
+ date: 2015-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bogo