atomic 0.0.1

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.
@@ -0,0 +1,33 @@
1
+ atomic: An atomic reference implementation for JRuby and green or GIL-threaded
2
+ Ruby implementations (MRI 1.8/1.9, Rubinius)
3
+
4
+ == Summary ==
5
+
6
+ This library provides:
7
+
8
+ * an Atomic class that guarantees atomic updates to its contained value
9
+
10
+ The Atomic class provides accessors for the contained "value" plus two update
11
+ methods:
12
+
13
+ * update will run the provided block, passing the current value and replacing
14
+ it with the block result iff the value has not been changed in the mean time.
15
+ It may run the block repeatedly if there are other concurrent updates in
16
+ progress.
17
+ * try_update will run the provided block, passing the current value and
18
+ replacing it with the block result. If the value changes before the update
19
+ can happen, it will throw Atomic::ConcurrentUpdateError.
20
+
21
+ The atomic repository is at http://github.com/headius/ruby-atomic.
22
+
23
+ == Usage ==
24
+
25
+ require 'atomic'
26
+
27
+ my_atomic = Atomic.new(0)
28
+ my_atomic.update {|v| v + 1}
29
+ begin
30
+ my_atomic.try_update {|v| v + 1}
31
+ rescue Atomic::ConcurrentUpdateError => cue
32
+ # deal with it (retry, propagate, etc)
33
+ end
@@ -0,0 +1,10 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ task :default => :test
5
+
6
+ desc "Run tests"
7
+ Rake::TestTask.new :test do |t|
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/*.rb"]
10
+ end
@@ -0,0 +1,15 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{atomic}
5
+ s.version = "0.0.1"
6
+ s.authors = ["Charles Oliver Nutter", "MenTaLguY"]
7
+ s.date = Time.now.strftime('YYYY-MM-DD')
8
+ s.description = "An atomic reference implementation for JRuby and green or GIL-threaded impls"
9
+ s.email = ["headius@headius.com", "mental@rydia.net"]
10
+ s.files = Dir['{lib,examples,test}/**/*'] + Dir['{*.txt,*.gemspec,Rakefile}']
11
+ s.homepage = "http://github.com/headius/ruby-atomic"
12
+ s.require_paths = ["lib"]
13
+ s.summary = "An atomic reference implementation for JRuby and green or GIL-threaded impls"
14
+ s.test_files = Dir["test/test*.rb"]
15
+ end
@@ -0,0 +1,12 @@
1
+ require 'atomic'
2
+
3
+ my_atomic = Atomic.new(0)
4
+ my_atomic.update {|v| v + 1}
5
+ puts "new value: #{my_atomic.value}"
6
+
7
+ begin
8
+ my_atomic.try_update {|v| v + 1}
9
+ rescue Atomic::ConcurrentUpdateError => cue
10
+ # deal with it (retry, propagate, etc)
11
+ end
12
+ puts "new value: #{my_atomic.value}"
@@ -0,0 +1,79 @@
1
+ base_atomic = Class.new do
2
+ class ConcurrentUpdateError < ThreadError
3
+ end
4
+
5
+ def initialize(value=nil)
6
+ @ref = InternalReference.new(value)
7
+ end
8
+
9
+ def value
10
+ @ref.get
11
+ end
12
+
13
+ def value=(new_value)
14
+ @ref.set(new_value)
15
+ new_value
16
+ end
17
+
18
+ # Pass the current value to the given block, replacing it
19
+ # with the block's result. May retry if the value changes
20
+ # during the block's execution.
21
+ def update
22
+ begin
23
+ try_update { |v| yield v }
24
+ rescue ConcurrentUpdateError
25
+ retry
26
+ end
27
+ end
28
+
29
+ def try_update
30
+ old_value = @ref.get
31
+ new_value = yield old_value
32
+ unless @ref.compare_and_set(old_value, new_value)
33
+ raise ConcurrentUpdateError, "Update failed"
34
+ end
35
+ old_value
36
+ end
37
+ end
38
+
39
+ if defined? RUBY_ENGINE && RUBY_ENGINE == "jruby"
40
+ require 'java'
41
+ Atomic = Class.new(base_atomic) do
42
+ InternalReference = java.util.concurrent.atomic.AtomicReference
43
+ end
44
+ else
45
+ Atomic = Class.new(base_atomic) do
46
+ class InternalReference
47
+ attr_accessor :value
48
+ alias_method :get, :value
49
+ alias_method :set, :value=
50
+
51
+ def initialize(value)
52
+ @value = value
53
+ end
54
+
55
+ def compare_and_set(old_value, new_value)
56
+ _exclusive do
57
+ return false unless @value.equal? old_value
58
+ @value = new_value
59
+ end
60
+ true
61
+ end
62
+
63
+ HAS_EXCLUSIVE = defined? Thread.exclusive
64
+ def _exclusive
65
+ if HAS_EXCLUSIVE
66
+ Thread.exclusive {yield}
67
+ else
68
+ begin
69
+ Thread.critical = true
70
+ yield
71
+ ensure
72
+ Thread.critical = false
73
+ end
74
+ end
75
+ end
76
+ private :_exclusive
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,35 @@
1
+ require 'test/unit'
2
+ require 'atomic'
3
+
4
+ class TestAtomic < Test::Unit::TestCase
5
+ def test_construct
6
+ atomic = Atomic.new
7
+ assert_equal nil, atomic.value
8
+
9
+ atomic = Atomic.new(0)
10
+ assert_equal 0, atomic.value
11
+ end
12
+
13
+ def test_value
14
+ atomic = Atomic.new(0)
15
+ atomic.value = 1
16
+
17
+ assert_equal 1, atomic.value
18
+ end
19
+
20
+ def test_update
21
+ atomic = Atomic.new(0)
22
+ atomic.update {|v| v + 1}
23
+
24
+ assert_equal 1, atomic.value
25
+ end
26
+
27
+ def test_try_update
28
+ atomic = Atomic.new(0)
29
+ atomic.try_update {|v| v + 1}
30
+
31
+ assert_equal 1, atomic.value
32
+ end
33
+
34
+ # TODO: Test the ConcurrentUpdateError cases
35
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: atomic
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Charles Oliver Nutter
13
+ - MenTaLguY
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-06-08 00:03:10.533000 -04:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: An atomic reference implementation for JRuby and green or GIL-threaded impls
23
+ email:
24
+ - headius@headius.com
25
+ - mental@rydia.net
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files: []
31
+
32
+ files:
33
+ - lib/atomic.rb
34
+ - examples/atomic_example.rb
35
+ - test/test_atomic.rb
36
+ - README.txt
37
+ - atomic.gemspec
38
+ - Rakefile
39
+ has_rdoc: true
40
+ homepage: http://github.com/headius/ruby-atomic
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options: []
45
+
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 0
55
+ version: "0"
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ requirements: []
65
+
66
+ rubyforge_project:
67
+ rubygems_version: 1.3.7
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: An atomic reference implementation for JRuby and green or GIL-threaded impls
71
+ test_files:
72
+ - test/test_atomic.rb