zoidberg 0.1.10 → 0.1.12

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: 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