quack_concurrency 0.5.3 → 0.5.4

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
  SHA256:
3
- metadata.gz: 7c6822c50d1a8483a8009ad94e2725691bf28a71d3e9441d67b092c6b96314db
4
- data.tar.gz: 47a4c773d831b66fe2b40db8ca23f7cb3c44962023ff1e7fc7cc4a4832bc41b9
3
+ metadata.gz: d110c1994e7796f45c3cade0f82f7bae2ce8daa0fa775e32fe92cb5a5d1bb3e7
4
+ data.tar.gz: 1253c01f31d051a5cdccd599c3d1ce597bc580c9e06311727b132aa4e1f2e172
5
5
  SHA512:
6
- metadata.gz: 7aebe4c95df5578c5a68d4331965dd6d68763ffd51e2683cc9aa345be9148b77f060914af76a728c3c394a9bb56ceb8f142a59855a22e6c833a9253f957235ba
7
- data.tar.gz: 1f406ab37a50d2d58f2a4952e1ed7f6152d050fa2d723c9477e8ab6cc9cd540dc31fa72b805027bc98c09d0fa73ae641f3d9e85f523cf91facb0f463be19df6c
6
+ metadata.gz: c44997c7c973429240bbf600ea68818eedb548012ccc0248028a4fc5a18509e9050b44baa92c563190512c1cb34a0999d8624288827915eb4dcdbc05997961ad
7
+ data.tar.gz: 99f22237f7a44ea60ac10c0a25c8ac6627fa17cf13de2f55e4797a749607f676dd02ffbfd47ade2f93a983e5ca83dab89e8374480ab930326154e47c14d69c36
@@ -61,18 +61,30 @@ module QuackConcurrency
61
61
  end
62
62
  @mutex.synchronize { @waiting_threads.push(caller) }
63
63
  if mutex
64
+ # ideally we would would check if this Thread can sleep (not the last Thread alive)
65
+ # before we unlock the mutex, however I am not sure is that can be implemented
64
66
  if mutex.respond_to?(:unlock!)
65
67
  mutex.unlock! { sleep(timeout) }
66
68
  else
67
69
  mutex.unlock
68
- sleep(timeout)
69
- mutex.lock
70
+ begin
71
+ sleep(timeout)
72
+ ensure # rescue a fatal error (eg. only Thread stopped)
73
+ if mutex.locked?
74
+ # another Thread locked this before it died
75
+ # this is not a correct state to be in but I don't know how to fix it
76
+ # given that there are no other alive Threads then than the ramifications should be minimal
77
+ else
78
+ mutex.lock
79
+ end
80
+ end
70
81
  end
71
82
  else
72
83
  sleep(timeout)
73
84
  end
74
- @mutex.synchronize { @waiting_threads.delete(caller) }
75
85
  self
86
+ ensure
87
+ @mutex.synchronize { @waiting_threads.delete(caller) }
76
88
  end
77
89
 
78
90
  # Returns the number of `Thread`s currently waiting.
@@ -35,18 +35,30 @@ module QuackConcurrency
35
35
  sleeper = UninterruptibleSleeper.for_current
36
36
  @mutex.synchronize { @waiting_threads_sleepers.push(sleeper) }
37
37
  if mutex
38
+ # ideally we would would check if this Thread can sleep (not the last Thread alive)
39
+ # before we unlock the mutex, however I am not sure is that can be implemented
38
40
  if mutex.respond_to?(:unlock!)
39
41
  mutex.unlock! { sleep(sleeper, timeout) }
40
42
  else
41
43
  mutex.unlock
42
- sleep(sleeper, timeout)
43
- mutex.lock
44
+ begin
45
+ sleep(sleeper, timeout)
46
+ ensure # rescue a fatal error (eg. only Thread stopped)
47
+ if mutex.locked?
48
+ # another Thread locked this before it died
49
+ # this is not a correct state to be in but I don't know how to fix it
50
+ # given that there are no other alive Threads then than the ramifications should be minimal
51
+ else
52
+ mutex.lock
53
+ end
54
+ end
44
55
  end
45
56
  else
46
57
  sleep(sleeper, timeout)
47
58
  end
48
- @mutex.synchronize { @waiting_threads_sleepers.delete(sleeper) }
49
59
  self
60
+ ensure
61
+ @mutex.synchronize { @waiting_threads_sleepers.delete(sleeper) }
50
62
  end
51
63
 
52
64
  def waiting_threads_count
@@ -54,7 +66,7 @@ module QuackConcurrency
54
66
  end
55
67
 
56
68
  private
57
-
69
+
58
70
  # @api private
59
71
  def signal_next
60
72
  next_waiting_thread_sleeper = @waiting_threads_sleepers.shift
@@ -4,6 +4,8 @@ module QuackConcurrency
4
4
  # Unlike simply calling `Thread#sleep`, {#stop_thread} will ensure that only
5
5
  # calling {#run_thread} on this {UninterruptibleSleeper} will wake the `Thread`.
6
6
  # Any call to `Thread#run` directly, will be ignored.
7
+ # `Thread`s can still be resumed if `Thread#raise` is called.
8
+ # A `ThreadError` will be raised if a the last running `Thread` is stopped.
7
9
  class UninterruptibleSleeper
8
10
 
9
11
  def self.for_current
@@ -52,13 +54,14 @@ module QuackConcurrency
52
54
  time_left = target_end_time - Time.now
53
55
  Kernel.sleep(time_left) if time_left > 0
54
56
  else
55
- Thread.stop
57
+ Thread.stop # may raise ThreadError if this is last running Thread
56
58
  end
57
59
  break if @state == :running || Time.now >= target_time
58
60
  end
61
+ ensure
59
62
  @state = :running
60
63
 
61
- # we relock the mutex ensure #run_thread has finshed before #stop_thread
64
+ # we relock the mutex to ensure #run_thread has finshed before #stop_thread
62
65
  # if Thread#run is called by another part of the code at the same time as
63
66
  # #run_thread is being called, we dont want the call to #run_thread
64
67
  # to call Thread#run on a Thread has already resumed and stopped again
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quack_concurrency
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.3
4
+ version: 0.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Fors