splib 1.3 → 1.4

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,8 @@
1
+ 1.4
2
+ * Clean up exclusive usage in Monitor
3
+ * Add a timeout on Monitor#wait
4
+ * Add Monitor#locked?
5
+ * Add Float library to define Float#within_delta?
1
6
  1.3
2
7
  * Add simple monitor
3
8
  1.2
data/lib/splib.rb CHANGED
@@ -4,6 +4,7 @@ module Splib
4
4
  :Constants,
5
5
  :Conversions,
6
6
  :Exec,
7
+ :Float,
7
8
  :HumanIdealRandomIterator,
8
9
  :Monitor,
9
10
  :PriorityQueue,
@@ -0,0 +1,18 @@
1
+ module Splib
2
+ # While not a big fan of monkeypatching, I want to be
3
+ # lazy getting to this
4
+ class ::Float
5
+ def within_delta?(args={})
6
+ raise ArgumentError.new('Missing required argument: :expected') unless args[:expected]
7
+ raise ArgumentError.new('Missing required argument: :delta') unless args[:delta]
8
+ e = args[:expected].to_f
9
+ d = args[:delta].to_f
10
+ mult = 0
11
+ if(pos = d.to_s.index('.'))
12
+ mult = (d.to_s.length - (pos + 1))
13
+ end
14
+ mult = 10 ** mult
15
+ ((e*mult) - (self*mult)).abs <= (d*mult)
16
+ end
17
+ end
18
+ end
data/lib/splib/Monitor.rb CHANGED
@@ -7,12 +7,27 @@ module Splib
7
7
  @threads = []
8
8
  @locks = []
9
9
  @lock_owner = nil
10
+ @timers = {}
10
11
  end
11
12
  # timeout:: Wait for given amount of time
12
13
  # Park a thread here
13
14
  def wait(timeout=nil)
15
+ if(timeout)
16
+ timout = timeout.to_f
17
+ @timers[Thread.current] = Thread.new(Thread.current) do |t|
18
+ sleep(timeout)
19
+ t.wakeup
20
+ end
21
+ end
14
22
  @threads << Thread.current
15
23
  Thread.stop
24
+ @threads.delete(Thread.current)
25
+ if(timeout)
26
+ if(@timers[Thread.current].alive?)
27
+ @timers[Thread.current].kill
28
+ end
29
+ @timers.delete(Thread.current)
30
+ end
16
31
  true
17
32
  end
18
33
  # Park thread while block is true
@@ -29,19 +44,19 @@ module Splib
29
44
  end
30
45
  # Wake up earliest thread
31
46
  def signal
32
- lock
33
- t = @threads.shift
34
- t.wakeup if t.alive?
35
- unlock
47
+ synchronize do
48
+ t = @threads.shift
49
+ t.wakeup if t && t.alive?
50
+ end
36
51
  end
37
52
  # Wake up all threads
38
53
  def broadcast
39
- lock
40
- @threads.each do |t|
41
- t.wakeup if t.alive?
54
+ synchronize do
55
+ @threads.each do |t|
56
+ t.wakeup if t.alive?
57
+ end
58
+ @threads.clear
42
59
  end
43
- @threads.clear
44
- unlock
45
60
  end
46
61
  # Number of threads waiting
47
62
  def waiters
@@ -49,38 +64,51 @@ module Splib
49
64
  end
50
65
  # Lock the monitor
51
66
  def lock
52
- stop = false
53
- Thread.exclusive do
54
- unless(@locks.empty?)
55
- @locks << Thread.current
56
- stop = true
57
- else
58
- @lock_owner = Thread.current
59
- end
60
- end
61
- Thread.stop if stop
67
+ Thread.stop if Thread.exclusive{ do_lock }
62
68
  end
63
69
  # Unlock the monitor
64
70
  def unlock
65
- unless(@lock_owner == Thread.current)
66
- raise ThreadError.new("Not owner attepmting to unlock monitor")
67
- else
68
- Thread.exclusive do
69
- unless(@locks.empty?)
70
- @locks.delete{|t|!t.alive?}
71
- @lock_owner = @locks.shift
72
- @lock_owner.wakeup
73
- else
74
- @lock_owner = nil
75
- end
76
- end
77
- end
71
+ Thread.exclusive{ do_unlock }
72
+ end
73
+ # Is monitor locked
74
+ def locked?
75
+ @locks.size > 0
78
76
  end
79
77
  # Lock the monitor, execute block and unlock the monitor
80
78
  def synchronize
81
- lock
82
- yield
83
- unlock
79
+ result = nil
80
+ Thread.exclusive do
81
+ do_lock
82
+ result = yield
83
+ do_unlock
84
+ end
85
+ result
86
+ end
87
+
88
+ private
89
+
90
+ def do_lock
91
+ stop = false
92
+ unless(@locks.empty?)
93
+ @locks << Thread.current
94
+ stop = true
95
+ else
96
+ @lock_owner = Thread.current
97
+ end
98
+ stop
99
+ end
100
+
101
+ def do_unlock
102
+ unless(@lock_owner == Thread.current)
103
+ raise ThreadError.new("Thread #{Thread.current} is not the current owner: #{@lock_owner}")
104
+ end
105
+ unless(@locks.empty?)
106
+ @locks.delete{|t|!t.alive?}
107
+ @lock_owner = @locks.shift
108
+ @lock_owner.wakeup
109
+ else
110
+ @lock_owner = nil
111
+ end
84
112
  end
85
113
  end
86
114
  end
data/splib.gemspec CHANGED
@@ -2,7 +2,7 @@ spec = Gem::Specification.new do |s|
2
2
  s.name = 'splib'
3
3
  s.author = 'spox'
4
4
  s.email = 'spox@modspox.com'
5
- s.version = '1.3'
5
+ s.version = '1.4'
6
6
  s.summary = 'Spox Library'
7
7
  s.platform = Gem::Platform::RUBY
8
8
  s.files = Dir['**/*']
@@ -0,0 +1,20 @@
1
+ require 'splib'
2
+ require 'test/unit'
3
+
4
+ class FloatTest < Test::Unit::TestCase
5
+ def setup
6
+ Splib.load :Float
7
+ end
8
+
9
+ def test_delta
10
+ t = 3.2
11
+ assert(3.204.within_delta?(:expected => t, :delta => 0.1))
12
+ assert(3.3.within_delta?(:expected => t, :delta => 0.1))
13
+ assert(3.3.within_delta?(:expected => t, :delta => 0.1))
14
+ assert(3.1.within_delta?(:expected => t, :delta => 0.1))
15
+ assert(!(3.09.within_delta?(:expected => t, :delta => 0.1)))
16
+ assert(!(3.31.within_delta?(:expected => t, :delta => 0.1)))
17
+ assert(3.0.within_delta?(:expected => 4, :delta => 1))
18
+ assert(!(3.0.within_delta?(:expected => 5, :delta => 1)))
19
+ end
20
+ end
@@ -17,6 +17,20 @@ class MonitorTest < Test::Unit::TestCase
17
17
  end
18
18
  end
19
19
 
20
+ def test_wait_timeout
21
+ t = []
22
+ o = []
23
+ 5.times{|i| t << Thread.new{ @monitor.wait((i+1)/100.0); o << 1 } }
24
+ sleep(0.015)
25
+ assert(!t.shift.alive?)
26
+ assert_equal(1, o.size)
27
+ sleep(0.11)
28
+ assert_equal(5, o.size)
29
+ t.each do |th|
30
+ assert(!th.alive?)
31
+ end
32
+ end
33
+
20
34
  def test_signal
21
35
  output = []
22
36
  t = []
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: splib
3
3
  version: !ruby/object:Gem::Version
4
- version: "1.3"
4
+ version: "1.4"
5
5
  platform: ruby
6
6
  authors:
7
7
  - spox
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2010-01-12 00:00:00 -08:00
12
+ date: 2010-01-13 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -23,13 +23,12 @@ extra_rdoc_files:
23
23
  - README.rdoc
24
24
  - CHANGELOG
25
25
  files:
26
- - tests
27
- - tests/cases
28
26
  - tests/cases/Array.rb
29
27
  - tests/cases/PriorityQueue.rb
30
28
  - tests/cases/UrlShorteners.rb
31
29
  - tests/cases/Exec.rb
32
30
  - tests/cases/Constants.rb
31
+ - tests/cases/Float.rb
33
32
  - tests/cases/CodeReloader.rb
34
33
  - tests/cases/HumanIdealRandomIterator.rb
35
34
  - tests/cases/Monitor.rb
@@ -37,14 +36,13 @@ files:
37
36
  - tests/run_tests.rb
38
37
  - tests/samplecode2.rb
39
38
  - tests/samplecode1.rb
40
- - lib
41
39
  - lib/splib.rb
42
- - lib/splib
43
40
  - lib/splib/Array.rb
44
41
  - lib/splib/PriorityQueue.rb
45
42
  - lib/splib/UrlShorteners.rb
46
43
  - lib/splib/Exec.rb
47
44
  - lib/splib/Constants.rb
45
+ - lib/splib/Float.rb
48
46
  - lib/splib/CodeReloader.rb
49
47
  - lib/splib/HumanIdealRandomIterator.rb
50
48
  - lib/splib/Monitor.rb
@@ -53,8 +51,11 @@ files:
53
51
  - LICENSE
54
52
  - splib.gemspec
55
53
  - README.rdoc
56
- has_rdoc: false
54
+ - splib-1.4.gem
55
+ has_rdoc: true
57
56
  homepage: http://github.com/spox/splib
57
+ licenses: []
58
+
58
59
  post_install_message:
59
60
  rdoc_options:
60
61
  - --title
@@ -79,9 +80,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
79
80
  requirements: []
80
81
 
81
82
  rubyforge_project:
82
- rubygems_version: 1.3.1
83
+ rubygems_version: 1.3.5
83
84
  signing_key:
84
- specification_version: 2
85
+ specification_version: 3
85
86
  summary: Spox Library
86
87
  test_files: []
87
88