tsafe 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "rspec", "~> 2.8.0"
10
+ gem "rdoc", "~> 3.12"
11
+ gem "bundler", ">= 1.0.0"
12
+ gem "jeweler", "~> 1.8.3"
13
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,31 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.3)
5
+ git (1.2.5)
6
+ jeweler (1.8.3)
7
+ bundler (~> 1.0)
8
+ git (>= 1.2.5)
9
+ rake
10
+ rdoc
11
+ json (1.7.1)
12
+ rake (0.9.2.2)
13
+ rdoc (3.12)
14
+ json (~> 1.4)
15
+ rspec (2.8.0)
16
+ rspec-core (~> 2.8.0)
17
+ rspec-expectations (~> 2.8.0)
18
+ rspec-mocks (~> 2.8.0)
19
+ rspec-core (2.8.0)
20
+ rspec-expectations (2.8.0)
21
+ diff-lcs (~> 1.1.2)
22
+ rspec-mocks (2.8.0)
23
+
24
+ PLATFORMS
25
+ ruby
26
+
27
+ DEPENDENCIES
28
+ bundler (>= 1.0.0)
29
+ jeweler (~> 1.8.3)
30
+ rdoc (~> 3.12)
31
+ rspec (~> 2.8.0)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Kasper Johansen
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = tsafe
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to tsafe
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
9
+ * Fork the project.
10
+ * Start a feature/bugfix branch.
11
+ * Commit and push until you are happy with your contribution.
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2012 Kasper Johansen. See LICENSE.txt for
18
+ further details.
19
+
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "tsafe"
18
+ gem.homepage = "http://github.com/kaspernj/tsafe"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Threadsafe proxy, array, hash and framework for making other classes threadsafe.}
21
+ gem.description = %Q{Proxy-objects for making another object threadsafe by proxying calls through mutex and method_missing. Monitored array and hash where all methods are going through monitor. Threadsafe class for including into a class that extends another class in order to make it threadsafe.}
22
+ gem.email = "k@spernj.org"
23
+ gem.authors = ["Kasper Johansen"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ task :default => :spec
40
+
41
+ require 'rdoc/task'
42
+ Rake::RDocTask.new do |rdoc|
43
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
44
+
45
+ rdoc.rdoc_dir = 'rdoc'
46
+ rdoc.title = "tsafe #{version}"
47
+ rdoc.rdoc_files.include('README*')
48
+ rdoc.rdoc_files.include('lib/**/*.rb')
49
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
data/lib/tsafe.rb ADDED
@@ -0,0 +1,120 @@
1
+ require "monitor"
2
+
3
+ #This module contains various tools to handle thread-safety easily and pretty.
4
+ module Tsafe
5
+ #JRuby can corrupt an array in a threadded env. Use this method to only get a synchronized array when running JRuby and not having to write "if RUBY_ENGINE"-stuff.
6
+ def self.std_array
7
+ return MonArray.new if RUBY_ENGINE == "jruby"
8
+ return []
9
+ end
10
+
11
+ #Instances of this class proxies calls to a given-object by using a mutex or monitor.
12
+ #
13
+ #==== Examples
14
+ # threadsafe_array = Tsafe::Proxy.new(:obj => [])
15
+ # threadsafe_array << 5
16
+ # ret = threadsafe_array[0]
17
+ #
18
+ # threadsafe_array = Tsafe::Proxy.new(:obj => [], :monitor => true)
19
+ class Proxy
20
+ #Spawn needed vars.
21
+ def initialize(args)
22
+ if args[:monitor]
23
+ @mutex = Monitor.new
24
+ elsif args[:mutex]
25
+ @mutex = args[:mutex]
26
+ else
27
+ @mutex = Mutex.new
28
+ end
29
+
30
+ @obj = args[:obj]
31
+ end
32
+
33
+ #Proxies all calls to this object through the mutex.
34
+ def method_missing(method_name, *args, &block)
35
+ @mutex.synchronize do
36
+ @obj.__send__(method_name, *args, &block)
37
+ end
38
+ end
39
+ end
40
+
41
+ #This module can be included on a class to make all method-calls synchronized (by using monitor). Examples with array and hash are below.
42
+ #
43
+ #===Examples
44
+ # class MySyncedClass < SomeOtherClassThatNeedsToBeSynchronized
45
+ # include Tsafe::Monitored
46
+ # end
47
+ module Monitored
48
+ def self.included(base)
49
+ base.to_s.split("::").inject(Object, :const_get).class_eval do
50
+ self.instance_methods.each do |method_name|
51
+ #These two methods create warnings under JRuby.
52
+ if RUBY_ENGINE == "jruby"
53
+ next if method_name == :instance_exec or method_name == :instance_eval
54
+ end
55
+
56
+ new_method_name = "_ts_#{method_name}"
57
+ alias_method(new_method_name, method_name)
58
+
59
+ define_method method_name do |*args, &block|
60
+ #Need to use monitor, since the internal calls might have to run not-synchronized, and we have just overwritten the internal methods.
61
+ @_ts_mutex = Monitor.new if !@_ts_mutex
62
+ @_ts_mutex.synchronize do
63
+ return self._ts___send__(new_method_name, *args, &block)
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ #This module can be included on a class to make all method-calls synchronized (by using mutex). Examples with array and hash are below.
72
+ #
73
+ #===Examples
74
+ # class MySyncedClass < SomeOtherClassThatNeedsToBeSynchronized
75
+ # include Tsafe::Mutexed
76
+ # end
77
+ module Mutexed
78
+ def self.included(base)
79
+ base.to_s.split("::").inject(Object, :const_get).class_eval do
80
+ self.instance_methods.each do |method_name|
81
+ #These two methods create warnings under JRuby.
82
+ if RUBY_ENGINE == "jruby"
83
+ next if method_name == :instance_exec or method_name == :instance_eval
84
+ end
85
+
86
+ new_method_name = "_ts_#{method_name}"
87
+ alias_method(new_method_name, method_name)
88
+
89
+ define_method method_name do |*args, &block|
90
+ #Need to use monitor, since the internal calls might have to run not-synchronized, and we have just overwritten the internal methods.
91
+ @_ts_mutex = Mutex.new if !@_ts_mutex
92
+ @_ts_mutex.synchronize do
93
+ return self._ts___send__(new_method_name, *args, &block)
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+
101
+ #Predefined synchronized array.
102
+ #
103
+ #===Examples
104
+ # arr = Tsafe::MonArray.new
105
+ # arr << 5
106
+ # ret = arr[0]
107
+ class MonArray < ::Array
108
+ include Monitored
109
+ end
110
+
111
+ #Predefined synchronized hash.
112
+ #
113
+ #===Examples
114
+ # h = Tsafe::MonHash.new
115
+ # h['test'] = 'trala'
116
+ # ret = h['test']
117
+ class MonHash < ::Hash
118
+ include Monitored
119
+ end
120
+ end
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'tsafe'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
@@ -0,0 +1,61 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Tsafe" do
4
+ it "should be able to spawn threadsafe proxy-objects" do
5
+ arr = Tsafe::Proxy.new(:obj => {})
6
+
7
+ 0.upto(5) do |i|
8
+ arr[i] = i
9
+ end
10
+
11
+ Thread.new do
12
+ begin
13
+ arr.each do |key, val|
14
+ res = key + val
15
+ sleep 0.1
16
+ end
17
+ rescue Exception => e
18
+ print e.inspect
19
+ end
20
+ end
21
+
22
+ 5.upto(10) do |i|
23
+ arr[i] = i
24
+ sleep 0.1
25
+ end
26
+ end
27
+
28
+ it "should be able to spawn special classes" do
29
+ #Create new synchronized hash.
30
+ arr = Tsafe::MonHash.new
31
+
32
+ #Make sure we get the right results.
33
+ arr[1] = 2
34
+
35
+ res = arr[1]
36
+ raise "Expected 2 but got '#{res}'." if res != 2
37
+
38
+ #Set some values to test with.
39
+ 0.upto(5) do |i|
40
+ arr[i] = i
41
+ end
42
+
43
+ #Try to call through each through a thread and then also try to set new values, which normally would crash the hash.
44
+ Thread.new do
45
+ begin
46
+ arr.each do |key, val|
47
+ res = key + val
48
+ sleep 0.1
49
+ end
50
+ rescue Exception => e
51
+ print e.inspect
52
+ end
53
+ end
54
+
55
+ #This should not crash it, since they should wait for each other.
56
+ 5.upto(10) do |i|
57
+ arr[i] = i
58
+ sleep 0.1
59
+ end
60
+ end
61
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tsafe
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.0
6
+ platform: ruby
7
+ authors:
8
+ - Kasper Johansen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2012-05-10 00:00:00 +02:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rspec
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: 2.8.0
24
+ type: :development
25
+ prerelease: false
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: rdoc
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ~>
33
+ - !ruby/object:Gem::Version
34
+ version: "3.12"
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: bundler
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: 1.0.0
46
+ type: :development
47
+ prerelease: false
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: jeweler
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ version: 1.8.3
57
+ type: :development
58
+ prerelease: false
59
+ version_requirements: *id004
60
+ description: Proxy-objects for making another object threadsafe by proxying calls through mutex and method_missing. Monitored array and hash where all methods are going through monitor. Threadsafe class for including into a class that extends another class in order to make it threadsafe.
61
+ email: k@spernj.org
62
+ executables: []
63
+
64
+ extensions: []
65
+
66
+ extra_rdoc_files:
67
+ - LICENSE.txt
68
+ - README.rdoc
69
+ files:
70
+ - .document
71
+ - .rspec
72
+ - Gemfile
73
+ - Gemfile.lock
74
+ - LICENSE.txt
75
+ - README.rdoc
76
+ - Rakefile
77
+ - VERSION
78
+ - lib/tsafe.rb
79
+ - spec/spec_helper.rb
80
+ - spec/tsafe_spec.rb
81
+ has_rdoc: true
82
+ homepage: http://github.com/kaspernj/tsafe
83
+ licenses:
84
+ - MIT
85
+ post_install_message:
86
+ rdoc_options: []
87
+
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ hash: -3605232843790904975
96
+ segments:
97
+ - 0
98
+ version: "0"
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: "0"
105
+ requirements: []
106
+
107
+ rubyforge_project:
108
+ rubygems_version: 1.6.2
109
+ signing_key:
110
+ specification_version: 3
111
+ summary: Threadsafe proxy, array, hash and framework for making other classes threadsafe.
112
+ test_files: []
113
+