Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
121 commits
Select commit Hold shift + click to select a range
76f8137
First rev of Atomic for MRI and JRuby.
headius Jun 8, 2010
d94363f
Yak-shaving for release, plus impl fixes to work properly on 1.8 or 1…
headius Jun 8, 2010
87091a4
simplify (yay for late binding)
Jun 8, 2010
0e439ec
expand tests a bit
Jun 8, 2010
ac08f56
move thread require to top
Jun 8, 2010
5de52ed
return the new value from update, rather than the old one
Jun 8, 2010
0f1b4b6
add Atomic#swap
Jun 8, 2010
6446bf0
Additional minor tweak: require 'thread' regardless of impl. Update t…
headius Jun 8, 2010
186fb3c
New version for JRuby that uses a real extension for its InternalRefe…
headius Jun 8, 2010
ef59b6c
full portability
Jun 9, 2010
44df3ce
C extension for MRI/1.9
Jun 9, 2010
f53b928
Add ext dir for Java stuff.
headius Jun 9, 2010
ecb44fe
Make try_update nonblocking using Mutex#try_lock in the default Inter…
headius Jun 9, 2010
a9e1a03
initialize cInternalReference
Jan 26, 2011
617c378
nodoc InternalReference
Jan 26, 2011
93975d8
Bump to 0.0.4 for release. Fixes #2.
headius Mar 10, 2011
6cb3222
Corrections to gemspec
kim Jul 1, 2011
2198442
Fix rb_mark => rb_gc_mark
kim Jul 1, 2011
606cacd
Experiment with system CAS operations to make ir_compare_and_set real…
kim Jul 1, 2011
2c5b731
Merge pull request #4 from kim/master
headius Jul 5, 2011
0c7896b
Bump version.
headius Jul 5, 2011
18bb1ba
Added simple benchmarks
Aug 15, 2011
bcee6ec
Merge pull request #5 from zimbatm/master
headius Aug 15, 2011
755065a
Parallel benchmark added
Sep 6, 2011
f35615b
Merge pull request #6 from zimbatm/master
headius Sep 6, 2011
66b2310
Perf improvements for CAS operations.
headius Sep 6, 2011
c609f35
Move benchmark to examples/
headius Sep 6, 2011
4d76b32
Update to version 0.0.6.
headius Sep 6, 2011
8171865
Split gem into -java and normal versions, so JRuby doesn't attempt to…
headius Sep 6, 2011
3477f07
More benchmark tools
Sep 9, 2011
74320cc
Merge pull request #7 from zimbatm/master
headius Sep 12, 2011
2db4ad7
Update README with more examples and recommend light blocks for #upda…
headius Sep 12, 2011
aa4b746
Use AtomicReferenceFieldUpdater, rather than creating a whole other o…
headius Nov 29, 2011
0f34f25
Update to 0.0.7.
headius Nov 29, 2011
2864e0c
Support Rubinius.
headius Nov 30, 2011
1d4d3c8
Update to 0.0.8 with support for Rubinius.
headius Nov 30, 2011
aa4d547
Modifications to support building on Windows. Fixes #8.
headius Dec 3, 2011
2dc992a
Bump version to 0.0.9.
headius Dec 3, 2011
a39a90e
Fix Atomic::InternalReference allocation
eric Feb 2, 2012
04e297d
Merge pull request #12 from eric/fix-internal-reference-alloc
headius Feb 2, 2012
2e284b1
Bump to 1.0.0.
headius Feb 2, 2012
bb0cee9
Update README.md
headius Mar 22, 2012
b141683
Add Apache-2.0 license file.
headius Apr 26, 2012
643e0cb
Make warning only in verbose mode.
headius Apr 26, 2012
d998fe8
Add license headers and fix gemspec to include all files.
headius Mar 29, 2013
5d176ab
Add jar to gitignore.
headius Mar 29, 2013
aa0b90c
Bump version to 0.0.2.
headius Mar 29, 2013
07a161d
Make JRuby version of Atomic more efficient.
headius Apr 4, 2013
f8f10cc
Reformat in GNU/MRI style.
headius Apr 4, 2013
fde37d8
More reorg plus efficient impls for Rubinius and MRI.
headius Apr 4, 2013
842a416
Bump version to 1.1.0.
headius Apr 4, 2013
bb781a5
Grr.
headius Apr 4, 2013
3dd9f9c
Add travis config.
headius Apr 4, 2013
a02f023
Add some ignores.
headius Apr 4, 2013
1d74992
Fixes to get tests working on travis.
headius Apr 4, 2013
4c70069
Update readme: rbx is not gil-threaded, JDK8 needed to build.
headius Apr 4, 2013
cd80d7a
Disable JRuby builds temporarily since we need JDK8 to build.
headius Apr 4, 2013
1b68767
Fix JRUBYREFERENCE8_ALLOCATOR
funny-falcon Apr 5, 2013
dc327eb
Merge pull request #16 from funny-falcon/patch-1
headius Apr 5, 2013
aa24d4d
Bump version to 1.1.1.
headius Apr 5, 2013
6aeb053
Add @funny-falcon to authors.
headius Apr 5, 2013
2c5ab6c
Include README and oneline logs in gem description.
headius Apr 5, 2013
f519385
Attempting to get description to look nice on rubygems.org.
headius Apr 5, 2013
58d3e34
Convert README to rdoc and try again.
headius Apr 5, 2013
b8858f9
More formatting for description.
headius Apr 5, 2013
e269463
Fix #15 by explicitly testing for GCC's CAS.
headius Apr 6, 2013
1b1c081
Bump to 1.1.6 for botched 1.1.5 release.
headius Apr 6, 2013
7d0ade6
Changing the arch to native, to make it successfully compile using mingw
Apr 11, 2013
14fc4a9
Removed compiled gem from src
Apr 11, 2013
9b58cf0
Merge pull request #20 from lazyspark/master
headius Apr 11, 2013
fa74e58
Bump version to 1.1.7.
headius Apr 11, 2013
073b4c1
Partial fix for numeric idempotence differences across Rubies.
headius Apr 15, 2013
0749145
Add pkg/ and *.gem to gitignore.
headius Apr 15, 2013
e59e92b
Add CAS tests for more numeric types.
headius Apr 15, 2013
6c2ce92
Fix #21 by moving win32 CFLAGS tweak above other test compiles.
headius Apr 16, 2013
c291231
Allow forcing fallback impl.
headius Apr 16, 2013
b6398e5
Add some missing license headers.
headius Apr 16, 2013
40eca8e
Make test work under 1.8-compat.
headius Apr 16, 2013
ed84820
Add numeric CAS logic for fallback, MRI, and Rubinius.
headius Apr 16, 2013
6869b89
Version 1.1.8.
headius Apr 16, 2013
e8d43f1
Limit gem description to just commit log.
headius Apr 16, 2013
0b1cd2d
Add license to gemspec.
headius Apr 16, 2013
86f3961
Revert "Convert README to rdoc and try again."
headius May 6, 2013
e9f1430
Revert description changes (damn you, RubyGems.org!). Fixes #22
headius May 6, 2013
d371a8b
Use -march=native on Solaris as well. Fixes #23.
headius Jun 26, 2013
d1a97cb
Bump version to 1.1.10.
headius Jun 26, 2013
ad690f7
Set march appropriately on RHEL5 32bit
rainhead Jul 11, 2013
d21837c
Merge pull request #26 from rainhead/master
headius Aug 2, 2013
ecea56d
Fix -march-i686 not supported in Ubuntu 12.04 LTS
Eric-Guo Aug 3, 2013
585986f
Merge pull request #27 from Eric-Guo/patch-1
headius Aug 3, 2013
24a68f3
Fix references to removed Unsafe stuff in JRuby and bump to 1.1.11
headius Aug 3, 2013
74502f1
Bump to 1.1.12.
headius Aug 3, 2013
6ee28c3
Copy relevant UnsafeHolder logic so it works across all JRubies.
headius Aug 14, 2013
ba2cd36
Bump version to 1.1.13.
headius Aug 14, 2013
07d1145
Adding Solaris support for atomic operations based on the comment at:
orderthruchaos Sep 9, 2013
457f31d
Merge pull request #31 from orderthruchaos/master
headius Sep 9, 2013
e7813e4
Bump version to 1.1.14.
headius Sep 11, 2013
1945844
Format Ruby code
headius Sep 15, 2013
f3b2cc6
Fix typo and grammar nits.
havenwood Oct 22, 2013
b48a8d0
Merge pull request #33 from havenwood/readme
headius Oct 28, 2013
ebc351b
attempt compilation using gcc instead of throwing error
soorajb Nov 28, 2013
9f8896c
include libkern/OSAtomic if available
tenderlove Jan 11, 2014
3c4861f
mswin-support
unak Feb 4, 2014
5a110d0
Merge pull request #35 from soorajb/patch-1
headius Feb 26, 2014
0b7a8eb
Merge pull request #37 from tenderlove/compile
headius Feb 26, 2014
60d2041
Merge branch 'mswin-support' of github.com:unak/ruby-atomic into unak…
headius Feb 26, 2014
4f97134
Add Gemfile to get appropriate dependencies installed.
headius Feb 26, 2014
b60856a
Fix rbx reference in travis build.
headius Feb 26, 2014
53610b7
Reenable JRuby builds.
headius Feb 26, 2014
b7485bb
Fix compile task on JRuby.
headius Feb 26, 2014
c096362
Update version to 1.1.15.
headius Feb 26, 2014
4d3040f
Allow GCC to be detected via CONFIG["CC"].
orderthruchaos Mar 5, 2014
3f76898
Ignore vim swap files.
orderthruchaos Mar 5, 2014
63107c0
Add travis badge
headius Mar 17, 2014
055d800
Merge pull request #41 from orderthruchaos/master
headius Mar 17, 2014
ba672de
Bump version to 1.1.16.
headius Mar 17, 2014
d780eec
Update test suite to Minitest 5
Apr 10, 2014
3cd3b43
Merge pull request #48 from strzibny/master
headius Apr 10, 2014
e3eb4e9
Add 'ruby-atomic/' from commit '3cd3b43cc110deef5d7057c06107f568666b7…
jdantonio May 30, 2014
49bbaec
Merged ruby-atomic gem.
jdantonio May 30, 2014
4f84b08
Fixed Rubinius bug
jdantonio May 30, 2014
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
Gemfile.lock
tests.txt
*.gem
.rvmrc
.ruby-version
Expand All @@ -21,9 +20,12 @@ coverage
.DS_Store
TAGS
tmtags
*.swo
*.swp
*.sw?
.idea
.rbx/*
*.py
*.pyc
lib/*.jar
ext/*.bundle
ext/*.so
ext/*.jar
pkg
*.gem
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ source 'https://rubygems.org'

gemspec


group :development do
gem 'rake', '~> 10.2.2'
gem 'countloc', '~> 0.4.0', platforms: :mri
gem 'yard', '~> 0.8.7.4'
gem 'inch', '~> 0.4.1', platforms: :mri
gem 'rake-compiler', '~> 0.9.2', platforms: [:mri, :mswin, :mingw]
end

group :testing do
Expand Down
68 changes: 62 additions & 6 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
$:.push File.join(File.dirname(__FILE__), 'lib')
$:.push File.join(File.dirname(__FILE__), 'tasks/support')

require 'rubygems'
require 'rake'
require 'bundler/gem_tasks'
require 'rspec'
require 'rspec/core/rake_task'

require 'concurrent'
require_relative 'lib/extension_helper'

Bundler::GemHelper.install_tasks

Expand All @@ -16,8 +13,67 @@ Dir.glob('tasks/**/*.rake').each do|rakefile|
load rakefile
end

desc "Run benchmarks"
task :bench do
exec "ruby -Ilib -Iext examples/bench_atomic.rb"
end

if defined?(JRUBY_VERSION)
require 'ant'

EXTENSION_NAME = 'concurrent_jruby'

directory "pkg/classes"

desc "Clean up build artifacts"
task :clean do
rm_rf "pkg/classes"
rm_rf "lib/#{EXTENSION_NAME}.jar"
end

desc "Compile the extension"
task :compile_java => "pkg/classes" do |t|
ant.javac :srcdir => "ext", :destdir => t.prerequisites.first,
:source => "1.5", :target => "1.5", :debug => true,
:classpath => "${java.class.path}:${sun.boot.class.path}"
end

desc "Build the jar"
task :jar => :compile_java do
ant.jar :basedir => "pkg/classes", :destfile => "lib/#{EXTENSION_NAME}.jar", :includes => "**/*.class"
end

task :compile => :jar

elsif use_c_extensions?

EXTENSION_NAME = 'concurrent_cruby'

require 'rake/extensiontask'

CLEAN.include Rake::FileList['**/*.so', '**/*.bundle', '**/*.o', '**/mkmf.log', '**/Makefile']

spec = Gem::Specification.load('concurrent-ruby.gemspec')
Rake::ExtensionTask.new(EXTENSION_NAME, spec) do |ext|
ext.ext_dir = 'ext'
ext.name = EXTENSION_NAME
ext.source_pattern = "**/*.{h,c,cpp}"
end

desc 'Clean, compile, and build the extension from scratch'
task :compile_c => [ :clean, :compile ]

task :irb => [:compile] do
sh "irb -r ./lib/#{EXTENSION_NAME}.bundle -I #{File.join(File.dirname(__FILE__), 'lib')}"
end
end

RSpec::Core::RakeTask.new(:travis_spec) do |t|
t.rspec_opts = '--tag ~@not_on_travis'
end

task :default => [:travis_spec]
if use_c_extensions?
task :default => [:compile_c, :travis_spec]
else
task :default => [:travis_spec]
end
7 changes: 7 additions & 0 deletions concurrent-ruby.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,12 @@ Gem::Specification.new do |s|
s.extra_rdoc_files = Dir['README*', 'LICENSE*', 'CHANGELOG*']
s.require_paths = ['lib']

if defined?(JRUBY_VERSION)
s.files = Dir['lib/concurrent_jruby.jar']
s.platform = 'java'
else
s.extensions = 'ext/extconf.rb'
end

s.required_ruby_version = '>= 1.9.3'
end
12 changes: 12 additions & 0 deletions examples/atomic_example.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require 'concurrent'

my_atomic = Concurrent::Atomic.new(0)
my_atomic.update {|v| v + 1}
puts "new value: #{my_atomic.value}"

begin
my_atomic.try_update {|v| v + 1}
rescue Concurrent::Atomic::ConcurrentUpdateError => cue
# deal with it (retry, propagate, etc)
end
puts "new value: #{my_atomic.value}"
109 changes: 109 additions & 0 deletions examples/bench_atomic.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
require 'benchmark'
require 'concurrent'
require 'thread'
Thread.abort_on_exception = true

$go = false # for synchronizing parallel threads

# number of updates on the value
N = ARGV[1] ? ARGV[1].to_i : 100_000

# number of threads for parallel test
M = ARGV[0] ? ARGV[0].to_i : 100


puts "*** Sequential updates ***"
Benchmark.bm(10) do |x|
value = 0
x.report "no lock" do
N.times do
value += 1
end
end

@lock = Mutex.new
x.report "mutex" do
value = 0
N.times do
@lock.synchronize do
value += 1
end
end
end

@atom = Concurrent::Atomic.new(0)
x.report "atomic" do
N.times do
@atom.update{|x| x += 1}
end
end
end

def para_setup(num_threads, count, &block)
if num_threads % 2 > 0
raise ArgumentError, "num_threads must be a multiple of two"
end
raise ArgumentError, "need block" unless block_given?

# Keep those threads together
tg = ThreadGroup.new

num_threads.times do |i|
diff = (i % 2 == 0) ? 1 : -1

t = Thread.new do
nil until $go
count.times do
yield diff
end
end

tg.add(t)
end

# Make sure all threads are started
while tg.list.find{|t| t.status != "run"}
Thread.pass
end

# For good measure
GC.start

tg
end

def para_run(tg)
$go = true
tg.list.each{|t| t.join}
$go = false
end

puts "*** Parallel updates ***"
Benchmark.bm(10) do |bm|
# This is not secure
value = 0
tg = para_setup(M, N/M) do |diff|
value += diff
end
bm.report("no lock"){ para_run(tg) }


value = 0
@lock = Mutex.new
tg = para_setup(M, N/M) do |diff|
@lock.synchronize do
value += diff
end
end
bm.report("mutex"){ para_run(tg) }
raise unless value == 0


@atom = Concurrent::Atomic.new(0)
tg = para_setup(M, N/M) do |diff|
@atom.update{|x| x + diff}
end
bm.report("atomic"){ para_run(tg) }
raise unless @atom.value == 0

end
138 changes: 138 additions & 0 deletions examples/bench_atomic_1.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#!/usr/bin/env ruby

$: << File.expand_path('../../lib', __FILE__)

require 'optparse'
require 'thread'
require 'benchmark'

require 'concurrent'

Thread.abort_on_exception = true

$conf = {
:lock => "atomic",
:num_threads => 100,
:count => 100_000,
:count_per_thread => nil,
:slow => nil,
}

OptionParser.new do |opts|
opts.on("-c", "--count NUM") do |n|
$conf[:count] = n.to_i
end
opts.on("-p", "--count-per-thread") do |n|
$conf[:count_per_thread] = n.to_i
end
opts.on("-t", "--num-threads NUM") do |n|
$conf[:num_threads] = n.to_i
end
opts.on("-s", "--slow NUM") do |n|
$conf[:slow] = n.to_i
end
opts.on("-l", "--lock atomic|mutex") do |x|
$conf[:lock] = x
end
opts.on("-h", "--help"){ puts opts; exit }
end.parse!(ARGV)

unless $conf[:count_per_thread]
$conf[:count_per_thread] = $conf[:count] / $conf[:num_threads]
end
$conf.delete(:count)

if $conf[:slow].to_i > 0
require 'digest/md5'
def slow_down
$conf[:slow].times do |i|
Digest::MD5.hexdigest(i.to_s)
end
end

ret = []
10.times do
m = Benchmark.measure{ slow_down }
ret << m.real
end

$conf[:slow_time] = [ret.min, ret.max]
else
def slow_down; end
end

$stderr.puts $conf.inspect

def para_prepare(&block)
num_threads = $conf[:num_threads]
count = $conf[:count_per_thread]

if num_threads % 2 > 0
raise ArgumentError, "num_threads must be a multiple of two"
end

# Keep those threads together
tg = ThreadGroup.new

num_threads.times do |i|
diff = (i % 2 == 0) ? 1 : -1

t = Thread.new do
nil until $go
count.times do
yield diff
end
end

tg.add(t)
end

# Make sure all threads are started
while tg.list.find{|t| t.status != "run"}
Thread.pass
end

# For good measure
GC.start

$go = false

tg
end



$tg = nil
if $conf[:lock] == "atomic"
$atom = Concurrent::Atomic.new(0)
$tg = para_prepare do |diff|
$atom.update do |x|
slow_down
x + diff
end
end
else
$lock = Mutex.new
$value = 0
$tg = para_prepare do |diff|
$lock.synchronize do
slow_down
$value += diff
end
end
end


# Run !
#
# NOTE: It seems to me that this measurement method
# is sensible to how the system dispatches his resources.
#
# More precise caluclation could be done using
# getrusage's times
ret = Benchmark.measure do
$go = true
$tg.list.each{|t| t.join}
$go = false
end
puts ret.real
Loading