thread 0.0.7 → 0.0.8

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