thread 0.0.7 → 0.0.8

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: ccee102c708a6f45b30e88830ed170d244be7036
4
- data.tar.gz: e2ff57960a623ab11f82aefe7372900f589602ac
3
+ metadata.gz: b8caeb122b45ef1fbfce75eae1c2f313ff356060
4
+ data.tar.gz: 5e851cb4ac1a270cf461fe4e4658168aac1bdb0b
5
5
  SHA512:
6
- metadata.gz: ed75e1af05833e2860b345a988f75cb985edd06564f78289a69a5bac1243609db45788c6682b55b1c2c313fd32d847ffda72e4b835fca506356b113c4fa06ef8
7
- data.tar.gz: e0308daa7693621bdf0dd753ec329989c448a61e29e09645db50432db3367e07ce4ae2a0e2c1d5c72fcd2c608271df541fe56f32f8feadbe99a149bcc56b7413
6
+ metadata.gz: e54a7cab6bfbb3144a2aa506804d5f9a4ea7b38c42f2e9ff2a55ace0dc0fce6a8554fa0de251041fa8fad8e481f70daf037076a9f9ef15d09fcd3394dd124739
7
+ data.tar.gz: 64b5e21bff244a09cd7fa5696d87533a7cfe0bd5622de3143c6b53a4d9c396abd43c0e0a5fdea8172dc64419419a4bf8b7fde93a11f7e7f7ee2be9aec6ddbcfe
data/README.md CHANGED
@@ -169,3 +169,27 @@ d = Thread.delay {
169
169
 
170
170
  puts ~d # => 42
171
171
  ```
172
+
173
+ Every
174
+ =====
175
+ An every executes the block every given seconds and yields the value to the
176
+ every object, you can then check if the current value is old or how much time
177
+ is left until the second call is done.
178
+
179
+ Example
180
+ -------
181
+
182
+ ```ruby
183
+ require 'net/http'
184
+ require 'thread/every'
185
+
186
+ e = Thread.every(5) {
187
+ Net::HTTP.get(URI.parse('http://www.whattimeisit.com/')).match %r{<B>(.*?)<BR>\s+(.*?)</B>}m do |m|
188
+ { date: m[1], time: m[2] }
189
+ end
190
+ }
191
+
192
+ loop do
193
+ puts ~e
194
+ end
195
+ ```
data/Rakefile CHANGED
@@ -16,5 +16,6 @@ task :test do
16
16
  sh 'rspec future_spec.rb --backtrace --color --format doc'
17
17
  sh 'rspec delay_spec.rb --backtrace --color --format doc'
18
18
  sh 'rspec pipe_spec.rb --backtrace --color --format doc'
19
+ sh 'rspec every_spec.rb --backtrace --color --format doc'
19
20
  end
20
21
  end
@@ -0,0 +1,197 @@
1
+ #--
2
+ # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
3
+ # Version 2, December 2004
4
+ #
5
+ # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
6
+ # TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
7
+ #
8
+ # 0. You just DO WHAT THE FUCK YOU WANT TO.
9
+ #++
10
+
11
+ require 'thread'
12
+
13
+ # An every runs the given block every given seconds, you can then get the
14
+ # value, check if the value is old and you can check how many seconds
15
+ # until the next run.
16
+ class Thread::Every
17
+ Cancel = Class.new(Exception)
18
+ Restart = Class.new(Exception)
19
+
20
+ # Create an every with the given seconds and block.
21
+ def initialize (every, &block)
22
+ raise ArgumentError, 'no block given' unless block
23
+
24
+ @every = every
25
+ @old = true
26
+ @mutex = Mutex.new
27
+ @thread = Thread.new {
28
+ loop do
29
+ begin
30
+ value = block.call
31
+
32
+ @mutex.synchronize {
33
+ @at = Time.now
34
+ @value = value
35
+ @old = false
36
+ @exception = nil
37
+ }
38
+ rescue Restart
39
+ next
40
+ rescue Exception => e
41
+ @mutex.synchronize {
42
+ @at = Time.now
43
+ @exception = e
44
+ }
45
+
46
+ break if e.is_a? Cancel
47
+ end
48
+
49
+ cond.broadcast if cond?
50
+
51
+ begin
52
+ sleep @every
53
+ rescue Restart
54
+ next
55
+ rescue Cancel => e
56
+ @mutex.synchronize {
57
+ @at = Time.now
58
+ @exception = e
59
+ }
60
+
61
+ break
62
+ end
63
+ end
64
+ }
65
+
66
+ ObjectSpace.define_finalizer self, self.class.finalizer(@thread)
67
+ end
68
+
69
+ # @private
70
+ def self.finalizer (thread)
71
+ proc {
72
+ thread.raise Cancel.new
73
+ }
74
+ end
75
+
76
+ # Change the number of seconds between each call.
77
+ def every (seconds)
78
+ @every = seconds
79
+
80
+ restart
81
+ end
82
+
83
+ # Cancel the every, {#value} will yield a Cancel exception.
84
+ def cancel
85
+ @mutex.synchronize {
86
+ @thread.raise Cancel.new('every cancelled')
87
+ }
88
+
89
+ self
90
+ end
91
+
92
+ # Check if the every has been cancelled.
93
+ def cancelled?
94
+ @mutex.synchronize {
95
+ @exception.is_a? Cancel
96
+ }
97
+ end
98
+
99
+ # Checks when the every was cancelled.
100
+ def cancelled_at
101
+ if cancelled?
102
+ @mutex.synchronize {
103
+ @at
104
+ }
105
+ end
106
+ end
107
+
108
+ # Restart the every.
109
+ def restart
110
+ @mutex.synchronize {
111
+ @thread.raise Restart.new
112
+ }
113
+
114
+ self
115
+ end
116
+
117
+ # Check if the every is running.
118
+ def running?
119
+ !cancelled?
120
+ end
121
+
122
+ # Check if the every is old, after the first #value call it becomes old,
123
+ # until another run of the block is gone)
124
+ def old?
125
+ @mutex.synchronize {
126
+ @old
127
+ }
128
+ end
129
+
130
+ # Gets the Time when the block was called.
131
+ def called_at
132
+ @mutex.synchronize {
133
+ @at
134
+ }
135
+ end
136
+
137
+ # Gets how many seconds are missing before another call.
138
+ def next_in
139
+ return if cancelled?
140
+
141
+ @mutex.synchronize {
142
+ @every - (Time.now - @at)
143
+ }
144
+ end
145
+
146
+ # Gets the current every value.
147
+ def value (timeout = nil)
148
+ @mutex.synchronize {
149
+ if @old
150
+ cond.wait(@mutex, *timeout)
151
+ end
152
+
153
+ @old = true
154
+
155
+ if @exception
156
+ raise @exception
157
+ else
158
+ @value
159
+ end
160
+ }
161
+ end
162
+
163
+ alias ~ value
164
+
165
+ # Gets the current every value, without blocking and waiting for the next
166
+ # call.
167
+ def value!
168
+ @mutex.synchronize {
169
+ @old = true
170
+
171
+ @value unless @exception
172
+ }
173
+ end
174
+
175
+ private
176
+ def cond?
177
+ instance_variable_defined? :@cond
178
+ end
179
+
180
+ def cond
181
+ @cond ||= ConditionVariable.new
182
+ end
183
+ end
184
+
185
+ class Thread
186
+ # Helper to create an every
187
+ def self.every (every, &block)
188
+ Thread::Every.new(every, &block)
189
+ end
190
+ end
191
+
192
+ module Kernel
193
+ # Helper to create an every
194
+ def every (every, &block)
195
+ Thread::Every.new(every, &block)
196
+ end
197
+ end
data/lib/thread/future.rb CHANGED
@@ -33,6 +33,15 @@ class Thread::Future
33
33
  }
34
34
 
35
35
  @thread = pool ? pool.process(&task) : Thread.new(&task)
36
+
37
+ ObjectSpace.define_finalizer self, self.class.finalizer(@thread)
38
+ end
39
+
40
+ # @private
41
+ def self.finalizer (thread)
42
+ proc {
43
+ thread.raise Cancel.new
44
+ }
36
45
  end
37
46
 
38
47
  # Check if an exception has been raised.
@@ -60,11 +69,13 @@ class Thread::Future
60
69
 
61
70
  # Cancel the future, {#value} will yield a Cancel exception
62
71
  def cancel
63
- return if delivered?
72
+ return self if delivered?
64
73
 
65
74
  @mutex.synchronize {
66
75
  @thread.raise Cancel.new('future cancelled')
67
76
  }
77
+
78
+ self
68
79
  end
69
80
 
70
81
  # Check if the future has been cancelled
data/lib/thread/pipe.rb CHANGED
@@ -60,11 +60,11 @@ class Thread::Pipe
60
60
  @input = input
61
61
  @output = output
62
62
 
63
- ObjectSpace.define_finalizer(self, self.class.finalize(@tasks))
63
+ ObjectSpace.define_finalizer self, self.class.finalizer(@tasks)
64
64
  end
65
65
 
66
66
  # @private
67
- def self.finalize (tasks)
67
+ def self.finalizer (tasks)
68
68
  proc {
69
69
  tasks.each(&:kill)
70
70
  }
@@ -28,7 +28,7 @@ class Thread::Promise
28
28
 
29
29
  # Deliver a value.
30
30
  def deliver (value)
31
- return if delivered?
31
+ return self if delivered?
32
32
 
33
33
  @mutex.synchronize {
34
34
  @value = value
@@ -0,0 +1,11 @@
1
+ #! /usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'thread/every'
4
+
5
+ describe Thread::Every do
6
+ it 'delivers a value properly' do
7
+ e = Thread.every(5) { sleep 0.5; 42 }
8
+
9
+ e.value.should == 42
10
+ end
11
+ end
data/thread.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new {|s|
2
2
  s.name = 'thread'
3
- s.version = '0.0.7'
3
+ s.version = '0.0.8'
4
4
  s.author = 'meh.'
5
5
  s.email = 'meh@schizofreni.co'
6
6
  s.homepage = 'http://github.com/meh/ruby-thread'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thread
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - meh.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-04-24 00:00:00.000000000 Z
11
+ date: 2013-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -50,6 +50,7 @@ files:
50
50
  - Rakefile
51
51
  - lib/thread/channel.rb
52
52
  - lib/thread/delay.rb
53
+ - lib/thread/every.rb
53
54
  - lib/thread/future.rb
54
55
  - lib/thread/pipe.rb
55
56
  - lib/thread/pool.rb
@@ -58,6 +59,7 @@ files:
58
59
  - lib/thread/recursive_mutex.rb
59
60
  - tests/channel_spec.rb
60
61
  - tests/delay_spec.rb
62
+ - tests/every_spec.rb
61
63
  - tests/future_spec.rb
62
64
  - tests/pipe_spec.rb
63
65
  - tests/promise_spec.rb