removed vendor files from git, readded vscode config

This commit is contained in:
Benjamin Jones 2020-03-26 09:47:36 +01:00
parent 92a9d2f0a9
commit 22adf8fe8a
2960 changed files with 0 additions and 383489 deletions

View File

@ -1,27 +0,0 @@
#!/usr/bin/env ruby
#
# This file was generated by RubyGems.
#
# The application 'jekyll' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require 'rubygems'
version = ">= 0.a"
str = ARGV.first
if str
str = str.b[/\A_(.*)_\z/, 1]
if str and Gem::Version.correct?(str)
version = str
ARGV.shift
end
end
if Gem.respond_to?(:activate_bin_path)
load Gem.activate_bin_path('jekyll', 'jekyll', version)
else
gem "jekyll", version
load Gem.bin_path("jekyll", "jekyll", version)
end

View File

@ -1,27 +0,0 @@
#!/usr/bin/env ruby
#
# This file was generated by RubyGems.
#
# The application 'kramdown' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require 'rubygems'
version = ">= 0.a"
str = ARGV.first
if str
str = str.b[/\A_(.*)_\z/, 1]
if str and Gem::Version.correct?(str)
version = str
ARGV.shift
end
end
if Gem.respond_to?(:activate_bin_path)
load Gem.activate_bin_path('kramdown', 'kramdown', version)
else
gem "kramdown", version
load Gem.bin_path("kramdown", "kramdown", version)
end

View File

@ -1,27 +0,0 @@
#!/usr/bin/env ruby
#
# This file was generated by RubyGems.
#
# The application 'listen' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require 'rubygems'
version = ">= 0.a"
str = ARGV.first
if str
str = str.b[/\A_(.*)_\z/, 1]
if str and Gem::Version.correct?(str)
version = str
ARGV.shift
end
end
if Gem.respond_to?(:activate_bin_path)
load Gem.activate_bin_path('listen', 'listen', version)
else
gem "listen", version
load Gem.bin_path("listen", "listen", version)
end

View File

@ -1,27 +0,0 @@
#!/usr/bin/env ruby
#
# This file was generated by RubyGems.
#
# The application 'rouge' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require 'rubygems'
version = ">= 0.a"
str = ARGV.first
if str
str = str.b[/\A_(.*)_\z/, 1]
if str and Gem::Version.correct?(str)
version = str
ARGV.shift
end
end
if Gem.respond_to?(:activate_bin_path)
load Gem.activate_bin_path('rouge', 'rougify', version)
else
gem "rouge", version
load Gem.bin_path("rouge", "rougify", version)
end

View File

@ -1,27 +0,0 @@
#!/usr/bin/env ruby
#
# This file was generated by RubyGems.
#
# The application 'safe_yaml' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require 'rubygems'
version = ">= 0.a"
str = ARGV.first
if str
str = str.b[/\A_(.*)_\z/, 1]
if str and Gem::Version.correct?(str)
version = str
ARGV.shift
end
end
if Gem.respond_to?(:activate_bin_path)
load Gem.activate_bin_path('safe_yaml', 'safe_yaml', version)
else
gem "safe_yaml", version
load Gem.bin_path("safe_yaml", "safe_yaml", version)
end

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,16 +0,0 @@
current directory: /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/eventmachine-1.2.7/ext/fastfilereader
/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/bin/ruby -I /Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/lib/ruby/site_ruby/2.6.0 -r ./siteconf20191020-69875-moqdwe.rb extconf.rb
creating Makefile
current directory: /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/eventmachine-1.2.7/ext/fastfilereader
make "DESTDIR=" clean
current directory: /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/eventmachine-1.2.7/ext/fastfilereader
make "DESTDIR="
compiling mapper.cpp
compiling rubymain.cpp
linking shared-object fastfilereaderext.bundle
current directory: /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/eventmachine-1.2.7/ext/fastfilereader
make "DESTDIR=" install
/usr/local/opt/coreutils/bin/ginstall -c -m 0755 fastfilereaderext.bundle ./.gem.20191020-69875-rb74yq

View File

@ -1,11 +0,0 @@
"gcc -o conftest -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/x86_64-darwin18 -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/ruby/backward -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0 -I. -I/usr/local/opt/libyaml/include -I/usr/local/opt/libksba/include -I/usr/local/opt/readline/include -I/usr/local/opt/zlib/include -I/usr/local/opt/openssl@1.1/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeclaration-after-statement -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -fno-common -pipe conftest.c -L. -L/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/zlib/lib -L/usr/local/opt/openssl@1.1/lib -L. -fstack-protector-strong -L/usr/local/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/zlib/lib -L/usr/local/opt/openssl@1.1/lib -lruby.2.6 "
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: int main(int argc, char **argv)
4: {
5: return 0;
6: }
/* end */

View File

@ -1,128 +0,0 @@
current directory: /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c
/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/bin/ruby -I /Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/lib/ruby/site_ruby/2.6.0 -r ./siteconf20191020-69875-r3jdpp.rb extconf.rb
checking for ffi.h... no
checking for ffi.h in /usr/local/include,/usr/include/ffi... no
checking for shlwapi.h... no
checking for rb_thread_call_without_gvl()... yes
checking for ruby_native_thread_p()... yes
checking for ruby_thread_has_gvl_p()... yes
creating extconf.h
creating Makefile
current directory: /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c
make "DESTDIR=" clean
current directory: /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c
make "DESTDIR="
Configuring libffi
clang: error: unsupported option '-print-multi-os-directory'
clang: error: no input files
cd "/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi-x86_64-darwin18" && /Applications/Xcode.app/Contents/Developer/usr/bin/make
/Applications/Xcode.app/Contents/Developer/usr/bin/make 'AR_FLAGS=' 'CC_FOR_BUILD=' 'CFLAGS=-Wall -fexceptions' 'CXXFLAGS=-g -O2' 'CFLAGS_FOR_BUILD=' 'CFLAGS_FOR_TARGET=' 'INSTALL=/usr/local/bin/ginstall -c' 'INSTALL_DATA=/usr/local/bin/ginstall -c -m 644' 'INSTALL_PROGRAM=/usr/local/bin/ginstall -c' 'INSTALL_SCRIPT=/usr/local/bin/ginstall -c' 'JC1FLAGS=' 'LDFLAGS=' 'LIBCFLAGS=' 'LIBCFLAGS_FOR_TARGET=' 'MAKE=/Applications/Xcode.app/Contents/Developer/usr/bin/make' 'MAKEINFO=/bin/sh /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/missing makeinfo ' 'PICFLAG=' 'PICFLAG_FOR_TARGET=' 'RUNTESTFLAGS=' 'SHELL=/bin/sh' 'exec_prefix=/usr/local' 'infodir=/usr/local/share/info' 'libdir=/usr/local/lib' 'mandir=/usr/local/share/man' 'prefix=/usr/local' 'AR=ar' 'AS=as' 'CC=gcc' 'CXX=g++' 'LD=ld' 'NM=/usr/bin/nm -B' 'RANLIB=ranlib' 'DESTDIR=' all-recursive
Making all in include
make[3]: Nothing to be done for `all'.
Making all in testsuite
make[3]: Nothing to be done for `all'.
Making all in man
make[3]: Nothing to be done for `all'.
/bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -Wall -fexceptions -c -o src/prep_cif.lo /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src/prep_cif.c
libtool: compile: gcc -DHAVE_CONFIG_H -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -Wall -fexceptions -c /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src/prep_cif.c -fno-common -DPIC -o src/.libs/prep_cif.o
/bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -Wall -fexceptions -c -o src/types.lo /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src/types.c
libtool: compile: gcc -DHAVE_CONFIG_H -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -Wall -fexceptions -c /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src/types.c -fno-common -DPIC -o src/.libs/types.o
/bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -Wall -fexceptions -c -o src/raw_api.lo /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src/raw_api.c
libtool: compile: gcc -DHAVE_CONFIG_H -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -Wall -fexceptions -c /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src/raw_api.c -fno-common -DPIC -o src/.libs/raw_api.o
/bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -Wall -fexceptions -c -o src/java_raw_api.lo /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src/java_raw_api.c
libtool: compile: gcc -DHAVE_CONFIG_H -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -Wall -fexceptions -c /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src/java_raw_api.c -fno-common -DPIC -o src/.libs/java_raw_api.o
/bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -Wall -fexceptions -c -o src/closures.lo /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src/closures.c
libtool: compile: gcc -DHAVE_CONFIG_H -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -Wall -fexceptions -c /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src/closures.c -fno-common -DPIC -o src/.libs/closures.o
/bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -Wall -fexceptions -c -o src/x86/ffi64.lo /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src/x86/ffi64.c
libtool: compile: gcc -DHAVE_CONFIG_H -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -Wall -fexceptions -c /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src/x86/ffi64.c -fno-common -DPIC -o src/x86/.libs/ffi64.o
/bin/sh ./libtool --mode=compile gcc -DHAVE_CONFIG_H -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -c -o src/x86/unix64.lo /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src/x86/unix64.S
libtool: compile: gcc -DHAVE_CONFIG_H -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -c /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src/x86/unix64.S -fno-common -DPIC -o src/x86/.libs/unix64.o
/bin/sh ./libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -Wall -fexceptions -c -o src/x86/ffiw64.lo /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src/x86/ffiw64.c
libtool: compile: gcc -DHAVE_CONFIG_H -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -Wall -fexceptions -c /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src/x86/ffiw64.c -fno-common -DPIC -o src/x86/.libs/ffiw64.o
/bin/sh ./libtool --mode=compile gcc -DHAVE_CONFIG_H -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -c -o src/x86/win64.lo /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src/x86/win64.S
libtool: compile: gcc -DHAVE_CONFIG_H -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -I. -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/include -Iinclude -I/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src -c /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/src/x86/win64.S -fno-common -DPIC -o src/x86/.libs/win64.o
/bin/sh ./libtool --tag=CC --mode=link gcc -Wall -fexceptions -o libffi_convenience.la src/prep_cif.lo src/types.lo src/raw_api.lo src/java_raw_api.lo src/closures.lo src/x86/ffi64.lo src/x86/unix64.lo src/x86/ffiw64.lo src/x86/win64.lo
libtool: link: ar cru .libs/libffi_convenience.a src/.libs/prep_cif.o src/.libs/types.o src/.libs/raw_api.o src/.libs/java_raw_api.o src/.libs/closures.o src/x86/.libs/ffi64.o src/x86/.libs/unix64.o src/x86/.libs/ffiw64.o src/x86/.libs/win64.o
libtool: link: ranlib .libs/libffi_convenience.a
libtool: link: ( cd ".libs" && rm -f "libffi_convenience.la" && ln -s "../libffi_convenience.la" "libffi_convenience.la" )
/bin/sh ./libtool --tag=CC --mode=link gcc -Wall -fexceptions -no-undefined -version-info `grep -v '^#' /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/libtool-version` -o libffi.la -rpath /usr/local/lib src/prep_cif.lo src/types.lo src/raw_api.lo src/java_raw_api.lo src/closures.lo src/x86/ffi64.lo src/x86/unix64.lo src/x86/ffiw64.lo src/x86/win64.lo
libtool: link: gcc -dynamiclib -o .libs/libffi.7.dylib src/.libs/prep_cif.o src/.libs/types.o src/.libs/raw_api.o src/.libs/java_raw_api.o src/.libs/closures.o src/x86/.libs/ffi64.o src/x86/.libs/unix64.o src/x86/.libs/ffiw64.o src/x86/.libs/win64.o -install_name /usr/local/lib/libffi.7.dylib -compatibility_version 9 -current_version 9.0 -Wl,-single_module
libtool: link: (cd ".libs" && rm -f "libffi.dylib" && ln -s "libffi.7.dylib" "libffi.dylib")
libtool: link: ( cd ".libs" && rm -f "libffi.la" && ln -s "../libffi.la" "libffi.la" )
compiling AbstractMemory.c
compiling ArrayType.c
compiling Buffer.c
compiling Call.c
compiling ClosurePool.c
compiling DynamicLibrary.c
compiling Function.c
Function.c:867:17: warning: 'ffi_prep_closure' is deprecated [-Wdeprecated-declarations]
ffiStatus = ffi_prep_closure(code, &fnInfo->ffi_cif, callback_invoke, closure);
^
/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi-x86_64-darwin18/include/ffi.h:339:18: note: 'ffi_prep_closure' has been explicitly marked deprecated here
__attribute__((deprecated))
^
1 warning generated.
compiling FunctionInfo.c
compiling LastError.c
compiling LongDouble.c
compiling MappedType.c
compiling MemoryPointer.c
compiling MethodHandle.c
compiling Platform.c
compiling Pointer.c
compiling Struct.c
compiling StructByValue.c
compiling StructLayout.c
compiling Thread.c
compiling Type.c
compiling Types.c
compiling Variadic.c
compiling ffi.c
linking shared-object ffi_c.bundle
current directory: /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c
make "DESTDIR=" install
cd "/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi-x86_64-darwin18" && /Applications/Xcode.app/Contents/Developer/usr/bin/make
/Applications/Xcode.app/Contents/Developer/usr/bin/make 'AR_FLAGS=' 'CC_FOR_BUILD=' 'CFLAGS=-Wall -fexceptions' 'CXXFLAGS=-g -O2' 'CFLAGS_FOR_BUILD=' 'CFLAGS_FOR_TARGET=' 'INSTALL=/usr/local/bin/ginstall -c' 'INSTALL_DATA=/usr/local/bin/ginstall -c -m 644' 'INSTALL_PROGRAM=/usr/local/bin/ginstall -c' 'INSTALL_SCRIPT=/usr/local/bin/ginstall -c' 'JC1FLAGS=' 'LDFLAGS=' 'LIBCFLAGS=' 'LIBCFLAGS_FOR_TARGET=' 'MAKE=/Applications/Xcode.app/Contents/Developer/usr/bin/make' 'MAKEINFO=/bin/sh /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi/missing makeinfo ' 'PICFLAG=' 'PICFLAG_FOR_TARGET=' 'RUNTESTFLAGS=' 'SHELL=/bin/sh' 'exec_prefix=/usr/local' 'infodir=/usr/local/share/info' 'libdir=/usr/local/lib' 'mandir=/usr/local/share/man' 'prefix=/usr/local' 'AR=ar' 'AS=as' 'CC=gcc' 'CXX=g++' 'LD=ld' 'NM=/usr/bin/nm -B' 'RANLIB=ranlib' 'DESTDIR=' all-recursive
Making all in include
make[3]: Nothing to be done for `all'.
Making all in testsuite
make[3]: Nothing to be done for `all'.
Making all in man
make[3]: Nothing to be done for `all'.
make[3]: Nothing to be done for `all-am'.
compiling AbstractMemory.c
compiling ArrayType.c
compiling Buffer.c
compiling Call.c
compiling ClosurePool.c
compiling DynamicLibrary.c
compiling Function.c
Function.c:867:17: warning: 'ffi_prep_closure' is deprecated [-Wdeprecated-declarations]
ffiStatus = ffi_prep_closure(code, &fnInfo->ffi_cif, callback_invoke, closure);
^
/Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/ffi-1.11.1/ext/ffi_c/libffi-x86_64-darwin18/include/ffi.h:339:18: note: 'ffi_prep_closure' has been explicitly marked deprecated here
__attribute__((deprecated))
^
1 warning generated.
compiling FunctionInfo.c
compiling LastError.c
compiling LongDouble.c
compiling MappedType.c
compiling MemoryPointer.c
compiling MethodHandle.c
compiling Platform.c
compiling Pointer.c
compiling Struct.c
compiling StructByValue.c
compiling StructLayout.c
compiling Thread.c
compiling Type.c
compiling Types.c
compiling Variadic.c
compiling ffi.c
linking shared-object ffi_c.bundle
/usr/local/opt/coreutils/bin/ginstall -c -m 0755 ffi_c.bundle ./.gem.20191020-69875-3w418n

View File

@ -1,215 +0,0 @@
"pkg-config --exists libffi"
package configuration for libffi is not found
have_header: checking for ffi.h... -------------------- no
"gcc -o conftest -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/x86_64-darwin18 -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/ruby/backward -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0 -I. -I/usr/local/opt/libyaml/include -I/usr/local/opt/libksba/include -I/usr/local/opt/readline/include -I/usr/local/opt/zlib/include -I/usr/local/opt/openssl@1.1/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeclaration-after-statement -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -fno-common -pipe conftest.c -L. -L/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/zlib/lib -L/usr/local/opt/openssl@1.1/lib -L. -fstack-protector-strong -L/usr/local/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/zlib/lib -L/usr/local/opt/openssl@1.1/lib -lruby.2.6 "
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: int main(int argc, char **argv)
4: {
5: return 0;
6: }
/* end */
"gcc -E -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/x86_64-darwin18 -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/ruby/backward -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0 -I. -I/usr/local/opt/libyaml/include -I/usr/local/opt/libksba/include -I/usr/local/opt/readline/include -I/usr/local/opt/zlib/include -I/usr/local/opt/openssl@1.1/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeclaration-after-statement -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -fno-common -pipe conftest.c -o conftest.i"
conftest.c:3:10: fatal error: 'ffi.h' file not found
#include <ffi.h>
^~~~~~~
1 error generated.
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: #include <ffi.h>
/* end */
--------------------
find_header: checking for ffi.h in /usr/local/include,/usr/include/ffi... -------------------- no
"gcc -E -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/x86_64-darwin18 -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/ruby/backward -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0 -I. -I/usr/local/opt/libyaml/include -I/usr/local/opt/libksba/include -I/usr/local/opt/readline/include -I/usr/local/opt/zlib/include -I/usr/local/opt/openssl@1.1/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeclaration-after-statement -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -fno-common -pipe conftest.c -o conftest.i"
conftest.c:3:10: fatal error: 'ffi.h' file not found
#include <ffi.h>
^~~~~~~
1 error generated.
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: #include <ffi.h>
/* end */
"gcc -E -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/x86_64-darwin18 -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/ruby/backward -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0 -I. -I/usr/local/opt/libyaml/include -I/usr/local/opt/libksba/include -I/usr/local/opt/readline/include -I/usr/local/opt/zlib/include -I/usr/local/opt/openssl@1.1/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeclaration-after-statement -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -fno-common -pipe -I/usr/local/include conftest.c -o conftest.i"
conftest.c:3:10: fatal error: 'ffi.h' file not found
#include <ffi.h>
^~~~~~~
1 error generated.
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: #include <ffi.h>
/* end */
"gcc -E -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/x86_64-darwin18 -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/ruby/backward -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0 -I. -I/usr/local/opt/libyaml/include -I/usr/local/opt/libksba/include -I/usr/local/opt/readline/include -I/usr/local/opt/zlib/include -I/usr/local/opt/openssl@1.1/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeclaration-after-statement -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -fno-common -pipe -I/usr/include/ffi conftest.c -o conftest.i"
conftest.c:3:10: fatal error: 'ffi.h' file not found
#include <ffi.h>
^~~~~~~
1 error generated.
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: #include <ffi.h>
/* end */
--------------------
have_header: checking for shlwapi.h... -------------------- no
"gcc -E -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/x86_64-darwin18 -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/ruby/backward -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0 -I. -I/usr/local/opt/libyaml/include -I/usr/local/opt/libksba/include -I/usr/local/opt/readline/include -I/usr/local/opt/zlib/include -I/usr/local/opt/openssl@1.1/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeclaration-after-statement -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -fno-common -pipe conftest.c -o conftest.i"
conftest.c:3:10: fatal error: 'shlwapi.h' file not found
#include <shlwapi.h>
^~~~~~~~~~~
1 error generated.
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: #include <shlwapi.h>
/* end */
--------------------
have_func: checking for rb_thread_call_without_gvl()... -------------------- yes
"gcc -o conftest -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/x86_64-darwin18 -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/ruby/backward -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0 -I. -I/usr/local/opt/libyaml/include -I/usr/local/opt/libksba/include -I/usr/local/opt/readline/include -I/usr/local/opt/zlib/include -I/usr/local/opt/openssl@1.1/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeclaration-after-statement -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -fno-common -pipe conftest.c -L. -L/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/zlib/lib -L/usr/local/opt/openssl@1.1/lib -L. -fstack-protector-strong -L/usr/local/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/zlib/lib -L/usr/local/opt/openssl@1.1/lib -lruby.2.6 "
conftest.c:14:57: error: use of undeclared identifier 'rb_thread_call_without_gvl'
int t(void) { void ((*volatile p)()); p = (void ((*)()))rb_thread_call_without_gvl; return !p; }
^
1 error generated.
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: /*top*/
4: extern int t(void);
5: int main(int argc, char **argv)
6: {
7: if (argc > 1000000) {
8: int (* volatile tp)(void)=(int (*)(void))&t;
9: printf("%d", (*tp)());
10: }
11:
12: return 0;
13: }
14: int t(void) { void ((*volatile p)()); p = (void ((*)()))rb_thread_call_without_gvl; return !p; }
/* end */
"gcc -o conftest -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/x86_64-darwin18 -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/ruby/backward -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0 -I. -I/usr/local/opt/libyaml/include -I/usr/local/opt/libksba/include -I/usr/local/opt/readline/include -I/usr/local/opt/zlib/include -I/usr/local/opt/openssl@1.1/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeclaration-after-statement -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -fno-common -pipe conftest.c -L. -L/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/zlib/lib -L/usr/local/opt/openssl@1.1/lib -L. -fstack-protector-strong -L/usr/local/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/zlib/lib -L/usr/local/opt/openssl@1.1/lib -lruby.2.6 "
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: /*top*/
4: extern int t(void);
5: int main(int argc, char **argv)
6: {
7: if (argc > 1000000) {
8: int (* volatile tp)(void)=(int (*)(void))&t;
9: printf("%d", (*tp)());
10: }
11:
12: return 0;
13: }
14: extern void rb_thread_call_without_gvl();
15: int t(void) { rb_thread_call_without_gvl(); return 0; }
/* end */
--------------------
have_func: checking for ruby_native_thread_p()... -------------------- yes
"gcc -o conftest -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/x86_64-darwin18 -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/ruby/backward -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0 -I. -I/usr/local/opt/libyaml/include -I/usr/local/opt/libksba/include -I/usr/local/opt/readline/include -I/usr/local/opt/zlib/include -I/usr/local/opt/openssl@1.1/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeclaration-after-statement -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -fno-common -pipe conftest.c -L. -L/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/zlib/lib -L/usr/local/opt/openssl@1.1/lib -L. -fstack-protector-strong -L/usr/local/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/zlib/lib -L/usr/local/opt/openssl@1.1/lib -lruby.2.6 "
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: /*top*/
4: extern int t(void);
5: int main(int argc, char **argv)
6: {
7: if (argc > 1000000) {
8: int (* volatile tp)(void)=(int (*)(void))&t;
9: printf("%d", (*tp)());
10: }
11:
12: return 0;
13: }
14: int t(void) { void ((*volatile p)()); p = (void ((*)()))ruby_native_thread_p; return !p; }
/* end */
--------------------
have_func: checking for ruby_thread_has_gvl_p()... -------------------- yes
"gcc -o conftest -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/x86_64-darwin18 -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/ruby/backward -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0 -I. -I/usr/local/opt/libyaml/include -I/usr/local/opt/libksba/include -I/usr/local/opt/readline/include -I/usr/local/opt/zlib/include -I/usr/local/opt/openssl@1.1/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeclaration-after-statement -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -fno-common -pipe conftest.c -L. -L/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/zlib/lib -L/usr/local/opt/openssl@1.1/lib -L. -fstack-protector-strong -L/usr/local/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/zlib/lib -L/usr/local/opt/openssl@1.1/lib -lruby.2.6 "
conftest.c:14:57: error: use of undeclared identifier 'ruby_thread_has_gvl_p'
int t(void) { void ((*volatile p)()); p = (void ((*)()))ruby_thread_has_gvl_p; return !p; }
^
1 error generated.
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: /*top*/
4: extern int t(void);
5: int main(int argc, char **argv)
6: {
7: if (argc > 1000000) {
8: int (* volatile tp)(void)=(int (*)(void))&t;
9: printf("%d", (*tp)());
10: }
11:
12: return 0;
13: }
14: int t(void) { void ((*volatile p)()); p = (void ((*)()))ruby_thread_has_gvl_p; return !p; }
/* end */
"gcc -o conftest -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/x86_64-darwin18 -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0/ruby/backward -I/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/include/ruby-2.6.0 -I. -I/usr/local/opt/libyaml/include -I/usr/local/opt/libksba/include -I/usr/local/opt/readline/include -I/usr/local/opt/zlib/include -I/usr/local/opt/openssl@1.1/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT -O3 -ggdb3 -Wall -Wextra -Wdeclaration-after-statement -Wdeprecated-declarations -Wdivision-by-zero -Wimplicit-function-declaration -Wimplicit-int -Wpointer-arith -Wshorten-64-to-32 -Wwrite-strings -Wmissing-noreturn -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wunused-variable -Wextra-tokens -fno-common -pipe conftest.c -L. -L/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/zlib/lib -L/usr/local/opt/openssl@1.1/lib -L. -fstack-protector-strong -L/usr/local/lib -L/usr/local/opt/libyaml/lib -L/usr/local/opt/libksba/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/zlib/lib -L/usr/local/opt/openssl@1.1/lib -lruby.2.6 "
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: /*top*/
4: extern int t(void);
5: int main(int argc, char **argv)
6: {
7: if (argc > 1000000) {
8: int (* volatile tp)(void)=(int (*)(void))&t;
9: printf("%d", (*tp)());
10: }
11:
12: return 0;
13: }
14: extern void ruby_thread_has_gvl_p();
15: int t(void) { ruby_thread_has_gvl_p(); return 0; }
/* end */
--------------------
extconf.h is:
/* begin */
1: #ifndef EXTCONF_H
2: #define EXTCONF_H
3: #define HAVE_RB_THREAD_CALL_WITHOUT_GVL 1
4: #define HAVE_RUBY_NATIVE_THREAD_P 1
5: #define HAVE_RUBY_THREAD_HAS_GVL_P 1
6: #define HAVE_FFI_PREP_CIF_VAR 1
7: #define USE_INTERNAL_LIBFFI 1
8: #define RUBY_1_9 1
9: #endif
/* end */

View File

@ -1,16 +0,0 @@
current directory: /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/http_parser.rb-0.6.0/ext/ruby_http_parser
/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/bin/ruby -I /Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/lib/ruby/site_ruby/2.6.0 -r ./siteconf20191020-69875-15g4lcd.rb extconf.rb
creating Makefile
current directory: /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/http_parser.rb-0.6.0/ext/ruby_http_parser
make "DESTDIR=" clean
current directory: /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/http_parser.rb-0.6.0/ext/ruby_http_parser
make "DESTDIR="
compiling ruby_http_parser.c
compiling ryah_http_parser.c
linking shared-object ruby_http_parser.bundle
current directory: /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/http_parser.rb-0.6.0/ext/ruby_http_parser
make "DESTDIR=" install
/usr/local/opt/coreutils/bin/ginstall -c -m 0755 ruby_http_parser.bundle ./.gem.20191020-69875-2pn1qv

View File

@ -1,75 +0,0 @@
current directory: /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/sassc-2.2.1/ext
/Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/bin/ruby -I /Users/BenjaminJones/.rvm/rubies/ruby-2.6.3/lib/ruby/site_ruby/2.6.0 -r ./siteconf20191020-69875-10qd776.rb extconf.rb
creating Makefile
current directory: /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/sassc-2.2.1/ext
make "DESTDIR=" clean
current directory: /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/sassc-2.2.1/ext
make "DESTDIR="
compiling ./libsass/src/units.cpp
compiling ./libsass/src/fn_miscs.cpp
compiling ./libsass/src/util.cpp
compiling ./libsass/src/ast_selectors.cpp
compiling ./libsass/src/environment.cpp
compiling ./libsass/src/memory/SharedPtr.cpp
compiling ./libsass/src/ast_sel_unify.cpp
compiling ./libsass/src/ast.cpp
compiling ./libsass/src/emitter.cpp
compiling ./libsass/src/bind.cpp
compiling ./libsass/src/sass_functions.cpp
compiling ./libsass/src/ast2c.cpp
compiling ./libsass/src/base64vlq.cpp
compiling ./libsass/src/context.cpp
compiling ./libsass/src/remove_placeholders.cpp
compiling ./libsass/src/node.cpp
compiling ./libsass/src/fn_colors.cpp
compiling ./libsass/src/sass_values.cpp
compiling ./libsass/src/constants.cpp
compiling ./libsass/src/ast_values.cpp
compiling ./libsass/src/lexer.cpp
compiling ./libsass/src/color_maps.cpp
compiling ./libsass/src/fn_selectors.cpp
compiling ./libsass/src/fn_numbers.cpp
compiling ./libsass/src/operators.cpp
compiling ./libsass/src/output.cpp
compiling ./libsass/src/source_map.cpp
compiling ./libsass/src/sass.cpp
compiling ./libsass/src/listize.cpp
compiling ./libsass/src/ast_fwd_decl.cpp
compiling ./libsass/src/sass_util.cpp
compiling ./libsass/src/fn_strings.cpp
compiling ./libsass/src/fn_utils.cpp
compiling ./libsass/src/ast_sel_cmp.cpp
compiling ./libsass/src/fn_maps.cpp
compiling ./libsass/src/file.cpp
compiling ./libsass/src/c99func.c
compiling ./libsass/src/ast_supports.cpp
compiling ./libsass/src/check_nesting.cpp
compiling ./libsass/src/inspect.cpp
compiling ./libsass/src/extend.cpp
compiling ./libsass/src/plugins.cpp
compiling ./libsass/src/cssize.cpp
compiling ./libsass/src/sass2scss.cpp
compiling ./libsass/src/to_value.cpp
compiling ./libsass/src/prelexer.cpp
compiling ./libsass/src/subset_map.cpp
compiling ./libsass/src/utf8_string.cpp
compiling ./libsass/src/backtrace.cpp
compiling ./libsass/src/json.cpp
compiling ./libsass/src/parser.cpp
compiling ./libsass/src/util_string.cpp
compiling ./libsass/src/error_handling.cpp
compiling ./libsass/src/sass_context.cpp
compiling ./libsass/src/eval.cpp
compiling ./libsass/src/values.cpp
compiling ./libsass/src/cencode.c
compiling ./libsass/src/fn_lists.cpp
compiling ./libsass/src/position.cpp
compiling ./libsass/src/expand.cpp
compiling ./libsass/src/c2ast.cpp
linking shared-object sassc/libsass.bundle
current directory: /Users/BenjaminJones/Documents/Code/ReclaimFutures/rf-web/vendor/bundle/gems/sassc-2.2.1/ext
make "DESTDIR=" install
/usr/local/opt/coreutils/bin/ginstall -c -m 0755 libsass.bundle ./.gem.20191020-69875-1kuo96p/sassc

View File

@ -1,235 +0,0 @@
# Addressable 2.7.0
- added `:compacted` flag to `normalized_query`
- `heuristic_parse` handles `mailto:` more intuitively
- refactored validation to use a prepended module
- dropped explicit support for JRuby 9.0.5.0
- compatibility w/ public_suffix 4.x
- performance improvements
# Addressable 2.6.0
- added `tld=` method to allow assignment to the public suffix
- most `heuristic_parse` patterns are now case-insensitive
- `heuristic_parse` handles more `file://` URI variations
- fixes bug in `heuristic_parse` when uri starts with digit
- fixes bug in `request_uri=` with query strings
- fixes template issues with `nil` and `?` operator
- `frozen_string_literal` pragmas added
- minor performance improvements in regexps
- fixes to eliminate warnings
# Addressable 2.5.2
- better support for frozen string literals
- fixed bug w/ uppercase characters in scheme
- IDNA errors w/ emoji URLs
- compatibility w/ public_suffix 3.x
# Addressable 2.5.1
- allow unicode normalization to be disabled for URI Template expansion
- removed duplicate test
# Addressable 2.5.0
- dropping support for Ruby 1.9
- adding support for Ruby 2.4 preview
- add support for public suffixes and tld; first runtime dependency
- hostname escaping should match RFC; underscores in hostnames no longer escaped
- paths beginning with // and missing an authority are now considered invalid
- validation now also takes place after setting a path
- handle backslashes in authority more like a browser for `heuristic_parse`
- unescaped backslashes in host now raise an `InvalidURIError`
- `merge!`, `join!`, `omit!` and `normalize!` don't disable deferred validation
- `heuristic_parse` now trims whitespace before parsing
- host parts longer than 63 bytes will be ignored and not passed to libidn
- normalized values always encoded as UTF-8
# Addressable 2.4.0
- support for 1.8.x dropped
- double quotes in a host now raises an error
- newlines in host will no longer get unescaped during normalization
- stricter handling of bogus scheme values
- stricter handling of encoded port values
- calling `require 'addressable'` will now load both the URI and Template files
- assigning to the `hostname` component with an `IPAddr` object is now supported
- assigning to the `origin` component is now supported
- fixed minor bug where an exception would be thrown for a missing ACE suffix
- better partial expansion of URI templates
# Addressable 2.3.8
- fix warnings
- update dependency gems
- support for 1.8.x officially deprecated
# Addressable 2.3.7
- fix scenario in which invalid URIs don't get an exception until inspected
- handle hostnames with two adjacent periods correctly
- upgrade of RSpec
# Addressable 2.3.6
- normalization drops empty query string
- better handling in template extract for missing values
- template modifier for `'?'` now treated as optional
- fixed issue where character class parameters were modified
- templates can now be tested for equality
- added `:sorted` option to normalization of query strings
- fixed issue with normalization of hosts given in `'example.com.'` form
# Addressable 2.3.5
- added Addressable::URI#empty? method
- Addressable::URI#hostname methods now strip square brackets from IPv6 hosts
- compatibility with Net::HTTP in Ruby 2.0.0
- Addressable::URI#route_from should always give relative URIs
# Addressable 2.3.4
- fixed issue with encoding altering its inputs
- query string normalization now leaves ';' characters alone
- FakeFS is detected before attempting to load unicode tables
- additional testing to ensure frozen objects don't cause problems
# Addressable 2.3.3
- fixed issue with converting common primitives during template expansion
- fixed port encoding issue
- removed a few warnings
- normalize should now ignore %2B in query strings
- the IDNA logic should now be handled by libidn in Ruby 1.9
- no template match should now result in nil instead of an empty MatchData
- added license information to gemspec
# Addressable 2.3.2
- added Addressable::URI#default_port method
- fixed issue with Marshalling Unicode data on Windows
- improved heuristic parsing to better handle IPv4 addresses
# Addressable 2.3.1
- fixed missing unicode data file
# Addressable 2.3.0
- updated Addressable::Template to use RFC 6570, level 4
- fixed compatibility problems with some versions of Ruby
- moved unicode tables into a data file for performance reasons
- removing support for multiple query value notations
# Addressable 2.2.8
- fixed issues with dot segment removal code
- form encoding can now handle multiple values per key
- updated development environment
# Addressable 2.2.7
- fixed issues related to Addressable::URI#query_values=
- the Addressable::URI.parse method is now polymorphic
# Addressable 2.2.6
- changed the way ambiguous paths are handled
- fixed bug with frozen URIs
- https supported in heuristic parsing
# Addressable 2.2.5
- 'parsing' a pre-parsed URI object is now a dup operation
- introduced conditional support for libidn
- fixed normalization issue on ampersands in query strings
- added additional tests around handling of query strings
# Addressable 2.2.4
- added origin support from draft-ietf-websec-origin-00
- resolved issue with attempting to navigate below root
- fixed bug with string splitting in query strings
# Addressable 2.2.3
- added :flat_array notation for query strings
# Addressable 2.2.2
- fixed issue with percent escaping of '+' character in query strings
# Addressable 2.2.1
- added support for application/x-www-form-urlencoded.
# Addressable 2.2.0
- added site methods
- improved documentation
# Addressable 2.1.2
- added HTTP request URI methods
- better handling of Windows file paths
- validation_deferred boolean replaced with defer_validation block
- normalization of percent-encoded paths should now be correct
- fixed issue with constructing URIs with relative paths
- fixed warnings
# Addressable 2.1.1
- more type checking changes
- fixed issue with unicode normalization
- added method to find template defaults
- symbolic keys are now allowed in template mappings
- numeric values and symbolic values are now allowed in template mappings
# Addressable 2.1.0
- refactored URI template support out into its own class
- removed extract method due to being useless and unreliable
- removed Addressable::URI.expand_template
- removed Addressable::URI#extract_mapping
- added partial template expansion
- fixed minor bugs in the parse and heuristic_parse methods
- fixed incompatibility with Ruby 1.9.1
- fixed bottleneck in Addressable::URI#hash and Addressable::URI#to_s
- fixed unicode normalization exception
- updated query_values methods to better handle subscript notation
- worked around issue with freezing URIs
- improved specs
# Addressable 2.0.2
- fixed issue with URI template expansion
- fixed issue with percent escaping characters 0-15
# Addressable 2.0.1
- fixed issue with query string assignment
- fixed issue with improperly encoded components
# Addressable 2.0.0
- the initialize method now takes an options hash as its only parameter
- added query_values method to URI class
- completely replaced IDNA implementation with pure Ruby
- renamed Addressable::ADDRESSABLE_VERSION to Addressable::VERSION
- completely reworked the Rakefile
- changed the behavior of the port method significantly
- Addressable::URI.encode_segment, Addressable::URI.unencode_segment renamed
- documentation is now in YARD format
- more rigorous type checking
- to_str method implemented, implicit conversion to Strings now allowed
- Addressable::URI#omit method added, Addressable::URI#merge method replaced
- updated URI Template code to match v 03 of the draft spec
- added a bunch of new specifications
# Addressable 1.0.4
- switched to using RSpec's pending system for specs that rely on IDN
- fixed issue with creating URIs with paths that are not prefixed with '/'
# Addressable 1.0.3
- implemented a hash method
# Addressable 1.0.2
- fixed minor bug with the extract_mapping method
# Addressable 1.0.1
- fixed minor bug with the extract_mapping method
# Addressable 1.0.0
- heuristic parse method added
- parsing is slightly more strict
- replaced to_h with to_hash
- fixed routing methods
- improved specifications
- improved heckle rake task
- no surviving heckle mutations
# Addressable 0.1.2
- improved normalization
- fixed bug in joining algorithm
- updated specifications
# Addressable 0.1.1
- updated documentation
- added URI Template variable extraction
# Addressable 0.1.0
- initial release
- implementation based on RFC 3986, 3987
- support for IRIs via libidn
- support for the URI Template draft spec

View File

@ -1,32 +0,0 @@
source 'https://rubygems.org'
gemspec
group :test do
gem 'rspec', '~> 3.8'
gem 'rspec-its', '~> 1.3'
end
group :development do
gem 'launchy', '~> 2.4', '>= 2.4.3'
gem 'redcarpet', :platform => :mri_19
gem 'yard'
end
group :test, :development do
gem 'rake', '> 10.0', '< 12'
gem 'simplecov', :require => false
gem 'coveralls', :require => false, :platforms => [
:ruby_20, :ruby_21, :ruby_22, :ruby_23
]
# Used to test compatibility.
gem 'rack-mount', git: 'https://github.com/sporkmonger/rack-mount.git', require: 'rack/mount'
if RUBY_VERSION.start_with?('2.0', '2.1')
gem 'rack', '< 2', :require => false
else
gem 'rack', :require => false
end
end
gem 'idn-ruby', :platform => [:mri_20, :mri_21, :mri_22, :mri_23, :mri_24]

View File

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,121 +0,0 @@
# Addressable
<dl>
<dt>Homepage</dt><dd><a href="https://github.com/sporkmonger/addressable">github.com/sporkmonger/addressable</a></dd>
<dt>Author</dt><dd><a href="mailto:bob@sporkmonger.com">Bob Aman</a></dd>
<dt>Copyright</dt><dd>Copyright © Bob Aman</dd>
<dt>License</dt><dd>Apache 2.0</dd>
</dl>
[![Gem Version](http://img.shields.io/gem/dt/addressable.svg)][gem]
[![Build Status](https://secure.travis-ci.org/sporkmonger/addressable.svg?branch=master)][travis]
[![Test Coverage Status](https://img.shields.io/coveralls/sporkmonger/addressable.svg)][coveralls]
[![Documentation Coverage Status](http://inch-ci.org/github/sporkmonger/addressable.svg?branch=master)][inch]
[gem]: https://rubygems.org/gems/addressable
[travis]: http://travis-ci.org/sporkmonger/addressable
[coveralls]: https://coveralls.io/r/sporkmonger/addressable
[inch]: http://inch-ci.org/github/sporkmonger/addressable
# Description
Addressable is an alternative implementation to the URI implementation
that is part of Ruby's standard library. It is flexible, offers heuristic
parsing, and additionally provides extensive support for IRIs and URI templates.
Addressable closely conforms to RFC 3986, RFC 3987, and RFC 6570 (level 4).
# Reference
- {Addressable::URI}
- {Addressable::Template}
# Example usage
```ruby
require "addressable/uri"
uri = Addressable::URI.parse("http://example.com/path/to/resource/")
uri.scheme
#=> "http"
uri.host
#=> "example.com"
uri.path
#=> "/path/to/resource/"
uri = Addressable::URI.parse("http://www.詹姆斯.com/")
uri.normalize
#=> #<Addressable::URI:0xc9a4c8 URI:http://www.xn--8ws00zhy3a.com/>
```
# URI Templates
For more details, see [RFC 6570](https://www.rfc-editor.org/rfc/rfc6570.txt).
```ruby
require "addressable/template"
template = Addressable::Template.new("http://example.com/{?query*}")
template.expand({
"query" => {
'foo' => 'bar',
'color' => 'red'
}
})
#=> #<Addressable::URI:0xc9d95c URI:http://example.com/?foo=bar&color=red>
template = Addressable::Template.new("http://example.com/{?one,two,three}")
template.partial_expand({"one" => "1", "three" => 3}).pattern
#=> "http://example.com/?one=1{&two}&three=3"
template = Addressable::Template.new(
"http://{host}{/segments*}/{?one,two,bogus}{#fragment}"
)
uri = Addressable::URI.parse(
"http://example.com/a/b/c/?one=1&two=2#foo"
)
template.extract(uri)
#=>
# {
# "host" => "example.com",
# "segments" => ["a", "b", "c"],
# "one" => "1",
# "two" => "2",
# "fragment" => "foo"
# }
```
# Install
```console
$ gem install addressable
```
You may optionally turn on native IDN support by installing libidn and the
idn gem:
```console
$ sudo apt-get install idn # Debian/Ubuntu
$ brew install libidn # OS X
$ gem install idn-ruby
```
# Semantic Versioning
This project uses [Semantic Versioning](https://semver.org/). You can (and should) specify your
dependency using a pessimistic version constraint covering the major and minor
values:
```ruby
spec.add_dependency 'addressable', '~> 2.5'
```
If you need a specific bug fix, you can also specify minimum tiny versions
without preventing updates to the latest minor release:
```ruby
spec.add_dependency 'addressable', '~> 2.3', '>= 2.3.7'
```

View File

@ -1,34 +0,0 @@
# frozen_string_literal: true
require 'rubygems'
require 'rake'
require File.join(File.dirname(__FILE__), 'lib', 'addressable', 'version')
PKG_DISPLAY_NAME = 'Addressable'
PKG_NAME = PKG_DISPLAY_NAME.downcase
PKG_VERSION = Addressable::VERSION::STRING
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
RELEASE_NAME = "REL #{PKG_VERSION}"
PKG_SUMMARY = "URI Implementation"
PKG_DESCRIPTION = <<-TEXT
Addressable is an alternative implementation to the URI implementation that is
part of Ruby's standard library. It is flexible, offers heuristic parsing, and
additionally provides extensive support for IRIs and URI templates.
TEXT
PKG_FILES = FileList[
"lib/**/*", "spec/**/*", "vendor/**/*", "data/**/*",
"tasks/**/*",
"[A-Z]*", "Rakefile"
].exclude(/pkg/).exclude(/database\.yml/).
exclude(/Gemfile\.lock/).exclude(/[_\.]git$/)
task :default => "spec"
WINDOWS = (RUBY_PLATFORM =~ /mswin|win32|mingw|bccwin|cygwin/) rescue false
SUDO = WINDOWS ? '' : ('sudo' unless ENV['SUDOLESS'])
Dir['tasks/**/*.rake'].each { |rake| load rake }

View File

@ -1,4 +0,0 @@
# frozen_string_literal: true
require 'addressable/uri'
require 'addressable/template'

View File

@ -1,27 +0,0 @@
# frozen_string_literal: true
# encoding:utf-8
#--
# Copyright (C) Bob Aman
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#++
begin
require "addressable/idna/native"
rescue LoadError
# libidn or the idn gem was not available, fall back on a pure-Ruby
# implementation...
require "addressable/idna/pure"
end

View File

@ -1,61 +0,0 @@
# frozen_string_literal: true
# encoding:utf-8
#--
# Copyright (C) Bob Aman
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#++
require "idn"
module Addressable
module IDNA
def self.punycode_encode(value)
IDN::Punycode.encode(value.to_s)
end
def self.punycode_decode(value)
IDN::Punycode.decode(value.to_s)
end
def self.unicode_normalize_kc(value)
IDN::Stringprep.nfkc_normalize(value.to_s)
end
def self.to_ascii(value)
value.to_s.split('.', -1).map do |segment|
if segment.size > 0 && segment.size < 64
IDN::Idna.toASCII(segment, IDN::Idna::ALLOW_UNASSIGNED)
elsif segment.size >= 64
segment
else
''
end
end.join('.')
end
def self.to_unicode(value)
value.to_s.split('.', -1).map do |segment|
if segment.size > 0 && segment.size < 64
IDN::Idna.toUnicode(segment, IDN::Idna::ALLOW_UNASSIGNED)
elsif segment.size >= 64
segment
else
''
end
end.join('.')
end
end
end

View File

@ -1,676 +0,0 @@
# frozen_string_literal: true
# encoding:utf-8
#--
# Copyright (C) Bob Aman
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#++
module Addressable
module IDNA
# This module is loosely based on idn_actionmailer by Mick Staugaard,
# the unicode library by Yoshida Masato, and the punycode implementation
# by Kazuhiro Nishiyama. Most of the code was copied verbatim, but
# some reformatting was done, and some translation from C was done.
#
# Without their code to work from as a base, we'd all still be relying
# on the presence of libidn. Which nobody ever seems to have installed.
#
# Original sources:
# http://github.com/staugaard/idn_actionmailer
# http://www.yoshidam.net/Ruby.html#unicode
# http://rubyforge.org/frs/?group_id=2550
UNICODE_TABLE = File.expand_path(
File.join(File.dirname(__FILE__), '../../..', 'data/unicode.data')
)
ACE_PREFIX = "xn--"
UTF8_REGEX = /\A(?:
[\x09\x0A\x0D\x20-\x7E] # ASCII
| [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
| \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
| \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4nil5
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
)*\z/mnx
UTF8_REGEX_MULTIBYTE = /(?:
[\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
| \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
| \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4nil5
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
)/mnx
# :startdoc:
# Converts from a Unicode internationalized domain name to an ASCII
# domain name as described in RFC 3490.
def self.to_ascii(input)
input = input.to_s unless input.is_a?(String)
input = input.dup
if input.respond_to?(:force_encoding)
input.force_encoding(Encoding::ASCII_8BIT)
end
if input =~ UTF8_REGEX && input =~ UTF8_REGEX_MULTIBYTE
parts = unicode_downcase(input).split('.')
parts.map! do |part|
if part.respond_to?(:force_encoding)
part.force_encoding(Encoding::ASCII_8BIT)
end
if part =~ UTF8_REGEX && part =~ UTF8_REGEX_MULTIBYTE
ACE_PREFIX + punycode_encode(unicode_normalize_kc(part))
else
part
end
end
parts.join('.')
else
input
end
end
# Converts from an ASCII domain name to a Unicode internationalized
# domain name as described in RFC 3490.
def self.to_unicode(input)
input = input.to_s unless input.is_a?(String)
parts = input.split('.')
parts.map! do |part|
if part =~ /^#{ACE_PREFIX}(.+)/
begin
punycode_decode(part[/^#{ACE_PREFIX}(.+)/, 1])
rescue Addressable::IDNA::PunycodeBadInput
# toUnicode is explicitly defined as never-fails by the spec
part
end
else
part
end
end
output = parts.join('.')
if output.respond_to?(:force_encoding)
output.force_encoding(Encoding::UTF_8)
end
output
end
# Unicode normalization form KC.
def self.unicode_normalize_kc(input)
input = input.to_s unless input.is_a?(String)
unpacked = input.unpack("U*")
unpacked =
unicode_compose(unicode_sort_canonical(unicode_decompose(unpacked)))
return unpacked.pack("U*")
end
##
# Unicode aware downcase method.
#
# @api private
# @param [String] input
# The input string.
# @return [String] The downcased result.
def self.unicode_downcase(input)
input = input.to_s unless input.is_a?(String)
unpacked = input.unpack("U*")
unpacked.map! { |codepoint| lookup_unicode_lowercase(codepoint) }
return unpacked.pack("U*")
end
private_class_method :unicode_downcase
def self.unicode_compose(unpacked)
unpacked_result = []
length = unpacked.length
return unpacked if length == 0
starter = unpacked[0]
starter_cc = lookup_unicode_combining_class(starter)
starter_cc = 256 if starter_cc != 0
for i in 1...length
ch = unpacked[i]
if (starter_cc == 0 &&
(composite = unicode_compose_pair(starter, ch)) != nil)
starter = composite
else
unpacked_result << starter
starter = ch
end
end
unpacked_result << starter
return unpacked_result
end
private_class_method :unicode_compose
def self.unicode_compose_pair(ch_one, ch_two)
if ch_one >= HANGUL_LBASE && ch_one < HANGUL_LBASE + HANGUL_LCOUNT &&
ch_two >= HANGUL_VBASE && ch_two < HANGUL_VBASE + HANGUL_VCOUNT
# Hangul L + V
return HANGUL_SBASE + (
(ch_one - HANGUL_LBASE) * HANGUL_VCOUNT + (ch_two - HANGUL_VBASE)
) * HANGUL_TCOUNT
elsif ch_one >= HANGUL_SBASE &&
ch_one < HANGUL_SBASE + HANGUL_SCOUNT &&
(ch_one - HANGUL_SBASE) % HANGUL_TCOUNT == 0 &&
ch_two >= HANGUL_TBASE && ch_two < HANGUL_TBASE + HANGUL_TCOUNT
# Hangul LV + T
return ch_one + (ch_two - HANGUL_TBASE)
end
p = []
ucs4_to_utf8 = lambda do |ch|
if ch < 128
p << ch
elsif ch < 2048
p << (ch >> 6 | 192)
p << (ch & 63 | 128)
elsif ch < 0x10000
p << (ch >> 12 | 224)
p << (ch >> 6 & 63 | 128)
p << (ch & 63 | 128)
elsif ch < 0x200000
p << (ch >> 18 | 240)
p << (ch >> 12 & 63 | 128)
p << (ch >> 6 & 63 | 128)
p << (ch & 63 | 128)
elsif ch < 0x4000000
p << (ch >> 24 | 248)
p << (ch >> 18 & 63 | 128)
p << (ch >> 12 & 63 | 128)
p << (ch >> 6 & 63 | 128)
p << (ch & 63 | 128)
elsif ch < 0x80000000
p << (ch >> 30 | 252)
p << (ch >> 24 & 63 | 128)
p << (ch >> 18 & 63 | 128)
p << (ch >> 12 & 63 | 128)
p << (ch >> 6 & 63 | 128)
p << (ch & 63 | 128)
end
end
ucs4_to_utf8.call(ch_one)
ucs4_to_utf8.call(ch_two)
return lookup_unicode_composition(p)
end
private_class_method :unicode_compose_pair
def self.unicode_sort_canonical(unpacked)
unpacked = unpacked.dup
i = 1
length = unpacked.length
return unpacked if length < 2
while i < length
last = unpacked[i-1]
ch = unpacked[i]
last_cc = lookup_unicode_combining_class(last)
cc = lookup_unicode_combining_class(ch)
if cc != 0 && last_cc != 0 && last_cc > cc
unpacked[i] = last
unpacked[i-1] = ch
i -= 1 if i > 1
else
i += 1
end
end
return unpacked
end
private_class_method :unicode_sort_canonical
def self.unicode_decompose(unpacked)
unpacked_result = []
for cp in unpacked
if cp >= HANGUL_SBASE && cp < HANGUL_SBASE + HANGUL_SCOUNT
l, v, t = unicode_decompose_hangul(cp)
unpacked_result << l
unpacked_result << v if v
unpacked_result << t if t
else
dc = lookup_unicode_compatibility(cp)
unless dc
unpacked_result << cp
else
unpacked_result.concat(unicode_decompose(dc.unpack("U*")))
end
end
end
return unpacked_result
end
private_class_method :unicode_decompose
def self.unicode_decompose_hangul(codepoint)
sindex = codepoint - HANGUL_SBASE;
if sindex < 0 || sindex >= HANGUL_SCOUNT
l = codepoint
v = t = nil
return l, v, t
end
l = HANGUL_LBASE + sindex / HANGUL_NCOUNT
v = HANGUL_VBASE + (sindex % HANGUL_NCOUNT) / HANGUL_TCOUNT
t = HANGUL_TBASE + sindex % HANGUL_TCOUNT
if t == HANGUL_TBASE
t = nil
end
return l, v, t
end
private_class_method :unicode_decompose_hangul
def self.lookup_unicode_combining_class(codepoint)
codepoint_data = UNICODE_DATA[codepoint]
(codepoint_data ?
(codepoint_data[UNICODE_DATA_COMBINING_CLASS] || 0) :
0)
end
private_class_method :lookup_unicode_combining_class
def self.lookup_unicode_compatibility(codepoint)
codepoint_data = UNICODE_DATA[codepoint]
(codepoint_data ?
codepoint_data[UNICODE_DATA_COMPATIBILITY] : nil)
end
private_class_method :lookup_unicode_compatibility
def self.lookup_unicode_lowercase(codepoint)
codepoint_data = UNICODE_DATA[codepoint]
(codepoint_data ?
(codepoint_data[UNICODE_DATA_LOWERCASE] || codepoint) :
codepoint)
end
private_class_method :lookup_unicode_lowercase
def self.lookup_unicode_composition(unpacked)
return COMPOSITION_TABLE[unpacked]
end
private_class_method :lookup_unicode_composition
HANGUL_SBASE = 0xac00
HANGUL_LBASE = 0x1100
HANGUL_LCOUNT = 19
HANGUL_VBASE = 0x1161
HANGUL_VCOUNT = 21
HANGUL_TBASE = 0x11a7
HANGUL_TCOUNT = 28
HANGUL_NCOUNT = HANGUL_VCOUNT * HANGUL_TCOUNT # 588
HANGUL_SCOUNT = HANGUL_LCOUNT * HANGUL_NCOUNT # 11172
UNICODE_DATA_COMBINING_CLASS = 0
UNICODE_DATA_EXCLUSION = 1
UNICODE_DATA_CANONICAL = 2
UNICODE_DATA_COMPATIBILITY = 3
UNICODE_DATA_UPPERCASE = 4
UNICODE_DATA_LOWERCASE = 5
UNICODE_DATA_TITLECASE = 6
begin
if defined?(FakeFS)
fakefs_state = FakeFS.activated?
FakeFS.deactivate!
end
# This is a sparse Unicode table. Codepoints without entries are
# assumed to have the value: [0, 0, nil, nil, nil, nil, nil]
UNICODE_DATA = File.open(UNICODE_TABLE, "rb") do |file|
Marshal.load(file.read)
end
ensure
if defined?(FakeFS)
FakeFS.activate! if fakefs_state
end
end
COMPOSITION_TABLE = {}
UNICODE_DATA.each do |codepoint, data|
canonical = data[UNICODE_DATA_CANONICAL]
exclusion = data[UNICODE_DATA_EXCLUSION]
if canonical && exclusion == 0
COMPOSITION_TABLE[canonical.unpack("C*")] = codepoint
end
end
UNICODE_MAX_LENGTH = 256
ACE_MAX_LENGTH = 256
PUNYCODE_BASE = 36
PUNYCODE_TMIN = 1
PUNYCODE_TMAX = 26
PUNYCODE_SKEW = 38
PUNYCODE_DAMP = 700
PUNYCODE_INITIAL_BIAS = 72
PUNYCODE_INITIAL_N = 0x80
PUNYCODE_DELIMITER = 0x2D
PUNYCODE_MAXINT = 1 << 64
PUNYCODE_PRINT_ASCII =
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" +
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" +
" !\"\#$%&'()*+,-./" +
"0123456789:;<=>?" +
"@ABCDEFGHIJKLMNO" +
"PQRSTUVWXYZ[\\]^_" +
"`abcdefghijklmno" +
"pqrstuvwxyz{|}~\n"
# Input is invalid.
class PunycodeBadInput < StandardError; end
# Output would exceed the space provided.
class PunycodeBigOutput < StandardError; end
# Input needs wider integers to process.
class PunycodeOverflow < StandardError; end
def self.punycode_encode(unicode)
unicode = unicode.to_s unless unicode.is_a?(String)
input = unicode.unpack("U*")
output = [0] * (ACE_MAX_LENGTH + 1)
input_length = input.size
output_length = [ACE_MAX_LENGTH]
# Initialize the state
n = PUNYCODE_INITIAL_N
delta = out = 0
max_out = output_length[0]
bias = PUNYCODE_INITIAL_BIAS
# Handle the basic code points:
input_length.times do |j|
if punycode_basic?(input[j])
if max_out - out < 2
raise PunycodeBigOutput,
"Output would exceed the space provided."
end
output[out] = input[j]
out += 1
end
end
h = b = out
# h is the number of code points that have been handled, b is the
# number of basic code points, and out is the number of characters
# that have been output.
if b > 0
output[out] = PUNYCODE_DELIMITER
out += 1
end
# Main encoding loop:
while h < input_length
# All non-basic code points < n have been
# handled already. Find the next larger one:
m = PUNYCODE_MAXINT
input_length.times do |j|
m = input[j] if (n...m) === input[j]
end
# Increase delta enough to advance the decoder's
# <n,i> state to <m,0>, but guard against overflow:
if m - n > (PUNYCODE_MAXINT - delta) / (h + 1)
raise PunycodeOverflow, "Input needs wider integers to process."
end
delta += (m - n) * (h + 1)
n = m
input_length.times do |j|
# Punycode does not need to check whether input[j] is basic:
if input[j] < n
delta += 1
if delta == 0
raise PunycodeOverflow,
"Input needs wider integers to process."
end
end
if input[j] == n
# Represent delta as a generalized variable-length integer:
q = delta; k = PUNYCODE_BASE
while true
if out >= max_out
raise PunycodeBigOutput,
"Output would exceed the space provided."
end
t = (
if k <= bias
PUNYCODE_TMIN
elsif k >= bias + PUNYCODE_TMAX
PUNYCODE_TMAX
else
k - bias
end
)
break if q < t
output[out] =
punycode_encode_digit(t + (q - t) % (PUNYCODE_BASE - t))
out += 1
q = (q - t) / (PUNYCODE_BASE - t)
k += PUNYCODE_BASE
end
output[out] = punycode_encode_digit(q)
out += 1
bias = punycode_adapt(delta, h + 1, h == b)
delta = 0
h += 1
end
end
delta += 1
n += 1
end
output_length[0] = out
outlen = out
outlen.times do |j|
c = output[j]
unless c >= 0 && c <= 127
raise StandardError, "Invalid output char."
end
unless PUNYCODE_PRINT_ASCII[c]
raise PunycodeBadInput, "Input is invalid."
end
end
output[0..outlen].map { |x| x.chr }.join("").sub(/\0+\z/, "")
end
private_class_method :punycode_encode
def self.punycode_decode(punycode)
input = []
output = []
if ACE_MAX_LENGTH * 2 < punycode.size
raise PunycodeBigOutput, "Output would exceed the space provided."
end
punycode.each_byte do |c|
unless c >= 0 && c <= 127
raise PunycodeBadInput, "Input is invalid."
end
input.push(c)
end
input_length = input.length
output_length = [UNICODE_MAX_LENGTH]
# Initialize the state
n = PUNYCODE_INITIAL_N
out = i = 0
max_out = output_length[0]
bias = PUNYCODE_INITIAL_BIAS
# Handle the basic code points: Let b be the number of input code
# points before the last delimiter, or 0 if there is none, then
# copy the first b code points to the output.
b = 0
input_length.times do |j|
b = j if punycode_delimiter?(input[j])
end
if b > max_out
raise PunycodeBigOutput, "Output would exceed the space provided."
end
b.times do |j|
unless punycode_basic?(input[j])
raise PunycodeBadInput, "Input is invalid."
end
output[out] = input[j]
out+=1
end
# Main decoding loop: Start just after the last delimiter if any
# basic code points were copied; start at the beginning otherwise.
in_ = b > 0 ? b + 1 : 0
while in_ < input_length
# in_ is the index of the next character to be consumed, and
# out is the number of code points in the output array.
# Decode a generalized variable-length integer into delta,
# which gets added to i. The overflow checking is easier
# if we increase i as we go, then subtract off its starting
# value at the end to obtain delta.
oldi = i; w = 1; k = PUNYCODE_BASE
while true
if in_ >= input_length
raise PunycodeBadInput, "Input is invalid."
end
digit = punycode_decode_digit(input[in_])
in_+=1
if digit >= PUNYCODE_BASE
raise PunycodeBadInput, "Input is invalid."
end
if digit > (PUNYCODE_MAXINT - i) / w
raise PunycodeOverflow, "Input needs wider integers to process."
end
i += digit * w
t = (
if k <= bias
PUNYCODE_TMIN
elsif k >= bias + PUNYCODE_TMAX
PUNYCODE_TMAX
else
k - bias
end
)
break if digit < t
if w > PUNYCODE_MAXINT / (PUNYCODE_BASE - t)
raise PunycodeOverflow, "Input needs wider integers to process."
end
w *= PUNYCODE_BASE - t
k += PUNYCODE_BASE
end
bias = punycode_adapt(i - oldi, out + 1, oldi == 0)
# I was supposed to wrap around from out + 1 to 0,
# incrementing n each time, so we'll fix that now:
if i / (out + 1) > PUNYCODE_MAXINT - n
raise PunycodeOverflow, "Input needs wider integers to process."
end
n += i / (out + 1)
i %= out + 1
# Insert n at position i of the output:
# not needed for Punycode:
# raise PUNYCODE_INVALID_INPUT if decode_digit(n) <= base
if out >= max_out
raise PunycodeBigOutput, "Output would exceed the space provided."
end
#memmove(output + i + 1, output + i, (out - i) * sizeof *output)
output[i + 1, out - i] = output[i, out - i]
output[i] = n
i += 1
out += 1
end
output_length[0] = out
output.pack("U*")
end
private_class_method :punycode_decode
def self.punycode_basic?(codepoint)
codepoint < 0x80
end
private_class_method :punycode_basic?
def self.punycode_delimiter?(codepoint)
codepoint == PUNYCODE_DELIMITER
end
private_class_method :punycode_delimiter?
def self.punycode_encode_digit(d)
d + 22 + 75 * ((d < 26) ? 1 : 0)
end
private_class_method :punycode_encode_digit
# Returns the numeric value of a basic codepoint
# (for use in representing integers) in the range 0 to
# base - 1, or PUNYCODE_BASE if codepoint does not represent a value.
def self.punycode_decode_digit(codepoint)
if codepoint - 48 < 10
codepoint - 22
elsif codepoint - 65 < 26
codepoint - 65
elsif codepoint - 97 < 26
codepoint - 97
else
PUNYCODE_BASE
end
end
private_class_method :punycode_decode_digit
# Bias adaptation method
def self.punycode_adapt(delta, numpoints, firsttime)
delta = firsttime ? delta / PUNYCODE_DAMP : delta >> 1
# delta >> 1 is a faster way of doing delta / 2
delta += delta / numpoints
difference = PUNYCODE_BASE - PUNYCODE_TMIN
k = 0
while delta > (difference * PUNYCODE_TMAX) / 2
delta /= difference
k += PUNYCODE_BASE
end
k + (difference + 1) * delta / (delta + PUNYCODE_SKEW)
end
private_class_method :punycode_adapt
end
# :startdoc:
end

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +0,0 @@
# frozen_string_literal: true
# encoding:utf-8
#--
# Copyright (C) Bob Aman
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#++
# Used to prevent the class/module from being loaded more than once
if !defined?(Addressable::VERSION)
module Addressable
module VERSION
MAJOR = 2
MINOR = 7
TINY = 0
STRING = [MAJOR, MINOR, TINY].join('.')
end
end
end

View File

@ -1,300 +0,0 @@
# frozen_string_literal: true
# coding: utf-8
# Copyright (C) Bob Aman
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require "spec_helper"
# Have to use RubyGems to load the idn gem.
require "rubygems"
require "addressable/idna"
shared_examples_for "converting from unicode to ASCII" do
it "should convert 'www.google.com' correctly" do
expect(Addressable::IDNA.to_ascii("www.google.com")).to eq("www.google.com")
end
long = 'AcinusFallumTrompetumNullunCreditumVisumEstAtCuadLongumEtCefallum.com'
it "should convert '#{long}' correctly" do
expect(Addressable::IDNA.to_ascii(long)).to eq(long)
end
it "should convert 'www.詹姆斯.com' correctly" do
expect(Addressable::IDNA.to_ascii(
"www.詹姆斯.com"
)).to eq("www.xn--8ws00zhy3a.com")
end
it "should convert 'www.Iñtërnâtiônàlizætiøn.com' correctly" do
"www.Iñtërnâtiônàlizætiøn.com"
expect(Addressable::IDNA.to_ascii(
"www.I\xC3\xB1t\xC3\xABrn\xC3\xA2ti\xC3\xB4" +
"n\xC3\xA0liz\xC3\xA6ti\xC3\xB8n.com"
)).to eq("www.xn--itrntinliztin-vdb0a5exd8ewcye.com")
end
it "should convert 'www.Iñtërnâtiônàlizætiøn.com' correctly" do
expect(Addressable::IDNA.to_ascii(
"www.In\xCC\x83te\xCC\x88rna\xCC\x82tio\xCC\x82n" +
"a\xCC\x80liz\xC3\xA6ti\xC3\xB8n.com"
)).to eq("www.xn--itrntinliztin-vdb0a5exd8ewcye.com")
end
it "should convert " +
"'www.ほんとうにながいわけのわからないどめいんめいのらべるまだながくしないとたりない.w3.mag.keio.ac.jp' " +
"correctly" do
expect(Addressable::IDNA.to_ascii(
"www.\343\201\273\343\202\223\343\201\250\343\201\206\343\201\253\343" +
"\201\252\343\201\214\343\201\204\343\202\217\343\201\221\343\201\256" +
"\343\202\217\343\201\213\343\202\211\343\201\252\343\201\204\343\201" +
"\251\343\202\201\343\201\204\343\202\223\343\202\201\343\201\204\343" +
"\201\256\343\202\211\343\201\271\343\202\213\343\201\276\343\201\240" +
"\343\201\252\343\201\214\343\201\217\343\201\227\343\201\252\343\201" +
"\204\343\201\250\343\201\237\343\202\212\343\201\252\343\201\204." +
"w3.mag.keio.ac.jp"
)).to eq(
"www.xn--n8jaaaaai5bhf7as8fsfk3jnknefdde3" +
"fg11amb5gzdb4wi9bya3kc6lra.w3.mag.keio.ac.jp"
)
end
it "should convert " +
"'www.ほんとうにながいわけのわからないどめいんめいのらべるまだながくしないとたりない.w3.mag.keio.ac.jp' " +
"correctly" do
expect(Addressable::IDNA.to_ascii(
"www.\343\201\273\343\202\223\343\201\250\343\201\206\343\201\253\343" +
"\201\252\343\201\213\343\202\231\343\201\204\343\202\217\343\201\221" +
"\343\201\256\343\202\217\343\201\213\343\202\211\343\201\252\343\201" +
"\204\343\201\250\343\202\231\343\202\201\343\201\204\343\202\223\343" +
"\202\201\343\201\204\343\201\256\343\202\211\343\201\270\343\202\231" +
"\343\202\213\343\201\276\343\201\237\343\202\231\343\201\252\343\201" +
"\213\343\202\231\343\201\217\343\201\227\343\201\252\343\201\204\343" +
"\201\250\343\201\237\343\202\212\343\201\252\343\201\204." +
"w3.mag.keio.ac.jp"
)).to eq(
"www.xn--n8jaaaaai5bhf7as8fsfk3jnknefdde3" +
"fg11amb5gzdb4wi9bya3kc6lra.w3.mag.keio.ac.jp"
)
end
it "should convert '点心和烤鸭.w3.mag.keio.ac.jp' correctly" do
expect(Addressable::IDNA.to_ascii(
"点心和烤鸭.w3.mag.keio.ac.jp"
)).to eq("xn--0trv4xfvn8el34t.w3.mag.keio.ac.jp")
end
it "should convert '가각갂갃간갅갆갇갈갉힢힣.com' correctly" do
expect(Addressable::IDNA.to_ascii(
"가각갂갃간갅갆갇갈갉힢힣.com"
)).to eq("xn--o39acdefghijk5883jma.com")
end
it "should convert " +
"'\347\242\274\346\250\231\346\272\226\350" +
"\220\254\345\234\213\347\242\274.com' correctly" do
expect(Addressable::IDNA.to_ascii(
"\347\242\274\346\250\231\346\272\226\350" +
"\220\254\345\234\213\347\242\274.com"
)).to eq("xn--9cs565brid46mda086o.com")
end
it "should convert 'リ宠퐱〹.com' correctly" do
expect(Addressable::IDNA.to_ascii(
"\357\276\230\345\256\240\355\220\261\343\200\271.com"
)).to eq("xn--eek174hoxfpr4k.com")
end
it "should convert 'リ宠퐱卄.com' correctly" do
expect(Addressable::IDNA.to_ascii(
"\343\203\252\345\256\240\355\220\261\345\215\204.com"
)).to eq("xn--eek174hoxfpr4k.com")
end
it "should convert 'ᆵ' correctly" do
expect(Addressable::IDNA.to_ascii(
"\341\206\265"
)).to eq("xn--4ud")
end
it "should convert 'ᆵ' correctly" do
expect(Addressable::IDNA.to_ascii(
"\357\276\257"
)).to eq("xn--4ud")
end
it "should convert '🌹🌹🌹.ws' correctly" do
expect(Addressable::IDNA.to_ascii(
"\360\237\214\271\360\237\214\271\360\237\214\271.ws"
)).to eq("xn--2h8haa.ws")
end
it "should handle two adjacent '.'s correctly" do
expect(Addressable::IDNA.to_ascii(
"example..host"
)).to eq("example..host")
end
end
shared_examples_for "converting from ASCII to unicode" do
long = 'AcinusFallumTrompetumNullunCreditumVisumEstAtCuadLongumEtCefallum.com'
it "should convert '#{long}' correctly" do
expect(Addressable::IDNA.to_unicode(long)).to eq(long)
end
it "should return the identity conversion when punycode decode fails" do
expect(Addressable::IDNA.to_unicode("xn--zckp1cyg1.sblo.jp")).to eq(
"xn--zckp1cyg1.sblo.jp")
end
it "should return the identity conversion when the ACE prefix has no suffix" do
expect(Addressable::IDNA.to_unicode("xn--...-")).to eq("xn--...-")
end
it "should convert 'www.google.com' correctly" do
expect(Addressable::IDNA.to_unicode("www.google.com")).to eq(
"www.google.com")
end
it "should convert 'www.詹姆斯.com' correctly" do
expect(Addressable::IDNA.to_unicode(
"www.xn--8ws00zhy3a.com"
)).to eq("www.詹姆斯.com")
end
it "should convert '詹姆斯.com' correctly" do
expect(Addressable::IDNA.to_unicode(
"xn--8ws00zhy3a.com"
)).to eq("詹姆斯.com")
end
it "should convert 'www.iñtërnâtiônàlizætiøn.com' correctly" do
expect(Addressable::IDNA.to_unicode(
"www.xn--itrntinliztin-vdb0a5exd8ewcye.com"
)).to eq("www.iñtërnâtiônàlizætiøn.com")
end
it "should convert 'iñtërnâtiônàlizætiøn.com' correctly" do
expect(Addressable::IDNA.to_unicode(
"xn--itrntinliztin-vdb0a5exd8ewcye.com"
)).to eq("iñtërnâtiônàlizætiøn.com")
end
it "should convert " +
"'www.ほんとうにながいわけのわからないどめいんめいのらべるまだながくしないとたりない.w3.mag.keio.ac.jp' " +
"correctly" do
expect(Addressable::IDNA.to_unicode(
"www.xn--n8jaaaaai5bhf7as8fsfk3jnknefdde3" +
"fg11amb5gzdb4wi9bya3kc6lra.w3.mag.keio.ac.jp"
)).to eq(
"www.ほんとうにながいわけのわからないどめいんめいのらべるまだながくしないとたりない.w3.mag.keio.ac.jp"
)
end
it "should convert '点心和烤鸭.w3.mag.keio.ac.jp' correctly" do
expect(Addressable::IDNA.to_unicode(
"xn--0trv4xfvn8el34t.w3.mag.keio.ac.jp"
)).to eq("点心和烤鸭.w3.mag.keio.ac.jp")
end
it "should convert '가각갂갃간갅갆갇갈갉힢힣.com' correctly" do
expect(Addressable::IDNA.to_unicode(
"xn--o39acdefghijk5883jma.com"
)).to eq("가각갂갃간갅갆갇갈갉힢힣.com")
end
it "should convert " +
"'\347\242\274\346\250\231\346\272\226\350" +
"\220\254\345\234\213\347\242\274.com' correctly" do
expect(Addressable::IDNA.to_unicode(
"xn--9cs565brid46mda086o.com"
)).to eq(
"\347\242\274\346\250\231\346\272\226\350" +
"\220\254\345\234\213\347\242\274.com"
)
end
it "should convert 'リ宠퐱卄.com' correctly" do
expect(Addressable::IDNA.to_unicode(
"xn--eek174hoxfpr4k.com"
)).to eq("\343\203\252\345\256\240\355\220\261\345\215\204.com")
end
it "should convert 'ᆵ' correctly" do
expect(Addressable::IDNA.to_unicode(
"xn--4ud"
)).to eq("\341\206\265")
end
it "should convert '🌹🌹🌹.ws' correctly" do
expect(Addressable::IDNA.to_unicode(
"xn--2h8haa.ws"
)).to eq("\360\237\214\271\360\237\214\271\360\237\214\271.ws")
end
it "should handle two adjacent '.'s correctly" do
expect(Addressable::IDNA.to_unicode(
"example..host"
)).to eq("example..host")
end
it "should normalize 'string' correctly" do
expect(Addressable::IDNA.unicode_normalize_kc(:'string')).to eq("string")
expect(Addressable::IDNA.unicode_normalize_kc("string")).to eq("string")
end
end
describe Addressable::IDNA, "when using the pure-Ruby implementation" do
before do
Addressable.send(:remove_const, :IDNA)
load "addressable/idna/pure.rb"
end
it_should_behave_like "converting from unicode to ASCII"
it_should_behave_like "converting from ASCII to unicode"
begin
require "fiber"
it "should not blow up inside fibers" do
f = Fiber.new do
Addressable.send(:remove_const, :IDNA)
load "addressable/idna/pure.rb"
end
f.resume
end
rescue LoadError
# Fibers aren't supported in this version of Ruby, skip this test.
warn('Fibers unsupported.')
end
end
begin
require "idn"
describe Addressable::IDNA, "when using the native-code implementation" do
before do
Addressable.send(:remove_const, :IDNA)
load "addressable/idna/native.rb"
end
it_should_behave_like "converting from unicode to ASCII"
it_should_behave_like "converting from ASCII to unicode"
end
rescue LoadError
# Cannot test the native implementation without libidn support.
warn('Could not load native IDN implementation.')
end

View File

@ -1,30 +0,0 @@
# frozen_string_literal: true
# coding: utf-8
# Copyright (C) Bob Aman
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require "spec_helper"
require "addressable/uri"
require "net/http"
describe Net::HTTP do
it "should be compatible with Addressable" do
response_body =
Net::HTTP.get(Addressable::URI.parse('http://www.google.com/'))
expect(response_body).not_to be_nil
end
end

View File

@ -1,106 +0,0 @@
# frozen_string_literal: true
# coding: utf-8
# Copyright (C) Bob Aman
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require "spec_helper"
require "addressable/uri"
require "addressable/template"
require "rack/mount"
describe Rack::Mount do
let(:app_one) do
proc { |env| [200, {'Content-Type' => 'text/plain'}, 'Route 1'] }
end
let(:app_two) do
proc { |env| [200, {'Content-Type' => 'text/plain'}, 'Route 2'] }
end
let(:app_three) do
proc { |env| [200, {'Content-Type' => 'text/plain'}, 'Route 3'] }
end
let(:routes) do
s = Rack::Mount::RouteSet.new do |set|
set.add_route(app_one, {
:request_method => 'GET',
:path_info => Addressable::Template.new('/one/{id}/')
}, {:id => 'unidentified'}, :one)
set.add_route(app_two, {
:request_method => 'GET',
:path_info => Addressable::Template.new('/two/')
}, {:id => 'unidentified'}, :two)
set.add_route(app_three, {
:request_method => 'GET',
:path_info => Addressable::Template.new('/three/{id}/').to_regexp
}, {:id => 'unidentified'}, :three)
end
s.rehash
s
end
it "should generate from routes with Addressable::Template" do
path, _ = routes.generate(:path_info, :one, {:id => '123'})
expect(path).to eq '/one/123/'
end
it "should generate from routes with Addressable::Template using defaults" do
path, _ = routes.generate(:path_info, :one, {})
expect(path).to eq '/one/unidentified/'
end
it "should recognize routes with Addressable::Template" do
request = Rack::Request.new(
'REQUEST_METHOD' => 'GET',
'PATH_INFO' => '/one/123/'
)
route, _, params = routes.recognize(request)
expect(route).not_to be_nil
expect(route.app).to eq app_one
expect(params).to eq({id: '123'})
end
it "should generate from routes with Addressable::Template" do
path, _ = routes.generate(:path_info, :two, {:id => '654'})
expect(path).to eq '/two/'
end
it "should generate from routes with Addressable::Template using defaults" do
path, _ = routes.generate(:path_info, :two, {})
expect(path).to eq '/two/'
end
it "should recognize routes with Addressable::Template" do
request = Rack::Request.new(
'REQUEST_METHOD' => 'GET',
'PATH_INFO' => '/two/'
)
route, _, params = routes.recognize(request)
expect(route).not_to be_nil
expect(route.app).to eq app_two
expect(params).to eq({id: 'unidentified'})
end
it "should recognize routes with derived Regexp" do
request = Rack::Request.new(
'REQUEST_METHOD' => 'GET',
'PATH_INFO' => '/three/789/'
)
route, _, params = routes.recognize(request)
expect(route).not_to be_nil
expect(route.app).to eq app_three
expect(params).to eq({id: '789'})
end
end

View File

@ -1,59 +0,0 @@
# frozen_string_literal: true
# coding: utf-8
# Copyright (C) Bob Aman
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
require "spec_helper"
require "addressable/uri"
describe Addressable::URI, "when created with a URI known to cause crashes " +
"in certain browsers" do
it "should parse correctly" do
uri = Addressable::URI.parse('%%30%30')
expect(uri.path).to eq('%%30%30')
expect(uri.normalize.path).to eq('%2500')
end
it "should parse correctly as a full URI" do
uri = Addressable::URI.parse('http://www.example.com/%%30%30')
expect(uri.path).to eq('/%%30%30')
expect(uri.normalize.path).to eq('/%2500')
end
end
describe Addressable::URI, "when created with a URI known to cause crashes " +
"in certain browsers" do
it "should parse correctly" do
uri = Addressable::URI.parse('لُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ 冗')
expect(uri.path).to eq('لُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ 冗')
expect(uri.normalize.path).to eq(
'%D9%84%D9%8F%D8%B5%D9%91%D8%A8%D9%8F%D9%84%D9%8F%D9%84%D8%B5%D9%91' +
'%D8%A8%D9%8F%D8%B1%D8%B1%D9%8B%20%E0%A5%A3%20%E0%A5%A3h%20%E0%A5' +
'%A3%20%E0%A5%A3%20%E5%86%97'
)
end
it "should parse correctly as a full URI" do
uri = Addressable::URI.parse('http://www.example.com/لُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ 冗')
expect(uri.path).to eq('/لُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ 冗')
expect(uri.normalize.path).to eq(
'/%D9%84%D9%8F%D8%B5%D9%91%D8%A8%D9%8F%D9%84%D9%8F%D9%84%D8%B5%D9%91' +
'%D8%A8%D9%8F%D8%B1%D8%B1%D9%8B%20%E0%A5%A3%20%E0%A5%A3h%20%E0%A5' +
'%A3%20%E0%A5%A3%20%E5%86%97'
)
end
end

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +0,0 @@
# frozen_string_literal: true
require 'bundler/setup'
require 'rspec/its'
begin
require 'coveralls'
Coveralls.wear! do
add_filter "spec/"
add_filter "vendor/"
end
rescue LoadError
warn "warning: coveralls gem not found; skipping Coveralls"
require 'simplecov'
SimpleCov.start do
add_filter "spec/"
add_filter "vendor/"
end
end
RSpec.configure do |config|
config.warnings = true
config.filter_run_when_matching :focus
end

View File

@ -1,4 +0,0 @@
# frozen_string_literal: true
desc "Remove all build products"
task "clobber"

View File

@ -1,93 +0,0 @@
# frozen_string_literal: true
require "rubygems/package_task"
namespace :gem do
GEM_SPEC = Gem::Specification.new do |s|
s.name = PKG_NAME
s.version = PKG_VERSION
s.summary = PKG_SUMMARY
s.description = PKG_DESCRIPTION
s.files = PKG_FILES.to_a
s.has_rdoc = true
s.extra_rdoc_files = %w( README.md )
s.rdoc_options.concat ["--main", "README.md"]
if !s.respond_to?(:add_development_dependency)
puts "Cannot build Gem with this version of RubyGems."
exit(1)
end
s.required_ruby_version = ">= 2.0"
s.add_runtime_dependency "public_suffix", ">= 2.0.2", "< 5.0"
s.add_development_dependency "bundler", ">= 1.0", "< 3.0"
s.require_path = "lib"
s.author = "Bob Aman"
s.email = "bob@sporkmonger.com"
s.homepage = "https://github.com/sporkmonger/addressable"
s.license = "Apache-2.0"
end
Gem::PackageTask.new(GEM_SPEC) do |p|
p.gem_spec = GEM_SPEC
p.need_tar = true
p.need_zip = true
end
desc "Generates .gemspec file"
task :gemspec do
spec_string = GEM_SPEC.to_ruby
File.open("#{GEM_SPEC.name}.gemspec", "w") do |file|
file.write spec_string
end
end
desc "Show information about the gem"
task :debug do
puts GEM_SPEC.to_ruby
end
desc "Install the gem"
task :install => ["clobber", "gem:package"] do
sh "#{SUDO} gem install --local pkg/#{GEM_SPEC.full_name}"
end
desc "Uninstall the gem"
task :uninstall do
installed_list = Gem.source_index.find_name(PKG_NAME)
if installed_list &&
(installed_list.collect { |s| s.version.to_s}.include?(PKG_VERSION))
sh(
"#{SUDO} gem uninstall --version '#{PKG_VERSION}' " +
"--ignore-dependencies --executables #{PKG_NAME}"
)
end
end
desc "Reinstall the gem"
task :reinstall => [:uninstall, :install]
desc "Package for release"
task :release => ["gem:package", "gem:gemspec"] do |t|
v = ENV["VERSION"] or abort "Must supply VERSION=x.y.z"
abort "Versions don't match #{v} vs #{PROJ.version}" if v != PKG_VERSION
pkg = "pkg/#{GEM_SPEC.full_name}"
changelog = File.open("CHANGELOG.md") { |file| file.read }
puts "Releasing #{PKG_NAME} v. #{PKG_VERSION}"
Rake::Task["git:tag:create"].invoke
end
end
desc "Alias to gem:package"
task "gem" => "gem:package"
task "gem:release" => "gem:gemspec"
task "clobber" => ["gem:clobber_package"]

View File

@ -1,47 +0,0 @@
# frozen_string_literal: true
namespace :git do
namespace :tag do
desc "List tags from the Git repository"
task :list do
tags = `git tag -l`
tags.gsub!("\r", "")
tags = tags.split("\n").sort {|a, b| b <=> a }
puts tags.join("\n")
end
desc "Create a new tag in the Git repository"
task :create do
changelog = File.open("CHANGELOG.md", "r") { |file| file.read }
puts "-" * 80
puts changelog
puts "-" * 80
puts
v = ENV["VERSION"] or abort "Must supply VERSION=x.y.z"
abort "Versions don't match #{v} vs #{PKG_VERSION}" if v != PKG_VERSION
git_status = `git status`
if git_status !~ /^nothing to commit/
abort "Working directory isn't clean."
end
tag = "#{PKG_NAME}-#{PKG_VERSION}"
msg = "Release #{PKG_NAME}-#{PKG_VERSION}"
existing_tags = `git tag -l #{PKG_NAME}-*`.split('\n')
if existing_tags.include?(tag)
warn("Tag already exists, deleting...")
unless system "git tag -d #{tag}"
abort "Tag deletion failed."
end
end
puts "Creating git tag '#{tag}'..."
unless system "git tag -a -m \"#{msg}\" #{tag}"
abort "Tag creation failed."
end
end
end
end
task "gem:release" => "git:tag:create"

View File

@ -1,24 +0,0 @@
# frozen_string_literal: true
namespace :metrics do
task :lines do
lines, codelines, total_lines, total_codelines = 0, 0, 0, 0
for file_name in FileList["lib/**/*.rb"]
f = File.open(file_name)
while line = f.gets
lines += 1
next if line =~ /^\s*$/
next if line =~ /^\s*#/
codelines += 1
end
puts "L: #{sprintf("%4d", lines)}, " +
"LOC #{sprintf("%4d", codelines)} | #{file_name}"
total_lines += lines
total_codelines += codelines
lines, codelines = 0, 0
end
puts "Total: Lines #{total_lines}, LOC #{total_codelines}"
end
end

View File

@ -1,23 +0,0 @@
# frozen_string_literal: true
require "rspec/core/rake_task"
namespace :spec do
RSpec::Core::RakeTask.new(:simplecov) do |t|
t.pattern = FileList['spec/**/*_spec.rb']
t.rspec_opts = ['--color', '--format', 'documentation']
end
namespace :simplecov do
desc "Browse the code coverage report."
task :browse => "spec:simplecov" do
require "launchy"
Launchy.open("coverage/index.html")
end
end
end
desc "Alias to spec:simplecov"
task "spec" => "spec:simplecov"
task "clobber" => ["spec:clobber_simplecov"]

View File

@ -1,29 +0,0 @@
# frozen_string_literal: true
require "rake"
begin
require "yard"
require "yard/rake/yardoc_task"
namespace :doc do
desc "Generate Yardoc documentation"
YARD::Rake::YardocTask.new do |yardoc|
yardoc.name = "yard"
yardoc.options = ["--verbose", "--markup", "markdown"]
yardoc.files = FileList[
"lib/**/*.rb", "ext/**/*.c",
"README.md", "CHANGELOG.md", "LICENSE.txt"
].exclude(/idna/)
end
end
task "clobber" => ["doc:clobber_yard"]
desc "Alias to doc:yard"
task "doc" => "doc:yard"
rescue LoadError
# If yard isn't available, it's not the end of the world
desc "Alias to doc:rdoc"
task "doc" => "doc:rdoc"
end

View File

@ -1,11 +0,0 @@
source "https://rubygems.org"
gemspec
gem "rake"
group :development do
gem "rspec-helpers", :require => false
gem "luna-rspec-formatters", :require => false
gem "pry", :require => false unless ENV[
"CI"
]
end

View File

@ -1,25 +0,0 @@
## 1.1.0 / 2016-06-28
### Minor Enhancements
* Support jruby (#8)
## 1.0.0 / 2016-04-28
### Major enhancements
- Merge Simple::ANSI and Colorator. (#7)
### Minor Enhancements
- Delete unnecessary `Symbol#to_sym` (#2)
- Change argument name of `Enumerator#each` for better code legibility (#3)
### Development Fixes
- Convert to new RSpec expectation syntax (#1)
- Fix `String#blue` result in README (#4)
## 0.1 / 2013-04-13
Birthday!

View File

@ -1,21 +0,0 @@
The MIT License
Copyright (c) Parker Moore
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -1,47 +0,0 @@
# colorator
Colorize your text for the terminal
[![Build Status](https://travis-ci.org/octopress/colorator.png?branch=master)](https://travis-ci.org/octopress/colorator)
## Example
```ruby
"this string".red
# => \e[31mthis string\e[0m
"my string".blue
# => \e[34mmy string\e[0m
# etc...
```
## Supported Colors
- `red`
- `black`
- `green`
- `yellow`
- `magenta`
- `white`
- `blue`
- `cyan`
- `bold`
## Other supported Ansi methods
- `clear_line`
- `has_ansi?`, `has_color?`
- `strip_ansi`, `strip_color`
- `reset_ansi`, `reset_color`
- `clear_screen`
- `ansi_jump`
## Why
There are a bunch of gems that provide functionality like this, but none have
as simple an API as this. Just call `"string".color` and your text will be
colorized.
## License
MIT. Written as a single Ruby file by Brandon Mathis, converted into a gem by
Parker Moore.

View File

@ -1,6 +0,0 @@
require "bundler/gem_tasks"
require "rspec/core/rake_task"
RSpec::Core::RakeTask.new(:spec)
task :default => :spec

View File

@ -1,23 +0,0 @@
# coding: utf-8
require File.expand_path('lib/colorator.rb', __dir__)
Gem::Specification.new do |spec|
spec.name = "colorator"
spec.summary = "Colorize your text in the terminal."
spec.version = Colorator::VERSION
spec.authors = ["Parker Moore", "Brandon Mathis"]
spec.email = ["parkrmoore@gmail.com", "brandon@imathis.com"]
spec.homepage = "https://github.com/octopress/colorator"
spec.licenses = ["MIT"]
all = `git ls-files -z`.split("\x0").reject { |f| f.start_with?(".") }
spec.files = all.select { |f| File.basename(f) == f || f =~ %r{^(bin|lib)/} }
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.extra_rdoc_files = ["README.markdown", "LICENSE"]
spec.rdoc_options = ["--charset=UTF-8"]
spec.add_development_dependency "rspec", "~> 3.1"
end

View File

@ -1,111 +0,0 @@
$:.unshift File.dirname(__FILE__)
module Colorator
module_function
VERSION = "1.1.0"
# --------------------------------------------------------------------------
ANSI_MATCHR = /\x1b.*?[jkmsuABGKH]/
ANSI_COLORS = {
:black => 30,
:red => 31,
:green => 32,
:yellow => 33,
:blue => 34,
:magenta => 35,
:cyan => 36,
:white => 37,
:bold => 1
}
# --------------------------------------------------------------------------
# Allows you to check if a string currently has ansi.
# --------------------------------------------------------------------------
def has_ansi?(str)
str.match(ANSI_MATCHR).is_a?(
MatchData
)
end
# --------------------------------------------------------------------------
# Jump the cursor, moving it up and then back down to it's spot, allowing
# you to do fancy things like multiple output (downloads) the way that Docker
# does them in an async way without breaking term.
# --------------------------------------------------------------------------
def ansi_jump(str, num)
"\x1b[#{num}A#{clear_line(str)}\x1b[#{
num
}B"
end
# --------------------------------------------------------------------------
def reset_ansi(str = "")
"\x1b[0m#{
str
}"
end
# --------------------------------------------------------------------------
def clear_line(str = "")
"\x1b[2K\r#{
str
}"
end
# --------------------------------------------------------------------------
# Strip ANSI from the current string, making it just a normal string.
# --------------------------------------------------------------------------
def strip_ansi(str)
str.gsub(
ANSI_MATCHR, ""
)
end
# --------------------------------------------------------------------------
# Clear the screen's current view, so the user gets a clean output.
# --------------------------------------------------------------------------
def clear_screen(str = "")
"\x1b[H\x1b[2J#{
str
}"
end
# --------------------------------------------------------------------------
def colorize(str = "", color)
"\x1b[#{color}m#{str}\x1b[0m"
end
# --------------------------------------------------------------------------
Colorator::ANSI_COLORS.each do |color, code|
define_singleton_method color do |str|
colorize(
str, code
)
end
end
# --------------------------------------------------------------------------
class << self
alias reset_color reset_ansi
alias strip_color strip_ansi
alias has_color? has_ansi?
end
# --------------------------------------------------------------------------
CORE_METHODS = (
public_methods - Object.methods
)
end
require "colorator/core_ext"

View File

@ -1,9 +0,0 @@
class String
Colorator::CORE_METHODS.each do |method|
define_method method do |*args|
Colorator.public_send(method,
self, *args
)
end
end
end

View File

@ -1,478 +0,0 @@
## Current
## Release v1.1.5, edge v0.5.0 (10 mar 2019)
concurrent-ruby:
* fix potential leak of context on JRuby and Java 7
concurrent-ruby-edge:
* Add finalized Concurrent::Cancellation
* Add finalized Concurrent::Throttle
* Add finalized Concurrent::Promises::Channel
* Add new Concurrent::ErlangActor
## Release v1.1.4 (14 Dec 2018)
* (#780) Remove java_alias of 'submit' method of Runnable to let executor service work on java 11
* (#776) Fix NameError on defining a struct with a name which is already taken in an ancestor
## Release v1.1.3 (7 Nov 2018)
* (#775) fix partial require of the gem (although not officially supported)
## Release v1.1.2 (6 Nov 2018)
* (#773) more defensive 1.9.3 support
## Release v1.1.1, edge v0.4.1 (1 Nov 2018)
* (#768) add support for 1.9.3 back
## Release v1.1.0, edge v0.4.0 (31 OCt 2018) (yanked)
* (#768) yanked because of issues with removed 1.9.3 support
## Release v1.1.0.pre2, edge v0.4.0.pre2 (18 Sep 2018)
concurrent-ruby:
* fixed documentation and README links
* fix Set for TruffleRuby and Rubinius
* use properly supported TruffleRuby APIs
concurrent-ruby-edge:
* add Promises.zip_futures_over_on
## Release v1.1.0.pre1, edge v0.4.0.pre1 (15 Aug 2018)
concurrent-ruby:
* requires at least Ruby 2.0
* [Promises](http://ruby-concurrency.github.io/concurrent-ruby/1.1.0/Concurrent/Promises.html)
are moved from `concurrent-ruby-edge` to `concurrent-ruby`
* Add support for TruffleRuby
* (#734) Fix Array/Hash/Set construction broken on TruffleRuby
* AtomicReference fixed
* CI stabilization
* remove sharp dependency edge -> core
* remove warnings
* documentation updates
* Exchanger is no longer documented as edge since it was already available in
`concurrent-ruby`
* (#644) Fix Map#each and #each_pair not returning enumerator outside of MRI
* (#659) Edge promises fail during error handling
* (#741) Raise on recursive Delay#value call
* (#727) #717 fix global IO executor on JRuby
* (#740) Drop support for CRuby 1.9, JRuby 1.7, Rubinius.
* (#737) Move AtomicMarkableReference out of Edge
* (#708) Prefer platform specific memory barriers
* (#735) Fix wrong expected exception in channel spec assertion
* (#729) Allow executor option in `Promise#then`
* (#725) fix timeout check to use timeout_interval
* (#719) update engine detection
* (#660) Add specs for Promise#zip/Promise.zip ordering
* (#654) Promise.zip execution changes
* (#666) Add thread safe set implementation
* (#651) #699 #to_s, #inspect should not output negative object IDs.
* (#685) Avoid RSpec warnings about raise_error
* (#680) Avoid RSpec monkey patching, persist spec results locally, use RSpec
v3.7.0
* (#665) Initialize the monitor for new subarrays on Rubinius
* (#661) Fix error handling in edge promises
concurrent-ruby-edge:
* (#659) Edge promises fail during error handling
* Edge files clearly separated in `lib-edge`
* added ReInclude
## Release v1.0.5, edge v0.3.1 (26 Feb 2017)
concurrent-ruby:
* Documentation for Event and Semaphore
* Use Unsafe#fullFence and #loadFence directly since the shortcuts were removed in JRuby
* Do not depend on org.jruby.util.unsafe.UnsafeHolder
concurrent-ruby-edge:
* (#620) Actors on Pool raise an error
* (#624) Delayed promises did not interact correctly with flatting
* Fix arguments yielded by callback methods
* Overridable default executor in promises factory methods
* Asking actor to terminate will always resolve to `true`
## Release v1.0.4, edge v0.3.0 (27 Dec 2016)
concurrent-ruby:
* Nothing
concurrent-ruby-edge:
* New promises' API renamed, lots of improvements, edge bumped to 0.3.0
* **Incompatible** with previous 0.2.3 version
* see https://github.com/ruby-concurrency/concurrent-ruby/pull/522
## Release v1.0.3 (17 Dec 2016)
* Trigger execution of flattened delayed futures
* Avoid forking for processor_count if possible
* Semaphore Mutex and JRuby parity
* Adds Map#each as alias to Map#each_pair
* Fix uninitialized instance variables
* Make Fixnum, Bignum merger ready
* Allows Promise#then to receive an executor
* TimerSet now survives a fork
* Reject promise on any exception
* Allow ThreadLocalVar to be initialized with a block
* Support Alpha with `Concurrent::processor_count`
* Fixes format-security error when compiling ruby_193_compatible.h
* Concurrent::Atom#swap fixed: reraise the exceptions from block
## Release v1.0.2 (2 May 2016)
* Fix bug with `Concurrent::Map` MRI backend `#inspect` method
* Fix bug with `Concurrent::Map` MRI backend using `Hash#value?`
* Improved documentation and examples
* Minor updates to Edge
## Release v1.0.1 (27 February 2016)
* Fix "uninitialized constant Concurrent::ReentrantReadWriteLock" error.
* Better handling of `autoload` vs. `require`.
* Improved API for Edge `Future` zipping.
* Fix reference leak in Edge `Future` constructor .
* Fix bug which prevented thread pools from surviving a `fork`.
* Fix bug in which `TimerTask` did not correctly specify all its dependencies.
* Improved support for JRuby+Truffle
* Improved error messages.
* Improved documentation.
* Updated README and CONTRIBUTING.
## Release v1.0.0 (13 November 2015)
* Rename `attr_volatile_with_cas` to `attr_atomic`
* Add `clear_each` to `LockFreeStack`
* Update `AtomicReference` documentation
* Further updates and improvements to the synchronization layer.
* Performance and memory usage performance with `Actor` logging.
* Fixed `ThreadPoolExecutor` task count methods.
* Improved `Async` performance for both short and long-lived objects.
* Fixed bug in `LockFreeLinkedSet`.
* Fixed bug in which `Agent#await` triggered a validation failure.
* Further `Channel` updates.
* Adopted a project Code of Conduct
* Cleared interpreter warnings
* Fixed bug in `ThreadPoolExecutor` task count methods
* Fixed bug in 'LockFreeLinkedSet'
* Improved Java extension loading
* Handle Exception children in Edge::Future
* Continued improvements to channel
* Removed interpreter warnings.
* Shared constants now in `lib/concurrent/constants.rb`
* Refactored many tests.
* Improved synchronization layer/memory model documentation.
* Bug fix in Edge `Future#flat`
* Brand new `Channel` implementation in Edge gem.
* Simplification of `RubySingleThreadExecutor`
* `Async` improvements
- Each object uses its own `SingleThreadExecutor` instead of the global thread pool.
- No longers supports executor injection
- Much better documentation
* `Atom` updates
- No longer `Dereferenceable`
- Now `Observable`
- Added a `#reset` method
* Brand new `Agent` API and implementation. Now functionally equivalent to Clojure.
* Continued improvements to the synchronization layer
* Merged in the `thread_safe` gem
- `Concurrent::Array`
- `Concurrent::Hash`
- `Concurrent::Map` (formerly ThreadSafe::Cache)
- `Concurrent::Tuple`
* Minor improvements to Concurrent::Map
* Complete rewrite of `Exchanger`
* Removed all deprecated code (classes, methods, constants, etc.)
* Updated Agent, MutexAtomic, and BufferedChannel to inherit from Synchronization::Object.
* Many improved tests
* Some internal reorganization
## Release v0.9.1 (09 August 2015)
* Fixed a Rubiniux bug in synchronization object
* Fixed all interpreter warnings (except circular references)
* Fixed require statements when requiring `Atom` alone
* Significantly improved `ThreadLocalVar` on non-JRuby platforms
* Fixed error handling in Edge `Concurrent.zip`
* `AtomicFixnum` methods `#increment` and `#decrement` now support optional delta
* New `AtomicFixnum#update` method
* Minor optimizations in `ReadWriteLock`
* New `ReentrantReadWriteLock` class
* `ThreadLocalVar#bind` method is now public
* Refactored many tests
## Release v0.9.0 (10 July 2015)
* Updated `AtomicReference`
- `AtomicReference#try_update` now simply returns instead of raising exception
- `AtomicReference#try_update!` was added to raise exceptions if an update
fails. Note: this is the same behavior as the old `try_update`
* Pure Java implementations of
- `AtomicBoolean`
- `AtomicFixnum`
- `Semaphore`
* Fixed bug when pruning Ruby thread pools
* Fixed bug in time calculations within `ScheduledTask`
* Default `count` in `CountDownLatch` to 1
* Use monotonic clock for all timers via `Concurrent.monotonic_time`
- Use `Process.clock_gettime(Process::CLOCK_MONOTONIC)` when available
- Fallback to `java.lang.System.nanoTime()` on unsupported JRuby versions
- Pure Ruby implementation for everything else
- Effects `Concurrent.timer`, `Concurrent.timeout`, `TimerSet`, `TimerTask`, and `ScheduledTask`
* Deprecated all clock-time based timer scheduling
- Only support scheduling by delay
- Effects `Concurrent.timer`, `TimerSet`, and `ScheduledTask`
* Added new `ReadWriteLock` class
* Consistent `at_exit` behavior for Java and Ruby thread pools.
* Added `at_exit` handler to Ruby thread pools (already in Java thread pools)
- Ruby handler stores the object id and retrieves from `ObjectSpace`
- JRuby disables `ObjectSpace` by default so that handler stores the object reference
* Added a `:stop_on_exit` option to thread pools to enable/disable `at_exit` handler
* Updated thread pool docs to better explain shutting down thread pools
* Simpler `:executor` option syntax for all abstractions which support this option
* Added `Executor#auto_terminate?` predicate method (for thread pools)
* Added `at_exit` handler to `TimerSet`
* Simplified auto-termination of the global executors
- Can now disable auto-termination of global executors
- Added shutdown/kill/wait_for_termination variants for global executors
* Can now disable auto-termination for *all* executors (the nuclear option)
* Simplified auto-termination of the global executors
* Deprecated terms "task pool" and "operation pool"
- New terms are "io executor" and "fast executor"
- New functions added with new names
- Deprecation warnings added to functions referencing old names
* Moved all thread pool related functions from `Concurrent::Configuration` to `Concurrent`
- Old functions still exist with deprecation warnings
- New functions have updated names as appropriate
* All high-level abstractions default to the "io executor"
* Fixed bug in `Actor` causing it to prematurely warm global thread pools on gem load
- This also fixed a `RejectedExecutionError` bug when running with minitest/autorun via JRuby
* Moved global logger up to the `Concurrent` namespace and refactored the code
* Optimized the performance of `Delay`
- Fixed a bug in which no executor option on construction caused block execution on a global thread pool
* Numerous improvements and bug fixes to `TimerSet`
* Fixed deadlock of `Future` when the handler raises Exception
* Added shared specs for more classes
* New concurrency abstractions including:
- `Atom`
- `Maybe`
- `ImmutableStruct`
- `MutableStruct`
- `SettableStruct`
* Created an Edge gem for unstable abstractions including
- `Actor`
- `Agent`
- `Channel`
- `Exchanger`
- `LazyRegister`
- **new Future Framework** <http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Edge.html> - unified
implementation of Futures and Promises which combines Features of previous `Future`,
`Promise`, `IVar`, `Event`, `Probe`, `dataflow`, `Delay`, `TimerTask` into single framework. It uses extensively
new synchronization layer to make all the paths **lock-free** with exception of blocking threads on `#wait`.
It offers better performance and does not block threads when not required.
* Actor framework changes:
- fixed reset loop in Pool
- Pool can use any actor as a worker, abstract worker class is no longer needed.
- Actor events not have format `[:event_name, *payload]` instead of just the Symbol.
- Actor now uses new Future/Promise Framework instead of `IVar` for better interoperability
- Behaviour definition array was simplified to `[BehaviourClass1, [BehaviourClass2, *initialization_args]]`
- Linking behavior responds to :linked message by returning array of linked actors
- Supervised behavior is removed in favour of just Linking
- RestartingContext is supervised by default now, `supervise: true` is not required any more
- Events can be private and public, so far only difference is that Linking will
pass to linked actors only public messages. Adding private :restarting and
:resetting events which are send before the actor restarts or resets allowing
to add callbacks to cleanup current child actors.
- Print also object_id in Reference to_s
- Add AbstractContext#default_executor to be able to override executor class wide
- Add basic IO example
- Documentation somewhat improved
- All messages should have same priority. It's now possible to send `actor << job1 << job2 << :terminate!` and
be sure that both jobs are processed first.
* Refactored `Channel` to use newer synchronization objects
* Added `#reset` and `#cancel` methods to `TimerSet`
* Added `#cancel` method to `Future` and `ScheduledTask`
* Refactored `TimerSet` to use `ScheduledTask`
* Updated `Async` with a factory that initializes the object
* Deprecated `Concurrent.timer` and `Concurrent.timeout`
* Reduced max threads on pure-Ruby thread pools (abends around 14751 threads)
* Moved many private/internal classes/modules into "namespace" modules
* Removed brute-force killing of threads in tests
* Fixed a thread pool bug when the operating system cannot allocate more threads
## Release v0.8.0 (25 January 2015)
* C extension for MRI have been extracted into the `concurrent-ruby-ext` companion gem.
Please see the README for more detail.
* Better variable isolation in `Promise` and `Future` via an `:args` option
* Continued to update intermittently failing tests
## Release v0.7.2 (24 January 2015)
* New `Semaphore` class based on [java.util.concurrent.Semaphore](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html)
* New `Promise.all?` and `Promise.any?` class methods
* Renamed `:overflow_policy` on thread pools to `:fallback_policy`
* Thread pools still accept the `:overflow_policy` option but display a warning
* Thread pools now implement `fallback_policy` behavior when not running (rather than universally rejecting tasks)
* Fixed minor `set_deref_options` constructor bug in `Promise` class
* Fixed minor `require` bug in `ThreadLocalVar` class
* Fixed race condition bug in `TimerSet` class
* Fixed race condition bug in `TimerSet` class
* Fixed signal bug in `TimerSet#post` method
* Numerous non-functional updates to clear warning when running in debug mode
* Fixed more intermittently failing tests
* Tests now run on new Travis build environment
* Multiple documentation updates
## Release v0.7.1 (4 December 2014)
Please see the [roadmap](https://github.com/ruby-concurrency/concurrent-ruby/issues/142) for more information on the next planned release.
* Added `flat_map` method to `Promise`
* Added `zip` method to `Promise`
* Fixed bug with logging in `Actor`
* Improvements to `Promise` tests
* Removed actor-experimental warning
* Added an `IndirectImmediateExecutor` class
* Allow disabling auto termination of global executors
* Fix thread leaking in `ThreadLocalVar` (uses `Ref` gem on non-JRuby systems)
* Fix thread leaking when pruning pure-Ruby thread pools
* Prevent `Actor` from using an `ImmediateExecutor` (causes deadlock)
* Added missing synchronizations to `TimerSet`
* Fixed bug with return value of `Concurrent::Actor::Utils::Pool#ask`
* Fixed timing bug in `TimerTask`
* Fixed bug when creating a `JavaThreadPoolExecutor` with minimum pool size of zero
* Removed confusing warning when not using native extenstions
* Improved documentation
## Release v0.7.0 (13 August 2014)
* Merge the [atomic](https://github.com/ruby-concurrency/atomic) gem
- Pure Ruby `MutexAtomic` atomic reference class
- Platform native atomic reference classes `CAtomic`, `JavaAtomic`, and `RbxAtomic`
- Automated [build process](https://github.com/ruby-concurrency/rake-compiler-dev-box)
- Fat binary releases for [multiple platforms](https://rubygems.org/gems/concurrent-ruby/versions) including Windows (32/64), Linux (32/64), OS X (64-bit), Solaris (64-bit), and JRuby
* C native `CAtomicBoolean`
* C native `CAtomicFixnum`
* Refactored intermittently failing tests
* Added `dataflow!` and `dataflow_with!` methods to match `Future#value!` method
* Better handling of timeout in `Agent`
* Actor Improvements
- Fine-grained implementation using chain of behaviors. Each behavior is responsible for single aspect like: `Termination`, `Pausing`, `Linking`, `Supervising`, etc. Users can create custom Actors easily based on their needs.
- Supervision was added. `RestartingContext` will pause on error waiting on its supervisor to decide what to do next ( options are `:terminate!`, `:resume!`, `:reset!`, `:restart!`). Supervising behavior also supports strategies `:one_for_one` and `:one_for_all`.
- Linking was added to be able to monitor actor's events like: `:terminated`, `:paused`, `:restarted`, etc.
- Dead letter routing added. Rejected envelopes are collected in a configurable actor (default: `Concurrent::Actor.root.ask!(:dead_letter_routing)`)
- Old `Actor` class removed and replaced by new implementation previously called `Actress`. `Actress` was kept as an alias for `Actor` to keep compatibility.
- `Utils::Broadcast` actor which allows Publishsubscribe pattern.
* More executors for managing serialized operations
- `SerializedExecution` mixin module
- `SerializedExecutionDelegator` for serializing *any* executor
* Updated `Async` with serialized execution
* Updated `ImmediateExecutor` and `PerThreadExecutor` with full executor service lifecycle
* Added a `Delay` to root `Actress` initialization
* Minor bug fixes to thread pools
* Refactored many intermittently failing specs
* Removed Java interop warning `executor.rb:148 warning: ambiguous Java methods found, using submit(java.lang.Runnable)`
* Fixed minor bug in `RubyCachedThreadPool` overflow policy
* Updated tests to use [RSpec 3.0](http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3)
* Removed deprecated `Actor` class
* Better support for Rubinius
## Release v0.6.1 (14 June 2014)
* Many improvements to `Concurrent::Actress`
* Bug fixes to `Concurrent::RubyThreadPoolExecutor`
* Fixed several brittle tests
* Moved documentation to http://ruby-concurrency.github.io/concurrent-ruby/frames.html
## Release v0.6.0 (25 May 2014)
* Added `Concurrent::Observable` to encapsulate our thread safe observer sets
* Improvements to new `Channel`
* Major improvements to `CachedThreadPool` and `FixedThreadPool`
* Added `SingleThreadExecutor`
* Added `Current::timer` function
* Added `TimerSet` executor
* Added `AtomicBoolean`
* `ScheduledTask` refactoring
* Pure Ruby and JRuby-optimized `PriorityQueue` classes
* Updated `Agent` behavior to more closely match Clojure
* Observer sets support block callbacks to the `add_observer` method
* New algorithm for thread creation in `RubyThreadPoolExecutor`
* Minor API updates to `Event`
* Rewritten `TimerTask` now an `Executor` instead of a `Runnable`
* Fixed many brittle specs
* Renamed `FixedThreadPool` and `CachedThreadPool` to `RubyFixedThreadPool` and `RubyCachedThreadPool`
* Created JRuby optimized `JavaFixedThreadPool` and `JavaCachedThreadPool`
* Consolidated fixed thread pool tests into `spec/concurrent/fixed_thread_pool_shared.rb` and `spec/concurrent/cached_thread_pool_shared.rb`
* `FixedThreadPool` now subclasses `RubyFixedThreadPool` or `JavaFixedThreadPool` as appropriate
* `CachedThreadPool` now subclasses `RubyCachedThreadPool` or `JavaCachedThreadPool` as appropriate
* New `Delay` class
* `Concurrent::processor_count` helper function
* New `Async` module
* Renamed `NullThreadPool` to `PerThreadExecutor`
* Deprecated `Channel` (we are planning a new implementation based on [Go](http://golangtutorials.blogspot.com/2011/06/channels-in-go.html))
* Added gem-level [configuration](http://robots.thoughtbot.com/mygem-configure-block)
* Deprecated `$GLOBAL_THREAD_POOL` in lieu of gem-level configuration
* Removed support for Ruby [1.9.2](https://www.ruby-lang.org/en/news/2013/12/17/maintenance-of-1-8-7-and-1-9-2/)
* New `RubyThreadPoolExecutor` and `JavaThreadPoolExecutor` classes
* All thread pools now extend the appropriate thread pool executor classes
* All thread pools now support `:overflow_policy` (based on Java's [reject policies](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html))
* Deprecated `UsesGlobalThreadPool` in lieu of explicit `:executor` option (dependency injection) on `Future`, `Promise`, and `Agent`
* Added `Concurrent::dataflow_with(executor, *inputs)` method to support executor dependency injection for dataflow
* Software transactional memory with `TVar` and `Concurrent::atomically`
* First implementation of [new, high-performance](https://github.com/ruby-concurrency/concurrent-ruby/pull/49) `Channel`
* `Actor` is deprecated in favor of new experimental actor implementation [#73](https://github.com/ruby-concurrency/concurrent-ruby/pull/73). To avoid namespace collision it is living in `Actress` namespace until `Actor` is removed in next release.
## Release v0.5.0
This is the most significant release of this gem since its inception. This release includes many improvements and optimizations. It also includes several bug fixes. The major areas of focus for this release were:
* Stability improvements on Ruby versions with thread-level parallelism ([JRuby](http://jruby.org/) and [Rubinius](http://rubini.us/))
* Creation of new low-level concurrency abstractions
* Internal refactoring to use the new low-level abstractions
Most of these updates had no effect on the gem API. There are a few notable exceptions which were unavoidable. Please read the [release notes](API-Updates-in-v0.5.0) for more information.
Specific changes include:
* New class `IVar`
* New class `MVar`
* New class `ThreadLocalVar`
* New class `AtomicFixnum`
* New class method `dataflow`
* New class `Condition`
* New class `CountDownLatch`
* New class `DependencyCounter`
* New class `SafeTaskExecutor`
* New class `CopyOnNotifyObserverSet`
* New class `CopyOnWriteObserverSet`
* `Future` updated with `execute` API
* `ScheduledTask` updated with `execute` API
* New `Promise` API
* `Future` now extends `IVar`
* `Postable#post?` now returns an `IVar`
* Thread safety fixes to `Dereferenceable`
* Thread safety fixes to `Obligation`
* Thread safety fixes to `Supervisor`
* Thread safety fixes to `Event`
* Various other thread safety (race condition) fixes
* Refactored brittle tests
* Implemented pending tests
* Added JRuby and Rubinius as Travis CI build targets
* Added [CodeClimate](https://codeclimate.com/) code review
* Improved YARD documentation

View File

@ -1,41 +0,0 @@
source 'https://rubygems.org'
require File.join(File.dirname(__FILE__), 'lib/concurrent/version')
require File.join(File.dirname(__FILE__ ), 'lib-edge/concurrent/edge/version')
no_path = ENV['NO_PATH']
options = no_path ? {} : { path: '.' }
gem 'concurrent-ruby', Concurrent::VERSION, options
gem 'concurrent-ruby-edge', Concurrent::EDGE_VERSION, options
gem 'concurrent-ruby-ext', Concurrent::VERSION, options.merge(platform: :mri)
group :development do
gem 'rake', '~> 12.0'
gem 'rake-compiler', '~> 1.0', '>= 1.0.7'
gem 'rake-compiler-dock', '~> 0.7.0'
gem 'pry', '~> 0.11', platforms: :mri
end
group :documentation, optional: true do
gem 'yard', '~> 0.9.0', require: false
gem 'redcarpet', '~> 3.0', platforms: :mri # understands github markdown
gem 'md-ruby-eval', '~> 0.6'
end
group :testing do
gem 'rspec', '~> 3.7'
gem 'timecop', '~> 0.7.4'
gem 'sigdump', require: false
end
# made opt-in since it will not install on jruby 1.7
group :coverage, optional: !ENV['COVERAGE'] do
gem 'simplecov', '~> 0.16.0', require: false
gem 'coveralls', '~> 0.8.2', require: false
end
group :benchmarks, optional: true do
gem 'benchmark-ips', '~> 2.7'
gem 'bench9000'
end

View File

@ -1,23 +0,0 @@
```
Copyright (c) Jerry D'Antonio -- released under the MIT license.
http://www.opensource.org/licenses/mit-license.php
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
```

View File

@ -1,381 +0,0 @@
# Concurrent Ruby
[![Gem Version](https://badge.fury.io/rb/concurrent-ruby.svg)](http://badge.fury.io/rb/concurrent-ruby)
[![Build Status](https://travis-ci.org/ruby-concurrency/concurrent-ruby.svg?branch=master)](https://travis-ci.org/ruby-concurrency/concurrent-ruby)
[![Build status](https://ci.appveyor.com/api/projects/status/iq8aboyuu3etad4w?svg=true)](https://ci.appveyor.com/project/rubyconcurrency/concurrent-ruby)
[![License](https://img.shields.io/badge/license-MIT-green.svg)](http://opensource.org/licenses/MIT)
[![Gitter chat](https://img.shields.io/badge/IRC%20(gitter)-devs%20%26%20users-brightgreen.svg)](https://gitter.im/ruby-concurrency/concurrent-ruby)
Modern concurrency tools for Ruby. Inspired by
[Erlang](http://www.erlang.org/doc/reference_manual/processes.html),
[Clojure](http://clojure.org/concurrent_programming),
[Scala](http://akka.io/),
[Haskell](http://www.haskell.org/haskellwiki/Applications_and_libraries/Concurrency_and_parallelism#Concurrent_Haskell),
[F#](http://blogs.msdn.com/b/dsyme/archive/2010/02/15/async-and-parallel-design-patterns-in-f-part-3-agents.aspx),
[C#](http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx),
[Java](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/package-summary.html),
and classic concurrency patterns.
<img src="https://raw.githubusercontent.com/ruby-concurrency/concurrent-ruby/master/docs-source/logo/concurrent-ruby-logo-300x300.png" align="right" style="margin-left: 20px;" />
The design goals of this gem are:
* Be an 'unopinionated' toolbox that provides useful utilities without debating which is better
or why
* Remain free of external gem dependencies
* Stay true to the spirit of the languages providing inspiration
* But implement in a way that makes sense for Ruby
* Keep the semantics as idiomatic Ruby as possible
* Support features that make sense in Ruby
* Exclude features that don't make sense in Ruby
* Be small, lean, and loosely coupled
* Thread-safety
* Backward compatibility
## Contributing
**This gem depends on
[contributions](https://github.com/ruby-concurrency/concurrent-ruby/graphs/contributors) and we
appreciate your help. Would you like to contribute? Great! Have a look at
[issues with `looking-for-contributor` label](https://github.com/ruby-concurrency/concurrent-ruby/issues?q=is%3Aissue+is%3Aopen+label%3Alooking-for-contributor).** And if you pick something up let us know on the issue.
## Thread Safety
*Concurrent Ruby makes one of the strongest thread safety guarantees of any Ruby concurrency
library, providing consistent behavior and guarantees on all four of the main Ruby interpreters
(MRI/CRuby, JRuby, Rubinius, TruffleRuby).*
Every abstraction in this library is thread safe. Specific thread safety guarantees are documented
with each abstraction.
It is critical to remember, however, that Ruby is a language of mutable references. *No*
concurrency library for Ruby can ever prevent the user from making thread safety mistakes (such as
sharing a mutable object between threads and modifying it on both threads) or from creating
deadlocks through incorrect use of locks. All the library can do is provide safe abstractions which
encourage safe practices. Concurrent Ruby provides more safe concurrency abstractions than any
other Ruby library, many of which support the mantra of
["Do not communicate by sharing memory; instead, share memory by communicating"](https://blog.golang.org/share-memory-by-communicating).
Concurrent Ruby is also the only Ruby library which provides a full suite of thread safe and
immutable variable types and data structures.
We've also initiated discussion to document [memory model](docs-source/synchronization.md) of Ruby which
would provide consistent behaviour and guarantees on all four of the main Ruby interpreters
(MRI/CRuby, JRuby, Rubinius, TruffleRuby).
## Features & Documentation
**The primary site for documentation is the automatically generated
[API documentation](http://ruby-concurrency.github.io/concurrent-ruby/index.html) which is up to
date with latest release.** This readme matches the master so may contain new stuff not yet
released.
We also have a [IRC (gitter)](https://gitter.im/ruby-concurrency/concurrent-ruby).
### Versioning
* `concurrent-ruby` uses [Semantic Versioning](http://semver.org/)
* `concurrent-ruby-ext` has always same version as `concurrent-ruby`
* `concurrent-ruby-edge` will always be 0.y.z therefore following
[point 4](http://semver.org/#spec-item-4) applies *"Major version zero
(0.y.z) is for initial development. Anything may change at any time. The
public API should not be considered stable."* However we additionally use
following rules:
* Minor version increment means incompatible changes were made
* Patch version increment means only compatible changes were made
#### General-purpose Concurrency Abstractions
* [Async](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Async.html):
A mixin module that provides simple asynchronous behavior to a class. Loosely based on Erlang's
[gen_server](http://www.erlang.org/doc/man/gen_server.html).
* [ScheduledTask](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ScheduledTask.html):
Like a Future scheduled for a specific future time.
* [TimerTask](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/TimerTask.html):
A Thread that periodically wakes up to perform work at regular intervals.
* [Promises](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Promises.html):
Unified implementation of futures and promises which combines features of previous `Future`,
`Promise`, `IVar`, `Event`, `dataflow`, `Delay`, and (partially) `TimerTask` into a single
framework. It extensively uses the new synchronization layer to make all the features
**non-blocking** and **lock-free**, with the exception of obviously blocking operations like
`#wait`, `#value`. It also offers better performance.
#### Thread-safe Value Objects, Structures, and Collections
Collection classes that were originally part of the (deprecated) `thread_safe` gem:
* [Array](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Array.html) A thread-safe
subclass of Ruby's standard [Array](http://ruby-doc.org/core-2.2.0/Array.html).
* [Hash](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Hash.html) A thread-safe
subclass of Ruby's standard [Hash](http://ruby-doc.org/core-2.2.0/Hash.html).
* [Set](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Set.html) A thread-safe
subclass of Ruby's standard [Set](http://ruby-doc.org/stdlib-2.4.0/libdoc/set/rdoc/Set.html).
* [Map](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Map.html) A hash-like object
that should have much better performance characteristics, especially under high concurrency,
than `Concurrent::Hash`.
* [Tuple](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Tuple.html) A fixed size
array with volatile (synchronized, thread safe) getters/setters.
Value objects inspired by other languages:
* [Maybe](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Maybe.html) A thread-safe,
immutable object representing an optional value, based on
[Haskell Data.Maybe](https://hackage.haskell.org/package/base-4.2.0.1/docs/Data-Maybe.html).
Structure classes derived from Ruby's [Struct](http://ruby-doc.org/core-2.2.0/Struct.html):
* [ImmutableStruct](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ImmutableStruct.html)
Immutable struct where values are set at construction and cannot be changed later.
* [MutableStruct](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/MutableStruct.html)
Synchronized, mutable struct where values can be safely changed at any time.
* [SettableStruct](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/SettableStruct.html)
Synchronized, write-once struct where values can be set at most once, either at construction
or any time thereafter.
Thread-safe variables:
* [Agent](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Agent.html): A way to
manage shared, mutable, *asynchronous*, independent state. Based on Clojure's
[Agent](http://clojure.org/agents).
* [Atom](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Atom.html): A way to manage
shared, mutable, *synchronous*, independent state. Based on Clojure's
[Atom](http://clojure.org/atoms).
* [AtomicBoolean](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/AtomicBoolean.html)
A boolean value that can be updated atomically.
* [AtomicFixnum](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/AtomicFixnum.html)
A numeric value that can be updated atomically.
* [AtomicReference](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/AtomicReference.html)
An object reference that may be updated atomically.
* [Exchanger](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Exchanger.html)
A synchronization point at which threads can pair and swap elements within pairs. Based on
Java's [Exchanger](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Exchanger.html).
* [MVar](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/MVar.html) A synchronized
single element container. Based on Haskell's
[MVar](https://hackage.haskell.org/package/base-4.8.1.0/docs/Control-Concurrent-MVar.html) and
Scala's [MVar](http://docs.typelevel.org/api/scalaz/nightly/index.html#scalaz.concurrent.MVar$).
* [ThreadLocalVar](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ThreadLocalVar.html)
A variable where the value is different for each thread.
* [TVar](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/TVar.html) A transactional
variable implementing software transactional memory (STM). Based on Clojure's
[Ref](http://clojure.org/refs).
#### Java-inspired ThreadPools and Other Executors
* See the [thread pool](http://ruby-concurrency.github.io/concurrent-ruby/master/file.thread_pools.html)
overview, which also contains a list of other Executors available.
#### Thread Synchronization Classes and Algorithms
* [CountDownLatch](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/CountDownLatch.html)
A synchronization object that allows one thread to wait on multiple other threads.
* [CyclicBarrier](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/CyclicBarrier.html)
A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.
* [Event](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Event.html) Old school
kernel-style event.
* [ReadWriteLock](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ReadWriteLock.html)
A lock that supports multiple readers but only one writer.
* [ReentrantReadWriteLock](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ReentrantReadWriteLock.html)
A read/write lock with reentrant and upgrade features.
* [Semaphore](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Semaphore.html)
A counting-based locking mechanism that uses permits.
* [AtomicMarkableReference](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/AtomicMarkableReference.html)
#### Deprecated
Deprecated features are still available and bugs are being fixed, but new features will not be added.
* ~~[Future](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Future.html):
An asynchronous operation that produces a value.~~ Replaced by
[Promises](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Promises.html).
* ~~[.dataflow](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent.html#dataflow-class_method):
Built on Futures, Dataflow allows you to create a task that will be scheduled when all of
its data dependencies are available.~~ Replaced by
[Promises](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Promises.html).
* ~~[Promise](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Promise.html): Similar
to Futures, with more features.~~ Replaced by
[Promises](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Promises.html).
* ~~[Delay](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Delay.html) Lazy evaluation
of a block yielding an immutable result. Based on Clojure's
[delay](https://clojuredocs.org/clojure.core/delay).~~ Replaced by
[Promises](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Promises.html).
* ~~[IVar](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/IVar.html) Similar to a
"future" but can be manually assigned once, after which it becomes immutable.~~ Replaced by
[Promises](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Promises.html).
### Edge Features
These are available in the `concurrent-ruby-edge` companion gem.
These features are under active development and may change frequently. They are expected not to
keep backward compatibility (there may also lack tests and documentation). Semantic versions will
be obeyed though. Features developed in `concurrent-ruby-edge` are expected to move to
`concurrent-ruby` when final.
* [Actor](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Actor.html): Implements
the Actor Model, where concurrent actors exchange messages.
*Status: Partial documentation and tests; depends on new future/promise framework; stability is good.*
* [Channel](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Channel.html):
Communicating Sequential Processes ([CSP](https://en.wikipedia.org/wiki/Communicating_sequential_processes)).
Functionally equivalent to Go [channels](https://tour.golang.org/concurrency/2) with additional
inspiration from Clojure [core.async](https://clojure.github.io/core.async/).
*Status: Partial documentation and tests.*
* [LazyRegister](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/LazyRegister.html)
* [LockFreeLinkedSet](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Edge/LockFreeLinkedSet.html)
*Status: will be moved to core soon.*
* [LockFreeStack](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/LockFreeStack.html)
*Status: missing documentation and tests.*
* [Promises::Channel](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Promises/Channel.html)
A first in first out channel that accepts messages with push family of methods and returns
messages with pop family of methods.
Pop and push operations can be represented as futures, see `#pop_op` and `#push_op`.
The capacity of the channel can be limited to support back pressure, use capacity option in `#initialize`.
`#pop` method blocks ans `#pop_op` returns pending future if there is no message in the channel.
If the capacity is limited the `#push` method blocks and `#push_op` returns pending future.
* [Cancellation](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Cancellation.html)
The Cancellation abstraction provides cooperative cancellation.
The standard methods `Thread#raise` of `Thread#kill` available in Ruby
are very dangerous (see linked the blog posts bellow).
Therefore concurrent-ruby provides an alternative.
* <https://jvns.ca/blog/2015/11/27/why-rubys-timeout-is-dangerous-and-thread-dot-raise-is-terrifying/>
* <http://www.mikeperham.com/2015/05/08/timeout-rubys-most-dangerous-api/>
* <http://blog.headius.com/2008/02/rubys-threadraise-threadkill-timeoutrb.html>
It provides an object which represents a task which can be executed,
the task has to get the reference to the object and periodically cooperatively check that it is not cancelled.
Good practices to make tasks cancellable:
* check cancellation every cycle of a loop which does significant work,
* do all blocking actions in a loop with a timeout then on timeout check cancellation
and if ok block again with the timeout
* [Throttle](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/Throttle.html)
A tool managing concurrency level of tasks.
* [ErlangActor](http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ErlangActor.html)
Actor implementation which precisely matches Erlang actor behaviour.
Requires at least Ruby 2.1 otherwise it's not loaded.
## Supported Ruby versions
* MRI 2.0 and above
* JRuby 9000
* TruffleRuby are supported.
* Any Ruby interpreter that is compliant with Ruby 2.0 or newer.
Actually we still support mri 1.9.3 and jruby 1.7.27 but we are looking at ways how to drop the support.
Java 8 is preferred for JRuby but every Java version on which JRuby 9000 runs is supported.
The legacy support for Rubinius is kept but it is no longer maintained, if you would like to help
please respond to [#739](https://github.com/ruby-concurrency/concurrent-ruby/issues/739).
## Usage
Everything within this gem can be loaded simply by requiring it:
```ruby
require 'concurrent'
```
*Requiring only specific abstractions from Concurrent Ruby is not yet supported.*
To use the tools in the Edge gem it must be required separately:
```ruby
require 'concurrent-edge'
```
If the library does not behave as expected, `Concurrent.use_stdlib_logger(Logger::DEBUG)` could
help to reveal the problem.
## Installation
```shell
gem install concurrent-ruby
```
or add the following line to Gemfile:
```ruby
gem 'concurrent-ruby', require: 'concurrent'
```
and run `bundle install` from your shell.
### Edge Gem Installation
The Edge gem must be installed separately from the core gem:
```shell
gem install concurrent-ruby-edge
```
or add the following line to Gemfile:
```ruby
gem 'concurrent-ruby-edge', require: 'concurrent-edge'
```
and run `bundle install` from your shell.
### C Extensions for MRI
Potential performance improvements may be achieved under MRI by installing optional C extensions.
To minimise installation errors the C extensions are available in the `concurrent-ruby-ext`
extension gem. `concurrent-ruby` and `concurrent-ruby-ext` are always released together with same
version. Simply install the extension gem too:
```ruby
gem install concurrent-ruby-ext
```
or add the following line to Gemfile:
```ruby
gem 'concurrent-ruby-ext'
```
and run `bundle install` from your shell.
In code it is only necessary to
```ruby
require 'concurrent'
```
The `concurrent-ruby` gem will automatically detect the presence of the `concurrent-ruby-ext` gem
and load the appropriate C extensions.
#### Note For gem developers
No gems should depend on `concurrent-ruby-ext`. Doing so will force C extensions on your users. The
best practice is to depend on `concurrent-ruby` and let users to decide if they want C extensions.
## Maintainers
* [Petr Chalupa](https://github.com/pitr-ch) (lead maintainer, point-of-contact)
* [Jerry D'Antonio](https://github.com/jdantonio) (creator)
* [Chris Seaton](https://github.com/chrisseaton)
### Special Thanks to
* [Brian Durand](https://github.com/bdurand) for the `ref` gem
* [Charles Oliver Nutter](https://github.com/headius) for the `atomic` and `thread_safe` gems
* [thedarkone](https://github.com/thedarkone) for the `thread_safe` gem
and to the past maintainers
* [Michele Della Torre](https://github.com/mighe)
* [Paweł Obrok](https://github.com/obrok)
* [Lucas Allan](https://github.com/lucasallan)
and to [Ruby Association](https://www.ruby.or.jp/en/) for sponsoring a project
["Enhancing Rubys concurrency tooling"](https://www.ruby.or.jp/en/news/20181106) in 2018.
## License and Copyright
*Concurrent Ruby* is free software released under the
[MIT License](http://www.opensource.org/licenses/MIT).
The *Concurrent Ruby* [logo](https://raw.githubusercontent.com/ruby-concurrency/concurrent-ruby/master/docs-source/logo/concurrent-ruby-logo-300x300.png) was
designed by [David Jones](https://twitter.com/zombyboy). It is Copyright &copy; 2014
[Jerry D'Antonio](https://twitter.com/jerrydantonio). All Rights Reserved.

View File

@ -1,327 +0,0 @@
require_relative 'lib/concurrent/version'
require_relative 'lib/concurrent/utility/engine'
if Concurrent.ruby_version :<, 2, 0, 0
# @!visibility private
module Kernel
def __dir__
File.dirname __FILE__
end
end
end
core_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby.gemspec')
ext_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby-ext.gemspec')
edge_gemspec = Gem::Specification.load File.join(__dir__, 'concurrent-ruby-edge.gemspec')
require 'rake/javaextensiontask'
Rake::JavaExtensionTask.new('concurrent_ruby', core_gemspec) do |ext|
ext.ext_dir = 'ext/concurrent-ruby'
ext.lib_dir = 'lib/concurrent'
end
unless Concurrent.on_jruby?
require 'rake/extensiontask'
Rake::ExtensionTask.new('concurrent_ruby_ext', ext_gemspec) do |ext|
ext.ext_dir = 'ext/concurrent-ruby-ext'
ext.lib_dir = 'lib/concurrent'
ext.source_pattern = '*.{c,h}'
ext.cross_compile = true
ext.cross_platform = ['x86-mingw32', 'x64-mingw32']
end
end
require 'rake_compiler_dock'
namespace :repackage do
desc '* with Windows fat distributions'
task :all do
Dir.chdir(__dir__) do
# store gems in vendor cache for docker
sh 'bundle package'
# build only the jar file not the whole gem for java platform, the jar is part the concurrent-ruby-x.y.z.gem
Rake::Task['lib/concurrent/concurrent_ruby.jar'].invoke
# build all gem files
RakeCompilerDock.sh 'bundle install --local && bundle exec rake cross native package --trace'
end
end
end
require 'rubygems'
require 'rubygems/package_task'
Gem::PackageTask.new(core_gemspec) {} if core_gemspec
Gem::PackageTask.new(ext_gemspec) {} if ext_gemspec && !Concurrent.on_jruby?
Gem::PackageTask.new(edge_gemspec) {} if edge_gemspec
CLEAN.include('lib/concurrent/2.*', 'lib/concurrent/*.jar')
begin
require 'rspec'
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
namespace :spec do
desc '* Configured for ci'
RSpec::Core::RakeTask.new(:ci) do |t|
options = %w[ --color
--backtrace
--order defined
--format documentation
--tag ~notravis ]
t.rspec_opts = [*options].join(' ')
end
desc '* test packaged and installed gems instead of local files'
task :installed do
Dir.chdir(__dir__) do
sh "gem install pkg/concurrent-ruby-#{Concurrent::VERSION}.gem"
sh "gem install pkg/concurrent-ruby-ext-#{Concurrent::VERSION}.gem" if Concurrent.on_cruby?
sh "gem install pkg/concurrent-ruby-edge-#{Concurrent::EDGE_VERSION}.gem"
ENV['NO_PATH'] = 'true'
sh 'bundle update'
sh 'bundle exec rake spec:ci'
end
end
end
desc 'executed in CI'
task :ci => [:compile, 'spec:ci']
task :default => [:clobber, :compile, :spec]
rescue LoadError => e
puts 'RSpec is not installed, skipping test task definitions: ' + e.message
end
current_yard_version_name = Concurrent::VERSION
begin
require 'yard'
require 'md_ruby_eval'
require_relative 'support/yard_full_types'
common_yard_options = ['--no-yardopts',
'--no-document',
'--no-private',
'--embed-mixins',
'--markup', 'markdown',
'--title', 'Concurrent Ruby',
'--template', 'default',
'--template-path', 'yard-template',
'--default-return', 'undocumented']
desc 'Generate YARD Documentation (signpost, master)'
task :yard => ['yard:signpost', 'yard:master']
namespace :yard do
desc '* eval markdown files'
task :eval_md do
Dir.chdir File.join(__dir__, 'docs-source') do
sh 'bundle exec md-ruby-eval --auto'
end
end
task :update_readme do
Dir.chdir __dir__ do
content = File.read(File.join('README.md')).
gsub(/\[([\w ]+)\]\(http:\/\/ruby-concurrency\.github\.io\/concurrent-ruby\/master\/.*\)/) do |_|
case $1
when 'LockFreeLinkedSet'
"{Concurrent::Edge::#{$1} #{$1}}"
when '.dataflow'
'{Concurrent.dataflow Concurrent.dataflow}'
when 'thread pool'
'{file:thread_pools.md thread pool}'
else
"{Concurrent::#{$1} #{$1}}"
end
end
FileUtils.mkpath 'tmp'
File.write 'tmp/README.md', content
end
end
define_yard_task = -> name do
output_dir = "docs/#{name}"
removal_name = "remove.#{name}"
task removal_name do
Dir.chdir __dir__ do
FileUtils.rm_rf output_dir
end
end
desc "* of #{name} into subdir #{name}"
YARD::Rake::YardocTask.new(name) do |yard|
yard.options.push(
'--output-dir', output_dir,
'--main', 'tmp/README.md',
*common_yard_options)
yard.files = ['./lib/**/*.rb',
'./lib-edge/**/*.rb',
'./ext/concurrent_ruby_ext/**/*.c',
'-',
'docs-source/thread_pools.md',
'docs-source/promises.out.md',
'docs-source/medium-example.out.rb',
'LICENSE.md',
'CHANGELOG.md']
end
Rake::Task[name].prerequisites.push removal_name, 'yard:eval_md', 'yard:update_readme'
end
define_yard_task.call current_yard_version_name
define_yard_task.call 'master'
desc "* signpost for versions"
YARD::Rake::YardocTask.new(:signpost) do |yard|
yard.options.push(
'--output-dir', 'docs',
'--main', 'docs-source/signpost.md',
*common_yard_options)
yard.files = ['no-lib']
end
define_uptodate_task = -> name do
namespace name do
desc "** ensure that #{name} generated documentation is matching the source code"
task :uptodate do
Dir.chdir(__dir__) do
begin
FileUtils.cp_r 'docs', 'docs-copy', verbose: true
Rake::Task["yard:#{name}"].invoke
sh 'diff -r docs/ docs-copy/' do |ok, res|
unless ok
begin
STDOUT.puts 'Command failed. Continue? (y/n)'
input = STDIN.gets.strip.downcase
end until %w(y n).include?(input)
exit 1 if input == 'n'
end
end
ensure
FileUtils.rm_rf 'docs-copy', verbose: true
end
end
end
end
end
define_uptodate_task.call current_yard_version_name
define_uptodate_task.call 'master'
end
rescue LoadError => e
puts 'YARD is not installed, skipping documentation task definitions: ' + e.message
end
desc 'build, test, and publish the gem'
task :release => ['release:checks', 'release:build', 'release:test', 'release:publish']
namespace :release do
# Depends on environment of @pitr-ch
mri_version = '2.5.1'
jruby_version = 'jruby-9.1.17.1'
task :checks => "yard:#{current_yard_version_name}:uptodate" do
Dir.chdir(__dir__) do
sh 'test -z "$(git status --porcelain)"' do |ok, res|
unless ok
begin
STDOUT.puts 'Command failed. Continue? (y/n)'
input = STDIN.gets.strip.downcase
end until %w(y n).include?(input)
exit 1 if input == 'n'
end
end
sh 'git fetch'
sh 'test $(git show-ref --verify --hash refs/heads/master) = ' +
'$(git show-ref --verify --hash refs/remotes/origin/master)' do |ok, res|
unless ok
begin
STDOUT.puts 'Command failed. Continue? (y/n)'
input = STDIN.gets.strip.downcase
end until %w(y n).include?(input)
exit 1 if input == 'n'
end
end
end
end
desc '* build all *.gem files necessary for release'
task :build => [:clobber, 'repackage:all']
desc '* test actual installed gems instead of cloned repository on MRI and JRuby'
task :test do
Dir.chdir(__dir__) do
old = ENV['RBENV_VERSION']
ENV['RBENV_VERSION'] = mri_version
sh 'rbenv version'
sh 'bundle exec rake spec:installed'
ENV['RBENV_VERSION'] = jruby_version
sh 'rbenv version'
sh 'bundle exec rake spec:installed'
puts 'Windows build is untested'
ENV['RBENV_VERSION'] = old
end
end
desc '* do all nested steps'
task :publish => ['publish:ask', 'publish:tag', 'publish:rubygems', 'publish:post_steps']
namespace :publish do
publish_edge = false
task :ask do
begin
STDOUT.puts 'Do you want to publish anything? (y/n)'
input = STDIN.gets.strip.downcase
end until %w(y n).include?(input)
exit 1 if input == 'n'
begin
STDOUT.puts 'Do you want to publish edge? (y/n)'
input = STDIN.gets.strip.downcase
end until %w(y n).include?(input)
publish_edge = input == 'y'
end
desc '** tag HEAD with current version and push to github'
task :tag do
Dir.chdir(__dir__) do
sh "git tag v#{Concurrent::VERSION}"
sh "git push origin v#{Concurrent::VERSION}"
sh "git tag edge-v#{Concurrent::EDGE_VERSION}" if publish_edge
sh "git push origin edge-v#{Concurrent::EDGE_VERSION}" if publish_edge
end
end
desc '** push all *.gem files to rubygems'
task :rubygems do
Dir.chdir(__dir__) do
sh "gem push pkg/concurrent-ruby-#{Concurrent::VERSION}.gem"
sh "gem push pkg/concurrent-ruby-edge-#{Concurrent::EDGE_VERSION}.gem" if publish_edge
sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}.gem"
sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}-x64-mingw32.gem"
sh "gem push pkg/concurrent-ruby-ext-#{Concurrent::VERSION}-x86-mingw32.gem"
end
end
desc '** print post release steps'
task :post_steps do
puts 'Manually: create a release on GitHub with relevant changelog part'
puts 'Manually: send email same as release with relevant changelog part'
puts 'Manually: tweet'
end
end
end

View File

@ -1,17 +0,0 @@
import org.jruby.Ruby;
import org.jruby.runtime.load.BasicLibraryService;
import java.io.IOException;
public class ConcurrentRubyService implements BasicLibraryService {
public boolean basicLoad(final Ruby runtime) throws IOException {
new com.concurrent_ruby.ext.AtomicReferenceLibrary().load(runtime, false);
new com.concurrent_ruby.ext.JavaAtomicBooleanLibrary().load(runtime, false);
new com.concurrent_ruby.ext.JavaAtomicFixnumLibrary().load(runtime, false);
new com.concurrent_ruby.ext.JavaSemaphoreLibrary().load(runtime, false);
new com.concurrent_ruby.ext.SynchronizationLibrary().load(runtime, false);
new com.concurrent_ruby.ext.JRubyMapBackendLibrary().load(runtime, false);
return true;
}
}

View File

@ -1,175 +0,0 @@
package com.concurrent_ruby.ext;
import java.lang.reflect.Field;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.RubyModule;
import org.jruby.RubyNumeric;
import org.jruby.RubyObject;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.load.Library;
/**
* This library adds an atomic reference type to JRuby for use in the atomic
* library. We do a native version to avoid the implicit value coercion that
* normally happens through JI.
*
* @author headius
*/
public class AtomicReferenceLibrary implements Library {
public void load(Ruby runtime, boolean wrap) throws IOException {
RubyModule concurrentMod = runtime.defineModule("Concurrent");
RubyClass atomicCls = concurrentMod.defineClassUnder("JavaAtomicReference", runtime.getObject(), JRUBYREFERENCE_ALLOCATOR);
try {
sun.misc.Unsafe.class.getMethod("getAndSetObject", Object.class);
atomicCls.setAllocator(JRUBYREFERENCE8_ALLOCATOR);
} catch (Exception e) {
// leave it as Java 6/7 version
}
atomicCls.defineAnnotatedMethods(JRubyReference.class);
}
private static final ObjectAllocator JRUBYREFERENCE_ALLOCATOR = new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new JRubyReference(runtime, klazz);
}
};
private static final ObjectAllocator JRUBYREFERENCE8_ALLOCATOR = new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new JRubyReference8(runtime, klazz);
}
};
@JRubyClass(name="JRubyReference", parent="Object")
public static class JRubyReference extends RubyObject {
volatile IRubyObject reference;
static final sun.misc.Unsafe UNSAFE;
static final long referenceOffset;
static {
try {
UNSAFE = UnsafeHolder.U;
Class k = JRubyReference.class;
referenceOffset = UNSAFE.objectFieldOffset(k.getDeclaredField("reference"));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public JRubyReference(Ruby runtime, RubyClass klass) {
super(runtime, klass);
}
@JRubyMethod
public IRubyObject initialize(ThreadContext context) {
UNSAFE.putObject(this, referenceOffset, context.nil);
return context.nil;
}
@JRubyMethod
public IRubyObject initialize(ThreadContext context, IRubyObject value) {
UNSAFE.putObject(this, referenceOffset, value);
return context.nil;
}
@JRubyMethod(name = {"get", "value"})
public IRubyObject get() {
return reference;
}
@JRubyMethod(name = {"set", "value="})
public IRubyObject set(IRubyObject newValue) {
UNSAFE.putObjectVolatile(this, referenceOffset, newValue);
return newValue;
}
@JRubyMethod(name = {"compare_and_set", "compare_and_swap"})
public IRubyObject compare_and_set(ThreadContext context, IRubyObject expectedValue, IRubyObject newValue) {
Ruby runtime = context.runtime;
if (expectedValue instanceof RubyNumeric) {
// numerics are not always idempotent in Ruby, so we need to do slower logic
return compareAndSetNumeric(context, expectedValue, newValue);
}
return runtime.newBoolean(UNSAFE.compareAndSwapObject(this, referenceOffset, expectedValue, newValue));
}
@JRubyMethod(name = {"get_and_set", "swap"})
public IRubyObject get_and_set(ThreadContext context, IRubyObject newValue) {
// less-efficient version for Java 6 and 7
while (true) {
IRubyObject oldValue = get();
if (UNSAFE.compareAndSwapObject(this, referenceOffset, oldValue, newValue)) {
return oldValue;
}
}
}
private IRubyObject compareAndSetNumeric(ThreadContext context, IRubyObject expectedValue, IRubyObject newValue) {
Ruby runtime = context.runtime;
// loop until:
// * reference CAS would succeed for same-valued objects
// * current and expected have different values as determined by #equals
while (true) {
IRubyObject current = reference;
if (!(current instanceof RubyNumeric)) {
// old value is not numeric, CAS fails
return runtime.getFalse();
}
RubyNumeric currentNumber = (RubyNumeric)current;
if (!currentNumber.equals(expectedValue)) {
// current number does not equal expected, fail CAS
return runtime.getFalse();
}
// check that current has not changed, or else allow loop to repeat
boolean success = UNSAFE.compareAndSwapObject(this, referenceOffset, current, newValue);
if (success) {
// value is same and did not change in interim...success
return runtime.getTrue();
}
}
}
}
private static final class UnsafeHolder {
private UnsafeHolder(){}
public static final sun.misc.Unsafe U = loadUnsafe();
private static sun.misc.Unsafe loadUnsafe() {
try {
Class unsafeClass = Class.forName("sun.misc.Unsafe");
Field f = unsafeClass.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (sun.misc.Unsafe) f.get(null);
} catch (Exception e) {
return null;
}
}
}
public static class JRubyReference8 extends JRubyReference {
public JRubyReference8(Ruby runtime, RubyClass klass) {
super(runtime, klass);
}
@Override
public IRubyObject get_and_set(ThreadContext context, IRubyObject newValue) {
// efficient version for Java 8
return (IRubyObject)UNSAFE.getAndSetObject(this, referenceOffset, newValue);
}
}
}

View File

@ -1,248 +0,0 @@
package com.concurrent_ruby.ext;
import org.jruby.*;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import com.concurrent_ruby.ext.jsr166e.ConcurrentHashMap;
import com.concurrent_ruby.ext.jsr166e.ConcurrentHashMapV8;
import com.concurrent_ruby.ext.jsr166e.nounsafe.*;
import org.jruby.runtime.Block;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.load.Library;
import java.io.IOException;
import java.util.Map;
import static org.jruby.runtime.Visibility.PRIVATE;
/**
* Native Java implementation to avoid the JI overhead.
*
* @author thedarkone
*/
public class JRubyMapBackendLibrary implements Library {
public void load(Ruby runtime, boolean wrap) throws IOException {
RubyModule concurrentMod = runtime.defineModule("Concurrent");
RubyModule thread_safeMod = concurrentMod.defineModuleUnder("Collection");
RubyClass jrubyRefClass = thread_safeMod.defineClassUnder("JRubyMapBackend", runtime.getObject(), BACKEND_ALLOCATOR);
jrubyRefClass.setAllocator(BACKEND_ALLOCATOR);
jrubyRefClass.defineAnnotatedMethods(JRubyMapBackend.class);
}
private static final ObjectAllocator BACKEND_ALLOCATOR = new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new JRubyMapBackend(runtime, klazz);
}
};
@JRubyClass(name="JRubyMapBackend", parent="Object")
public static class JRubyMapBackend extends RubyObject {
// Defaults used by the CHM
static final int DEFAULT_INITIAL_CAPACITY = 16;
static final float DEFAULT_LOAD_FACTOR = 0.75f;
public static final boolean CAN_USE_UNSAFE_CHM = canUseUnsafeCHM();
private ConcurrentHashMap<IRubyObject, IRubyObject> map;
private static ConcurrentHashMap<IRubyObject, IRubyObject> newCHM(int initialCapacity, float loadFactor) {
if (CAN_USE_UNSAFE_CHM) {
return new ConcurrentHashMapV8<IRubyObject, IRubyObject>(initialCapacity, loadFactor);
} else {
return new com.concurrent_ruby.ext.jsr166e.nounsafe.ConcurrentHashMapV8<IRubyObject, IRubyObject>(initialCapacity, loadFactor);
}
}
private static ConcurrentHashMap<IRubyObject, IRubyObject> newCHM() {
return newCHM(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
}
private static boolean canUseUnsafeCHM() {
try {
new com.concurrent_ruby.ext.jsr166e.ConcurrentHashMapV8(); // force class load and initialization
return true;
} catch (Throwable t) { // ensuring we really do catch everything
// Doug's Unsafe setup errors always have this "Could not ini.." message
if (isCausedBySecurityException(t)) {
return false;
}
throw (t instanceof RuntimeException ? (RuntimeException) t : new RuntimeException(t));
}
}
private static boolean isCausedBySecurityException(Throwable t) {
while (t != null) {
if ((t.getMessage() != null && t.getMessage().contains("Could not initialize intrinsics")) || t instanceof SecurityException) {
return true;
}
t = t.getCause();
}
return false;
}
public JRubyMapBackend(Ruby runtime, RubyClass klass) {
super(runtime, klass);
}
@JRubyMethod
public IRubyObject initialize(ThreadContext context) {
map = newCHM();
return context.getRuntime().getNil();
}
@JRubyMethod
public IRubyObject initialize(ThreadContext context, IRubyObject options) {
map = toCHM(context, options);
return context.getRuntime().getNil();
}
private ConcurrentHashMap<IRubyObject, IRubyObject> toCHM(ThreadContext context, IRubyObject options) {
Ruby runtime = context.getRuntime();
if (!options.isNil() && options.respondsTo("[]")) {
IRubyObject rInitialCapacity = options.callMethod(context, "[]", runtime.newSymbol("initial_capacity"));
IRubyObject rLoadFactor = options.callMethod(context, "[]", runtime.newSymbol("load_factor"));
int initialCapacity = !rInitialCapacity.isNil() ? RubyNumeric.num2int(rInitialCapacity.convertToInteger()) : DEFAULT_INITIAL_CAPACITY;
float loadFactor = !rLoadFactor.isNil() ? (float)RubyNumeric.num2dbl(rLoadFactor.convertToFloat()) : DEFAULT_LOAD_FACTOR;
return newCHM(initialCapacity, loadFactor);
} else {
return newCHM();
}
}
@JRubyMethod(name = "[]", required = 1)
public IRubyObject op_aref(ThreadContext context, IRubyObject key) {
IRubyObject value;
return ((value = map.get(key)) == null) ? context.getRuntime().getNil() : value;
}
@JRubyMethod(name = {"[]="}, required = 2)
public IRubyObject op_aset(IRubyObject key, IRubyObject value) {
map.put(key, value);
return value;
}
@JRubyMethod
public IRubyObject put_if_absent(IRubyObject key, IRubyObject value) {
IRubyObject result = map.putIfAbsent(key, value);
return result == null ? getRuntime().getNil() : result;
}
@JRubyMethod
public IRubyObject compute_if_absent(final ThreadContext context, final IRubyObject key, final Block block) {
return map.computeIfAbsent(key, new ConcurrentHashMap.Fun<IRubyObject, IRubyObject>() {
@Override
public IRubyObject apply(IRubyObject key) {
return block.yieldSpecific(context);
}
});
}
@JRubyMethod
public IRubyObject compute_if_present(final ThreadContext context, final IRubyObject key, final Block block) {
IRubyObject result = map.computeIfPresent(key, new ConcurrentHashMap.BiFun<IRubyObject, IRubyObject, IRubyObject>() {
@Override
public IRubyObject apply(IRubyObject key, IRubyObject oldValue) {
IRubyObject result = block.yieldSpecific(context, oldValue == null ? context.getRuntime().getNil() : oldValue);
return result.isNil() ? null : result;
}
});
return result == null ? context.getRuntime().getNil() : result;
}
@JRubyMethod
public IRubyObject compute(final ThreadContext context, final IRubyObject key, final Block block) {
IRubyObject result = map.compute(key, new ConcurrentHashMap.BiFun<IRubyObject, IRubyObject, IRubyObject>() {
@Override
public IRubyObject apply(IRubyObject key, IRubyObject oldValue) {
IRubyObject result = block.yieldSpecific(context, oldValue == null ? context.getRuntime().getNil() : oldValue);
return result.isNil() ? null : result;
}
});
return result == null ? context.getRuntime().getNil() : result;
}
@JRubyMethod
public IRubyObject merge_pair(final ThreadContext context, final IRubyObject key, final IRubyObject value, final Block block) {
IRubyObject result = map.merge(key, value, new ConcurrentHashMap.BiFun<IRubyObject, IRubyObject, IRubyObject>() {
@Override
public IRubyObject apply(IRubyObject oldValue, IRubyObject newValue) {
IRubyObject result = block.yieldSpecific(context, oldValue == null ? context.getRuntime().getNil() : oldValue);
return result.isNil() ? null : result;
}
});
return result == null ? context.getRuntime().getNil() : result;
}
@JRubyMethod
public RubyBoolean replace_pair(IRubyObject key, IRubyObject oldValue, IRubyObject newValue) {
return getRuntime().newBoolean(map.replace(key, oldValue, newValue));
}
@JRubyMethod(name = "key?", required = 1)
public RubyBoolean has_key_p(IRubyObject key) {
return map.containsKey(key) ? getRuntime().getTrue() : getRuntime().getFalse();
}
@JRubyMethod
public IRubyObject key(IRubyObject value) {
final IRubyObject key = map.findKey(value);
return key == null ? getRuntime().getNil() : key;
}
@JRubyMethod
public IRubyObject replace_if_exists(IRubyObject key, IRubyObject value) {
IRubyObject result = map.replace(key, value);
return result == null ? getRuntime().getNil() : result;
}
@JRubyMethod
public IRubyObject get_and_set(IRubyObject key, IRubyObject value) {
IRubyObject result = map.put(key, value);
return result == null ? getRuntime().getNil() : result;
}
@JRubyMethod
public IRubyObject delete(IRubyObject key) {
IRubyObject result = map.remove(key);
return result == null ? getRuntime().getNil() : result;
}
@JRubyMethod
public RubyBoolean delete_pair(IRubyObject key, IRubyObject value) {
return getRuntime().newBoolean(map.remove(key, value));
}
@JRubyMethod
public IRubyObject clear() {
map.clear();
return this;
}
@JRubyMethod
public IRubyObject each_pair(ThreadContext context, Block block) {
for (Map.Entry<IRubyObject,IRubyObject> entry : map.entrySet()) {
block.yieldSpecific(context, entry.getKey(), entry.getValue());
}
return this;
}
@JRubyMethod
public RubyFixnum size(ThreadContext context) {
return context.getRuntime().newFixnum(map.size());
}
@JRubyMethod
public IRubyObject get_or_default(IRubyObject key, IRubyObject defaultValue) {
return map.getValueOrDefault(key, defaultValue);
}
@JRubyMethod(visibility = PRIVATE)
public JRubyMapBackend initialize_copy(ThreadContext context, IRubyObject other) {
map = newCHM();
return this;
}
}
}

View File

@ -1,93 +0,0 @@
package com.concurrent_ruby.ext;
import org.jruby.Ruby;
import org.jruby.RubyBoolean;
import org.jruby.RubyClass;
import org.jruby.RubyModule;
import org.jruby.RubyNil;
import org.jruby.RubyObject;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.load.Library;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;
public class JavaAtomicBooleanLibrary implements Library {
public void load(Ruby runtime, boolean wrap) throws IOException {
RubyModule concurrentMod = runtime.defineModule("Concurrent");
RubyClass atomicCls = concurrentMod.defineClassUnder("JavaAtomicBoolean", runtime.getObject(), JRUBYREFERENCE_ALLOCATOR);
atomicCls.defineAnnotatedMethods(JavaAtomicBoolean.class);
}
private static final ObjectAllocator JRUBYREFERENCE_ALLOCATOR = new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new JavaAtomicBoolean(runtime, klazz);
}
};
@JRubyClass(name = "JavaAtomicBoolean", parent = "Object")
public static class JavaAtomicBoolean extends RubyObject {
private AtomicBoolean atomicBoolean;
public JavaAtomicBoolean(Ruby runtime, RubyClass metaClass) {
super(runtime, metaClass);
}
@JRubyMethod
public IRubyObject initialize(ThreadContext context, IRubyObject value) {
atomicBoolean = new AtomicBoolean(convertRubyBooleanToJavaBoolean(value));
return context.nil;
}
@JRubyMethod
public IRubyObject initialize(ThreadContext context) {
atomicBoolean = new AtomicBoolean();
return context.nil;
}
@JRubyMethod(name = "value")
public IRubyObject value() {
return getRuntime().newBoolean(atomicBoolean.get());
}
@JRubyMethod(name = "true?")
public IRubyObject isAtomicTrue() {
return getRuntime().newBoolean(atomicBoolean.get());
}
@JRubyMethod(name = "false?")
public IRubyObject isAtomicFalse() {
return getRuntime().newBoolean((atomicBoolean.get() == false));
}
@JRubyMethod(name = "value=")
public IRubyObject setAtomic(ThreadContext context, IRubyObject newValue) {
atomicBoolean.set(convertRubyBooleanToJavaBoolean(newValue));
return context.nil;
}
@JRubyMethod(name = "make_true")
public IRubyObject makeTrue() {
return getRuntime().newBoolean(atomicBoolean.compareAndSet(false, true));
}
@JRubyMethod(name = "make_false")
public IRubyObject makeFalse() {
return getRuntime().newBoolean(atomicBoolean.compareAndSet(true, false));
}
private boolean convertRubyBooleanToJavaBoolean(IRubyObject newValue) {
if (newValue instanceof RubyBoolean.False || newValue instanceof RubyNil) {
return false;
} else {
return true;
}
}
}
}

View File

@ -1,113 +0,0 @@
package com.concurrent_ruby.ext;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicLong;
import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.RubyFixnum;
import org.jruby.RubyModule;
import org.jruby.RubyObject;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.load.Library;
import org.jruby.runtime.Block;
public class JavaAtomicFixnumLibrary implements Library {
public void load(Ruby runtime, boolean wrap) throws IOException {
RubyModule concurrentMod = runtime.defineModule("Concurrent");
RubyClass atomicCls = concurrentMod.defineClassUnder("JavaAtomicFixnum", runtime.getObject(), JRUBYREFERENCE_ALLOCATOR);
atomicCls.defineAnnotatedMethods(JavaAtomicFixnum.class);
}
private static final ObjectAllocator JRUBYREFERENCE_ALLOCATOR = new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new JavaAtomicFixnum(runtime, klazz);
}
};
@JRubyClass(name = "JavaAtomicFixnum", parent = "Object")
public static class JavaAtomicFixnum extends RubyObject {
private AtomicLong atomicLong;
public JavaAtomicFixnum(Ruby runtime, RubyClass metaClass) {
super(runtime, metaClass);
}
@JRubyMethod
public IRubyObject initialize(ThreadContext context) {
this.atomicLong = new AtomicLong(0);
return context.nil;
}
@JRubyMethod
public IRubyObject initialize(ThreadContext context, IRubyObject value) {
this.atomicLong = new AtomicLong(rubyFixnumToLong(value));
return context.nil;
}
@JRubyMethod(name = "value")
public IRubyObject getValue() {
return getRuntime().newFixnum(atomicLong.get());
}
@JRubyMethod(name = "value=")
public IRubyObject setValue(ThreadContext context, IRubyObject newValue) {
atomicLong.set(rubyFixnumToLong(newValue));
return context.nil;
}
@JRubyMethod(name = {"increment", "up"})
public IRubyObject increment() {
return getRuntime().newFixnum(atomicLong.incrementAndGet());
}
@JRubyMethod(name = {"increment", "up"})
public IRubyObject increment(IRubyObject value) {
long delta = rubyFixnumToLong(value);
return getRuntime().newFixnum(atomicLong.addAndGet(delta));
}
@JRubyMethod(name = {"decrement", "down"})
public IRubyObject decrement() {
return getRuntime().newFixnum(atomicLong.decrementAndGet());
}
@JRubyMethod(name = {"decrement", "down"})
public IRubyObject decrement(IRubyObject value) {
long delta = rubyFixnumToLong(value);
return getRuntime().newFixnum(atomicLong.addAndGet(-delta));
}
@JRubyMethod(name = "compare_and_set")
public IRubyObject compareAndSet(ThreadContext context, IRubyObject expect, IRubyObject update) {
return getRuntime().newBoolean(atomicLong.compareAndSet(rubyFixnumToLong(expect), rubyFixnumToLong(update)));
}
@JRubyMethod
public IRubyObject update(ThreadContext context, Block block) {
for (;;) {
long _oldValue = atomicLong.get();
IRubyObject oldValue = getRuntime().newFixnum(_oldValue);
IRubyObject newValue = block.yield(context, oldValue);
if (atomicLong.compareAndSet(_oldValue, rubyFixnumToLong(newValue))) {
return newValue;
}
}
}
private long rubyFixnumToLong(IRubyObject value) {
if (value instanceof RubyFixnum) {
RubyFixnum fixNum = (RubyFixnum) value;
return fixNum.getLongValue();
} else {
throw getRuntime().newArgumentError("value must be a Fixnum");
}
}
}
}

View File

@ -1,159 +0,0 @@
package com.concurrent_ruby.ext;
import java.io.IOException;
import java.util.concurrent.Semaphore;
import org.jruby.Ruby;
import org.jruby.RubyClass;
import org.jruby.RubyFixnum;
import org.jruby.RubyModule;
import org.jruby.RubyNumeric;
import org.jruby.RubyObject;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
public class JavaSemaphoreLibrary {
public void load(Ruby runtime, boolean wrap) throws IOException {
RubyModule concurrentMod = runtime.defineModule("Concurrent");
RubyClass atomicCls = concurrentMod.defineClassUnder("JavaSemaphore", runtime.getObject(), JRUBYREFERENCE_ALLOCATOR);
atomicCls.defineAnnotatedMethods(JavaSemaphore.class);
}
private static final ObjectAllocator JRUBYREFERENCE_ALLOCATOR = new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new JavaSemaphore(runtime, klazz);
}
};
@JRubyClass(name = "JavaSemaphore", parent = "Object")
public static class JavaSemaphore extends RubyObject {
private JRubySemaphore semaphore;
public JavaSemaphore(Ruby runtime, RubyClass metaClass) {
super(runtime, metaClass);
}
@JRubyMethod
public IRubyObject initialize(ThreadContext context, IRubyObject value) {
this.semaphore = new JRubySemaphore(rubyFixnumInt(value, "count"));
return context.nil;
}
@JRubyMethod
public IRubyObject acquire(ThreadContext context, IRubyObject value) throws InterruptedException {
this.semaphore.acquire(rubyFixnumToPositiveInt(value, "permits"));
return context.nil;
}
@JRubyMethod(name = "available_permits")
public IRubyObject availablePermits(ThreadContext context) {
return getRuntime().newFixnum(this.semaphore.availablePermits());
}
@JRubyMethod(name = "drain_permits")
public IRubyObject drainPermits(ThreadContext context) {
return getRuntime().newFixnum(this.semaphore.drainPermits());
}
@JRubyMethod
public IRubyObject acquire(ThreadContext context) throws InterruptedException {
this.semaphore.acquire(1);
return context.nil;
}
@JRubyMethod(name = "try_acquire")
public IRubyObject tryAcquire(ThreadContext context) throws InterruptedException {
return getRuntime().newBoolean(semaphore.tryAcquire(1));
}
@JRubyMethod(name = "try_acquire")
public IRubyObject tryAcquire(ThreadContext context, IRubyObject permits) throws InterruptedException {
return getRuntime().newBoolean(semaphore.tryAcquire(rubyFixnumToPositiveInt(permits, "permits")));
}
@JRubyMethod(name = "try_acquire")
public IRubyObject tryAcquire(ThreadContext context, IRubyObject permits, IRubyObject timeout) throws InterruptedException {
return getRuntime().newBoolean(
semaphore.tryAcquire(
rubyFixnumToPositiveInt(permits, "permits"),
rubyNumericToLong(timeout, "timeout"),
java.util.concurrent.TimeUnit.SECONDS)
);
}
@JRubyMethod
public IRubyObject release(ThreadContext context) {
this.semaphore.release(1);
return getRuntime().newBoolean(true);
}
@JRubyMethod
public IRubyObject release(ThreadContext context, IRubyObject value) {
this.semaphore.release(rubyFixnumToPositiveInt(value, "permits"));
return getRuntime().newBoolean(true);
}
@JRubyMethod(name = "reduce_permits")
public IRubyObject reducePermits(ThreadContext context, IRubyObject reduction) throws InterruptedException {
this.semaphore.publicReducePermits(rubyFixnumToNonNegativeInt(reduction, "reduction"));
return context.nil;
}
private int rubyFixnumInt(IRubyObject value, String paramName) {
if (value instanceof RubyFixnum) {
RubyFixnum fixNum = (RubyFixnum) value;
return (int) fixNum.getLongValue();
} else {
throw getRuntime().newArgumentError(paramName + " must be integer");
}
}
private int rubyFixnumToNonNegativeInt(IRubyObject value, String paramName) {
if (value instanceof RubyFixnum && ((RubyFixnum) value).getLongValue() >= 0) {
RubyFixnum fixNum = (RubyFixnum) value;
return (int) fixNum.getLongValue();
} else {
throw getRuntime().newArgumentError(paramName + " must be a non-negative integer");
}
}
private int rubyFixnumToPositiveInt(IRubyObject value, String paramName) {
if (value instanceof RubyFixnum && ((RubyFixnum) value).getLongValue() > 0) {
RubyFixnum fixNum = (RubyFixnum) value;
return (int) fixNum.getLongValue();
} else {
throw getRuntime().newArgumentError(paramName + " must be an integer greater than zero");
}
}
private long rubyNumericToLong(IRubyObject value, String paramName) {
if (value instanceof RubyNumeric && ((RubyNumeric) value).getDoubleValue() > 0) {
RubyNumeric fixNum = (RubyNumeric) value;
return fixNum.getLongValue();
} else {
throw getRuntime().newArgumentError(paramName + " must be a float greater than zero");
}
}
class JRubySemaphore extends Semaphore {
public JRubySemaphore(int permits) {
super(permits);
}
public JRubySemaphore(int permits, boolean value) {
super(permits, value);
}
public void publicReducePermits(int i) {
reducePermits(i);
}
}
}
}

View File

@ -1,307 +0,0 @@
package com.concurrent_ruby.ext;
import org.jruby.Ruby;
import org.jruby.RubyBasicObject;
import org.jruby.RubyClass;
import org.jruby.RubyModule;
import org.jruby.RubyObject;
import org.jruby.RubyThread;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.Block;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.load.Library;
import sun.misc.Unsafe;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class SynchronizationLibrary implements Library {
private static final Unsafe UNSAFE = loadUnsafe();
private static final boolean FULL_FENCE = supportsFences();
private static Unsafe loadUnsafe() {
try {
Class ncdfe = Class.forName("sun.misc.Unsafe");
Field f = ncdfe.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (Unsafe) f.get((java.lang.Object) null);
} catch (Exception var2) {
return null;
} catch (NoClassDefFoundError var3) {
return null;
}
}
private static boolean supportsFences() {
if (UNSAFE == null) {
return false;
} else {
try {
Method m = UNSAFE.getClass().getDeclaredMethod("fullFence", new Class[0]);
if (m != null) {
return true;
}
} catch (Exception var1) {
// nothing
}
return false;
}
}
private static final ObjectAllocator JRUBY_OBJECT_ALLOCATOR = new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new JRubyObject(runtime, klazz);
}
};
private static final ObjectAllocator OBJECT_ALLOCATOR = new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new Object(runtime, klazz);
}
};
private static final ObjectAllocator ABSTRACT_LOCKABLE_OBJECT_ALLOCATOR = new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new AbstractLockableObject(runtime, klazz);
}
};
private static final ObjectAllocator JRUBY_LOCKABLE_OBJECT_ALLOCATOR = new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new JRubyLockableObject(runtime, klazz);
}
};
public void load(Ruby runtime, boolean wrap) throws IOException {
RubyModule synchronizationModule = runtime.
defineModule("Concurrent").
defineModuleUnder("Synchronization");
RubyModule jrubyAttrVolatileModule = synchronizationModule.defineModuleUnder("JRubyAttrVolatile");
jrubyAttrVolatileModule.defineAnnotatedMethods(JRubyAttrVolatile.class);
defineClass(runtime, synchronizationModule, "AbstractObject", "JRubyObject",
JRubyObject.class, JRUBY_OBJECT_ALLOCATOR);
defineClass(runtime, synchronizationModule, "JRubyObject", "Object",
Object.class, OBJECT_ALLOCATOR);
defineClass(runtime, synchronizationModule, "Object", "AbstractLockableObject",
AbstractLockableObject.class, ABSTRACT_LOCKABLE_OBJECT_ALLOCATOR);
defineClass(runtime, synchronizationModule, "AbstractLockableObject", "JRubyLockableObject",
JRubyLockableObject.class, JRUBY_LOCKABLE_OBJECT_ALLOCATOR);
defineClass(runtime, synchronizationModule, "Object", "JRuby",
JRuby.class, new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new JRuby(runtime, klazz);
}
});
}
private RubyClass defineClass(
Ruby runtime,
RubyModule namespace,
String parentName,
String name,
Class javaImplementation,
ObjectAllocator allocator) {
final RubyClass parentClass = namespace.getClass(parentName);
if (parentClass == null) {
System.out.println("not found " + parentName);
throw runtime.newRuntimeError(namespace.toString() + "::" + parentName + " is missing");
}
final RubyClass newClass = namespace.defineClassUnder(name, parentClass, allocator);
newClass.defineAnnotatedMethods(javaImplementation);
return newClass;
}
// Facts:
// - all ivar reads are without any synchronisation of fences see
// https://github.com/jruby/jruby/blob/master/core/src/main/java/org/jruby/runtime/ivars/VariableAccessor.java#L110-110
// - writes depend on UnsafeHolder.U, null -> SynchronizedVariableAccessor, !null -> StampedVariableAccessor
// SynchronizedVariableAccessor wraps with synchronized block, StampedVariableAccessor uses fullFence or
// volatilePut
// TODO (pitr 16-Sep-2015): what do we do in Java 9 ?
// module JRubyAttrVolatile
public static class JRubyAttrVolatile {
// volatile threadContext is used as a memory barrier per the JVM memory model happens-before semantic
// on volatile fields. any volatile field could have been used but using the thread context is an
// attempt to avoid code elimination.
private static volatile int volatileField;
@JRubyMethod(name = "full_memory_barrier", visibility = Visibility.PUBLIC)
public static IRubyObject fullMemoryBarrier(ThreadContext context, IRubyObject self) {
// Prevent reordering of ivar writes with publication of this instance
if (!FULL_FENCE) {
// Assuming that following volatile read and write is not eliminated it simulates fullFence.
// If it's eliminated it'll cause problems only on non-x86 platforms.
// http://shipilev.net/blog/2014/jmm-pragmatics/#_happens_before_test_your_understanding
final int volatileRead = volatileField;
volatileField = context.getLine();
} else {
UNSAFE.fullFence();
}
return context.nil;
}
@JRubyMethod(name = "instance_variable_get_volatile", visibility = Visibility.PUBLIC)
public static IRubyObject instanceVariableGetVolatile(
ThreadContext context,
IRubyObject self,
IRubyObject name) {
// Ensure we ses latest value with loadFence
if (!FULL_FENCE) {
// piggybacking on volatile read, simulating loadFence
final int volatileRead = volatileField;
return ((RubyBasicObject) self).instance_variable_get(context, name);
} else {
UNSAFE.loadFence();
return ((RubyBasicObject) self).instance_variable_get(context, name);
}
}
@JRubyMethod(name = "instance_variable_set_volatile", visibility = Visibility.PUBLIC)
public static IRubyObject InstanceVariableSetVolatile(
ThreadContext context,
IRubyObject self,
IRubyObject name,
IRubyObject value) {
// Ensure we make last update visible
if (!FULL_FENCE) {
// piggybacking on volatile write, simulating storeFence
final IRubyObject result = ((RubyBasicObject) self).instance_variable_set(name, value);
volatileField = context.getLine();
return result;
} else {
// JRuby uses StampedVariableAccessor which calls fullFence
// so no additional steps needed.
// See https://github.com/jruby/jruby/blob/master/core/src/main/java/org/jruby/runtime/ivars/StampedVariableAccessor.java#L151-L159
return ((RubyBasicObject) self).instance_variable_set(name, value);
}
}
}
@JRubyClass(name = "JRubyObject", parent = "AbstractObject")
public static class JRubyObject extends RubyObject {
public JRubyObject(Ruby runtime, RubyClass metaClass) {
super(runtime, metaClass);
}
}
@JRubyClass(name = "Object", parent = "JRubyObject")
public static class Object extends JRubyObject {
public Object(Ruby runtime, RubyClass metaClass) {
super(runtime, metaClass);
}
}
@JRubyClass(name = "AbstractLockableObject", parent = "Object")
public static class AbstractLockableObject extends Object {
public AbstractLockableObject(Ruby runtime, RubyClass metaClass) {
super(runtime, metaClass);
}
}
@JRubyClass(name = "JRubyLockableObject", parent = "AbstractLockableObject")
public static class JRubyLockableObject extends JRubyObject {
public JRubyLockableObject(Ruby runtime, RubyClass metaClass) {
super(runtime, metaClass);
}
@JRubyMethod(name = "synchronize", visibility = Visibility.PROTECTED)
public IRubyObject rubySynchronize(ThreadContext context, Block block) {
synchronized (this) {
return block.yield(context, null);
}
}
@JRubyMethod(name = "ns_wait", optional = 1, visibility = Visibility.PROTECTED)
public IRubyObject nsWait(ThreadContext context, IRubyObject[] args) {
Ruby runtime = context.runtime;
if (args.length > 1) {
throw runtime.newArgumentError(args.length, 1);
}
Double timeout = null;
if (args.length > 0 && !args[0].isNil()) {
timeout = args[0].convertToFloat().getDoubleValue();
if (timeout < 0) {
throw runtime.newArgumentError("time interval must be positive");
}
}
if (Thread.interrupted()) {
throw runtime.newConcurrencyError("thread interrupted");
}
boolean success = false;
try {
success = context.getThread().wait_timeout(this, timeout);
} catch (InterruptedException ie) {
throw runtime.newConcurrencyError(ie.getLocalizedMessage());
} finally {
// An interrupt or timeout may have caused us to miss
// a notify that we consumed, so do another notify in
// case someone else is available to pick it up.
if (!success) {
this.notify();
}
}
return this;
}
@JRubyMethod(name = "ns_signal", visibility = Visibility.PROTECTED)
public IRubyObject nsSignal(ThreadContext context) {
notify();
return this;
}
@JRubyMethod(name = "ns_broadcast", visibility = Visibility.PROTECTED)
public IRubyObject nsBroadcast(ThreadContext context) {
notifyAll();
return this;
}
}
@JRubyClass(name = "JRuby")
public static class JRuby extends RubyObject {
public JRuby(Ruby runtime, RubyClass metaClass) {
super(runtime, metaClass);
}
@JRubyMethod(name = "sleep_interruptibly", visibility = Visibility.PUBLIC, module = true)
public static IRubyObject sleepInterruptibly(final ThreadContext context, IRubyObject receiver, final Block block) {
try {
context.getThread().executeBlockingTask(new RubyThread.BlockingTask() {
@Override
public void run() throws InterruptedException {
block.call(context);
}
@Override
public void wakeup() {
context.getThread().getNativeThread().interrupt();
}
});
} catch (InterruptedException e) {
throw context.runtime.newThreadError("interrupted in Concurrent::Synchronization::JRuby.sleep_interruptibly");
}
return context.nil;
}
}
}

View File

@ -1,31 +0,0 @@
package com.concurrent_ruby.ext.jsr166e;
import java.util.Map;
import java.util.Set;
public interface ConcurrentHashMap<K, V> {
/** Interface describing a function of one argument */
public interface Fun<A,T> { T apply(A a); }
/** Interface describing a function of two arguments */
public interface BiFun<A,B,T> { T apply(A a, B b); }
public V get(K key);
public V put(K key, V value);
public V putIfAbsent(K key, V value);
public V computeIfAbsent(K key, Fun<? super K, ? extends V> mf);
public V computeIfPresent(K key, BiFun<? super K, ? super V, ? extends V> mf);
public V compute(K key, BiFun<? super K, ? super V, ? extends V> mf);
public V merge(K key, V value, BiFun<? super V, ? super V, ? extends V> mf);
public boolean replace(K key, V oldVal, V newVal);
public V replace(K key, V value);
public boolean containsKey(K key);
public boolean remove(Object key, Object value);
public V remove(K key);
public void clear();
public Set<Map.Entry<K,V>> entrySet();
public int size();
public V getValueOrDefault(Object key, V defaultValue);
public boolean containsValue(V value);
public K findKey(V value);
}

View File

@ -1,203 +0,0 @@
/*
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// This is based on 1.9 version.
package com.concurrent_ruby.ext.jsr166e;
import java.util.concurrent.atomic.AtomicLong;
import java.io.IOException;
import java.io.Serializable;
import java.io.ObjectInputStream;
/**
* One or more variables that together maintain an initially zero
* {@code long} sum. When updates (method {@link #add}) are contended
* across threads, the set of variables may grow dynamically to reduce
* contention. Method {@link #sum} (or, equivalently, {@link
* #longValue}) returns the current total combined across the
* variables maintaining the sum.
*
* <p>This class is usually preferable to {@link AtomicLong} when
* multiple threads update a common sum that is used for purposes such
* as collecting statistics, not for fine-grained synchronization
* control. Under low update contention, the two classes have similar
* characteristics. But under high contention, expected throughput of
* this class is significantly higher, at the expense of higher space
* consumption.
*
* <p>This class extends {@link Number}, but does <em>not</em> define
* methods such as {@code hashCode} and {@code compareTo} because
* instances are expected to be mutated, and so are not useful as
* collection keys.
*
* <p><em>jsr166e note: This class is targeted to be placed in
* java.util.concurrent.atomic.</em>
*
* @since 1.8
* @author Doug Lea
*/
public class LongAdder extends Striped64 implements Serializable {
private static final long serialVersionUID = 7249069246863182397L;
/**
* Version of plus for use in retryUpdate
*/
final long fn(long v, long x) { return v + x; }
/**
* Creates a new adder with initial sum of zero.
*/
public LongAdder() {
}
/**
* Adds the given value.
*
* @param x the value to add
*/
public void add(long x) {
Cell[] as; long b, v; HashCode hc; Cell a; int n;
if ((as = cells) != null || !casBase(b = base, b + x)) {
boolean uncontended = true;
int h = (hc = threadHashCode.get()).code;
if (as == null || (n = as.length) < 1 ||
(a = as[(n - 1) & h]) == null ||
!(uncontended = a.cas(v = a.value, v + x)))
retryUpdate(x, hc, uncontended);
}
}
/**
* Equivalent to {@code add(1)}.
*/
public void increment() {
add(1L);
}
/**
* Equivalent to {@code add(-1)}.
*/
public void decrement() {
add(-1L);
}
/**
* Returns the current sum. The returned value is <em>NOT</em> an
* atomic snapshot: Invocation in the absence of concurrent
* updates returns an accurate result, but concurrent updates that
* occur while the sum is being calculated might not be
* incorporated.
*
* @return the sum
*/
public long sum() {
long sum = base;
Cell[] as = cells;
if (as != null) {
int n = as.length;
for (int i = 0; i < n; ++i) {
Cell a = as[i];
if (a != null)
sum += a.value;
}
}
return sum;
}
/**
* Resets variables maintaining the sum to zero. This method may
* be a useful alternative to creating a new adder, but is only
* effective if there are no concurrent updates. Because this
* method is intrinsically racy, it should only be used when it is
* known that no threads are concurrently updating.
*/
public void reset() {
internalReset(0L);
}
/**
* Equivalent in effect to {@link #sum} followed by {@link
* #reset}. This method may apply for example during quiescent
* points between multithreaded computations. If there are
* updates concurrent with this method, the returned value is
* <em>not</em> guaranteed to be the final value occurring before
* the reset.
*
* @return the sum
*/
public long sumThenReset() {
long sum = base;
Cell[] as = cells;
base = 0L;
if (as != null) {
int n = as.length;
for (int i = 0; i < n; ++i) {
Cell a = as[i];
if (a != null) {
sum += a.value;
a.value = 0L;
}
}
}
return sum;
}
/**
* Returns the String representation of the {@link #sum}.
* @return the String representation of the {@link #sum}
*/
public String toString() {
return Long.toString(sum());
}
/**
* Equivalent to {@link #sum}.
*
* @return the sum
*/
public long longValue() {
return sum();
}
/**
* Returns the {@link #sum} as an {@code int} after a narrowing
* primitive conversion.
*/
public int intValue() {
return (int)sum();
}
/**
* Returns the {@link #sum} as a {@code float}
* after a widening primitive conversion.
*/
public float floatValue() {
return (float)sum();
}
/**
* Returns the {@link #sum} as a {@code double} after a widening
* primitive conversion.
*/
public double doubleValue() {
return (double)sum();
}
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
s.defaultWriteObject();
s.writeLong(sum());
}
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject();
busy = 0;
cells = null;
base = s.readLong();
}
}

View File

@ -1,342 +0,0 @@
/*
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// This is based on 1.5 version.
package com.concurrent_ruby.ext.jsr166e;
import java.util.Random;
/**
* A package-local class holding common representation and mechanics
* for classes supporting dynamic striping on 64bit values. The class
* extends Number so that concrete subclasses must publicly do so.
*/
abstract class Striped64 extends Number {
/*
* This class maintains a lazily-initialized table of atomically
* updated variables, plus an extra "base" field. The table size
* is a power of two. Indexing uses masked per-thread hash codes.
* Nearly all declarations in this class are package-private,
* accessed directly by subclasses.
*
* Table entries are of class Cell; a variant of AtomicLong padded
* to reduce cache contention on most processors. Padding is
* overkill for most Atomics because they are usually irregularly
* scattered in memory and thus don't interfere much with each
* other. But Atomic objects residing in arrays will tend to be
* placed adjacent to each other, and so will most often share
* cache lines (with a huge negative performance impact) without
* this precaution.
*
* In part because Cells are relatively large, we avoid creating
* them until they are needed. When there is no contention, all
* updates are made to the base field. Upon first contention (a
* failed CAS on base update), the table is initialized to size 2.
* The table size is doubled upon further contention until
* reaching the nearest power of two greater than or equal to the
* number of CPUS. Table slots remain empty (null) until they are
* needed.
*
* A single spinlock ("busy") is used for initializing and
* resizing the table, as well as populating slots with new Cells.
* There is no need for a blocking lock: When the lock is not
* available, threads try other slots (or the base). During these
* retries, there is increased contention and reduced locality,
* which is still better than alternatives.
*
* Per-thread hash codes are initialized to random values.
* Contention and/or table collisions are indicated by failed
* CASes when performing an update operation (see method
* retryUpdate). Upon a collision, if the table size is less than
* the capacity, it is doubled in size unless some other thread
* holds the lock. If a hashed slot is empty, and lock is
* available, a new Cell is created. Otherwise, if the slot
* exists, a CAS is tried. Retries proceed by "double hashing",
* using a secondary hash (Marsaglia XorShift) to try to find a
* free slot.
*
* The table size is capped because, when there are more threads
* than CPUs, supposing that each thread were bound to a CPU,
* there would exist a perfect hash function mapping threads to
* slots that eliminates collisions. When we reach capacity, we
* search for this mapping by randomly varying the hash codes of
* colliding threads. Because search is random, and collisions
* only become known via CAS failures, convergence can be slow,
* and because threads are typically not bound to CPUS forever,
* may not occur at all. However, despite these limitations,
* observed contention rates are typically low in these cases.
*
* It is possible for a Cell to become unused when threads that
* once hashed to it terminate, as well as in the case where
* doubling the table causes no thread to hash to it under
* expanded mask. We do not try to detect or remove such cells,
* under the assumption that for long-running instances, observed
* contention levels will recur, so the cells will eventually be
* needed again; and for short-lived ones, it does not matter.
*/
/**
* Padded variant of AtomicLong supporting only raw accesses plus CAS.
* The value field is placed between pads, hoping that the JVM doesn't
* reorder them.
*
* JVM intrinsics note: It would be possible to use a release-only
* form of CAS here, if it were provided.
*/
static final class Cell {
volatile long p0, p1, p2, p3, p4, p5, p6;
volatile long value;
volatile long q0, q1, q2, q3, q4, q5, q6;
Cell(long x) { value = x; }
final boolean cas(long cmp, long val) {
return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val);
}
// Unsafe mechanics
private static final sun.misc.Unsafe UNSAFE;
private static final long valueOffset;
static {
try {
UNSAFE = getUnsafe();
Class<?> ak = Cell.class;
valueOffset = UNSAFE.objectFieldOffset
(ak.getDeclaredField("value"));
} catch (Exception e) {
throw new Error(e);
}
}
}
/**
* Holder for the thread-local hash code. The code is initially
* random, but may be set to a different value upon collisions.
*/
static final class HashCode {
static final Random rng = new Random();
int code;
HashCode() {
int h = rng.nextInt(); // Avoid zero to allow xorShift rehash
code = (h == 0) ? 1 : h;
}
}
/**
* The corresponding ThreadLocal class
*/
static final class ThreadHashCode extends ThreadLocal<HashCode> {
public HashCode initialValue() { return new HashCode(); }
}
/**
* Static per-thread hash codes. Shared across all instances to
* reduce ThreadLocal pollution and because adjustments due to
* collisions in one table are likely to be appropriate for
* others.
*/
static final ThreadHashCode threadHashCode = new ThreadHashCode();
/** Number of CPUS, to place bound on table size */
static final int NCPU = Runtime.getRuntime().availableProcessors();
/**
* Table of cells. When non-null, size is a power of 2.
*/
transient volatile Cell[] cells;
/**
* Base value, used mainly when there is no contention, but also as
* a fallback during table initialization races. Updated via CAS.
*/
transient volatile long base;
/**
* Spinlock (locked via CAS) used when resizing and/or creating Cells.
*/
transient volatile int busy;
/**
* Package-private default constructor
*/
Striped64() {
}
/**
* CASes the base field.
*/
final boolean casBase(long cmp, long val) {
return UNSAFE.compareAndSwapLong(this, baseOffset, cmp, val);
}
/**
* CASes the busy field from 0 to 1 to acquire lock.
*/
final boolean casBusy() {
return UNSAFE.compareAndSwapInt(this, busyOffset, 0, 1);
}
/**
* Computes the function of current and new value. Subclasses
* should open-code this update function for most uses, but the
* virtualized form is needed within retryUpdate.
*
* @param currentValue the current value (of either base or a cell)
* @param newValue the argument from a user update call
* @return result of the update function
*/
abstract long fn(long currentValue, long newValue);
/**
* Handles cases of updates involving initialization, resizing,
* creating new Cells, and/or contention. See above for
* explanation. This method suffers the usual non-modularity
* problems of optimistic retry code, relying on rechecked sets of
* reads.
*
* @param x the value
* @param hc the hash code holder
* @param wasUncontended false if CAS failed before call
*/
final void retryUpdate(long x, HashCode hc, boolean wasUncontended) {
int h = hc.code;
boolean collide = false; // True if last slot nonempty
for (;;) {
Cell[] as; Cell a; int n; long v;
if ((as = cells) != null && (n = as.length) > 0) {
if ((a = as[(n - 1) & h]) == null) {
if (busy == 0) { // Try to attach new Cell
Cell r = new Cell(x); // Optimistically create
if (busy == 0 && casBusy()) {
boolean created = false;
try { // Recheck under lock
Cell[] rs; int m, j;
if ((rs = cells) != null &&
(m = rs.length) > 0 &&
rs[j = (m - 1) & h] == null) {
rs[j] = r;
created = true;
}
} finally {
busy = 0;
}
if (created)
break;
continue; // Slot is now non-empty
}
}
collide = false;
}
else if (!wasUncontended) // CAS already known to fail
wasUncontended = true; // Continue after rehash
else if (a.cas(v = a.value, fn(v, x)))
break;
else if (n >= NCPU || cells != as)
collide = false; // At max size or stale
else if (!collide)
collide = true;
else if (busy == 0 && casBusy()) {
try {
if (cells == as) { // Expand table unless stale
Cell[] rs = new Cell[n << 1];
for (int i = 0; i < n; ++i)
rs[i] = as[i];
cells = rs;
}
} finally {
busy = 0;
}
collide = false;
continue; // Retry with expanded table
}
h ^= h << 13; // Rehash
h ^= h >>> 17;
h ^= h << 5;
}
else if (busy == 0 && cells == as && casBusy()) {
boolean init = false;
try { // Initialize table
if (cells == as) {
Cell[] rs = new Cell[2];
rs[h & 1] = new Cell(x);
cells = rs;
init = true;
}
} finally {
busy = 0;
}
if (init)
break;
}
else if (casBase(v = base, fn(v, x)))
break; // Fall back on using base
}
hc.code = h; // Record index for next time
}
/**
* Sets base and all cells to the given value.
*/
final void internalReset(long initialValue) {
Cell[] as = cells;
base = initialValue;
if (as != null) {
int n = as.length;
for (int i = 0; i < n; ++i) {
Cell a = as[i];
if (a != null)
a.value = initialValue;
}
}
}
// Unsafe mechanics
private static final sun.misc.Unsafe UNSAFE;
private static final long baseOffset;
private static final long busyOffset;
static {
try {
UNSAFE = getUnsafe();
Class<?> sk = Striped64.class;
baseOffset = UNSAFE.objectFieldOffset
(sk.getDeclaredField("base"));
busyOffset = UNSAFE.objectFieldOffset
(sk.getDeclaredField("busy"));
} catch (Exception e) {
throw new Error(e);
}
}
/**
* Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
* Replace with a simple call to Unsafe.getUnsafe when integrating
* into a jdk.
*
* @return a sun.misc.Unsafe
*/
private static sun.misc.Unsafe getUnsafe() {
try {
return sun.misc.Unsafe.getUnsafe();
} catch (SecurityException se) {
try {
return java.security.AccessController.doPrivileged
(new java.security
.PrivilegedExceptionAction<sun.misc.Unsafe>() {
public sun.misc.Unsafe run() throws Exception {
java.lang.reflect.Field f = sun.misc
.Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (sun.misc.Unsafe) f.get(null);
}});
} catch (java.security.PrivilegedActionException e) {
throw new RuntimeException("Could not initialize intrinsics",
e.getCause());
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More