splib 1.3 → 1.4

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