tsafe 0.0.6 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,6 +9,7 @@ GEM
9
9
  rake
10
10
  rdoc
11
11
  json (1.7.3)
12
+ json (1.7.3-java)
12
13
  rake (0.9.2.2)
13
14
  rdoc (3.12)
14
15
  json (~> 1.4)
@@ -22,6 +23,7 @@ GEM
22
23
  rspec-mocks (2.8.0)
23
24
 
24
25
  PLATFORMS
26
+ java
25
27
  ruby
26
28
 
27
29
  DEPENDENCIES
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.6
1
+ 0.0.9
@@ -4,14 +4,21 @@ require "monitor"
4
4
  module Tsafe
5
5
  #Autoloader for subclasses.
6
6
  def self.const_missing(name)
7
- require "#{File.dirname(__FILE__)}/tsafe_#{name.to_s.downcase}.rb"
7
+ filep = "#{File.dirname(__FILE__)}/tsafe_#{name.to_s.downcase}"
8
+
9
+ if RUBY_ENGINE == "jruby" and File.exists?("#{filep}_jruby.rb")
10
+ require "#{filep}_jruby.rb"
11
+ else
12
+ require filep
13
+ end
14
+
8
15
  raise "Still not loaded: '#{name}'." if !Tsafe.const_defined?(name)
9
16
  return Tsafe.const_get(name)
10
17
  end
11
18
 
12
- #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.
19
+ #JRuby can corrupt an array in a threadded env. Use this method to only get a synchronized array when running JRuby in order to not having to write "if RUBY_ENGINE"-stuff.
13
20
  def self.std_array
14
- return MonArray.new if RUBY_ENGINE == "jruby"
21
+ return Tsafe::MonArray.new if RUBY_ENGINE == "jruby"
15
22
  return []
16
23
  end
17
24
  end
@@ -8,5 +8,5 @@ class Tsafe::MonArray < ::Array
8
8
  @@tsafe_rwmutex_w_methods = [:<<, :collect, :collect!, :compact!, :delete, :delete_at, :delete_if, :drop, :drop_while, :fill, :flatten!, :insert, :keep_if, :map, :map!, :replace, :shuffle!, :slice!, :shift, :sort!, :sort_by!, :unshift]
9
9
  @@tsafe_rwmutex_r_methods = [:each, :each_index, :take_while]
10
10
 
11
- include Tsafe::SynModule
11
+ include Tsafe::Mrswlock_synmodule
12
12
  end
@@ -8,5 +8,5 @@ class Tsafe::MonHash < ::Hash
8
8
  @@tsafe_mrswlock_w_methods = [:[]=, :clear, :delete, :delete_if, :keep_if, :merge!, :rehash, :reject!, :replace, :select!, :shift, :store, :update, :values_at]
9
9
  @@tsafe_mrswlock_r_methods = [:each, :each_key, :each_pair, :each_value]
10
10
 
11
- include Tsafe::Mrswlock::SynModule
11
+ include Tsafe::Mrswlock_synmodule
12
12
  end
@@ -1,7 +1,7 @@
1
- #A class that allows many simultanious read-synchronizations but locks both reading and writing while calling the write-synchronzie-method.
1
+ # A class that allows many simultanious read-synchronizations but locks both reading and writing while calling the write-synchronzie-method.
2
+ # This version does not work in JRuby! 'const_missing'-autoloader should automatically load the JRuby-version.
3
+ # It is not 'actually' thread-safe, but because of GIL, it wont bug up. If it was actually thread-safe, the performance would go down. So it only works with GIL.
2
4
  class Tsafe::Mrswlock
3
- @@debug = false
4
-
5
5
  # Sets various variables.
6
6
  def initialize
7
7
  @reads = 0
@@ -18,15 +18,9 @@ class Tsafe::Mrswlock
18
18
  def rsync
19
19
  begin
20
20
  tid = Thread.current.__id__
21
-
22
- while @w_mutex.locked? and @locked_by != tid
23
- Thread.pass
24
- print "Passed because lock.\n" if @@debug
25
- end
26
-
21
+ Thread.pass while @w_mutex.locked? and @locked_by != tid
27
22
  @reading_threads[tid] = true
28
23
  @reads += 1
29
- print "Reading more than one at a time! (#{@reads})\n" if @@debug and @reads >= 2
30
24
  yield
31
25
  ensure
32
26
  @reading_threads.delete(tid)
@@ -48,12 +42,8 @@ class Tsafe::Mrswlock
48
42
  #Wait for any reads to finish that might have started while we were getting the lock.
49
43
  #Also allow write if there is only one reading thread and that reading thread is the current thread.
50
44
  while @reads > 0
51
- if @reading_threads.key?(tid)
52
- raise ThreadError, "Deadlock: Writing is not allowed while reading."
53
- end
54
-
45
+ raise ThreadError, "Deadlock: Writing is not allowed while reading." if @reading_threads.key?(tid)
55
46
  Thread.pass
56
- print "Passed because reading.\n" if @@debug
57
47
  end
58
48
 
59
49
  yield
@@ -62,68 +52,4 @@ class Tsafe::Mrswlock
62
52
  end
63
53
  end
64
54
  end
65
-
66
- #This module can be included in order to painlessly make a thread-safe multi-reader-single-writer thread-safe copy of a class.
67
- #===Examples
68
- # class Tsafe::MonHash < ::Hash
69
- # @@tsafe_mrswlock_w_methods = [:[]=, :clear, :delete, :delete_if, :keep_if, :merge!, :rehash, :reject!, :replace, :select!, :shift, :store, :update, :values_at]
70
- # @@tsafe_mrswlock_r_methods = [:each, :each_key, :each_pair, :each_value]
71
- # include Tsafe::Mrswlock::SynModule
72
- # end
73
- module SynModule
74
- def self.included(base)
75
- base.to_s.split("::").inject(Object, :const_get).class_eval do
76
- #Yields the given block within the read-lock.
77
- #===Examples
78
- # obj._tsafe_rsync do
79
- # #do something within read-lock.
80
- # end
81
- def _tsafe_rsync(&block)
82
- @tsafe_mrswlock.rsync(&block)
83
- end
84
-
85
- #Yields the given block within the write-lock (and read-lock).
86
- #===Examples
87
- # obj._tsafe_wsync do
88
- # #do something within write-lock.
89
- # end
90
- def _tsafe_wsync(&block)
91
- @tsafe_mrswlock.rsync(&block)
92
- end
93
-
94
- #Rename initialize.
95
- alias_method(:initialize_mrswlock, :initialize)
96
-
97
- #Make another initialize-method that spawns the lock and then calls the original initialize.
98
- define_method(:initialize) do |*args, &block|
99
- @tsafe_mrswlock = Tsafe::Mrswlock.new
100
- return initialize_mrswlock(*args, &block)
101
- end
102
-
103
- #Makes reader methods go through reader-lock.
104
- base.class_variable_get(:@@tsafe_mrswlock_r_methods).each do |mname|
105
- newmname = "tsafe_mrswlock_#{mname}".to_sym
106
- alias_method(newmname, mname)
107
-
108
- define_method(mname) do |*args, &block|
109
- @tsafe_mrswlock.rsync do
110
- return self.__send__(newmname, *args, &block)
111
- end
112
- end
113
- end
114
-
115
- #Makes writer methods go through writer-lock.
116
- base.class_variable_get(:@@tsafe_mrswlock_w_methods).each do |mname|
117
- newmname = "tsafe_mrswlock_#{mname}".to_sym
118
- alias_method(newmname, mname)
119
-
120
- define_method(mname) do |*args, &block|
121
- @tsafe_mrswlock.wsync do
122
- return self.__send__(newmname, *args, &block)
123
- end
124
- end
125
- end
126
- end
127
- end
128
- end
129
55
  end
@@ -0,0 +1,45 @@
1
+ require "java"
2
+
3
+ # A class that allows many simultanious read-synchronizations but locks both reading and writing while calling the write-synchronzie-method.
4
+ # This is the JRuby-version and will not work under anything else. It uses 'java.util.concurrent.locks.ReentrantReadWriteLock' instead of doing the locking in Ruby.
5
+ class Tsafe::Mrswlock
6
+ # Sets various variables.
7
+ def initialize
8
+ @lock = java.util.concurrent.locks.ReentrantReadWriteLock.new
9
+
10
+ #This hash holds thread-IDs for threads that are reading.
11
+ @reading_threads = {}
12
+ end
13
+
14
+ # Runs the given block through the read-synchronization.
15
+ def rsync
16
+ @lock.read_lock.lock
17
+ tid = Thread.current.__id__
18
+ @reading_threads[tid] = true
19
+
20
+ begin
21
+ yield
22
+ ensure
23
+ @reading_threads.delete(tid)
24
+ @lock.read_lock.unlock
25
+ end
26
+ end
27
+
28
+ #Runs the given block through the write-synchronization (locks both reading and writing).
29
+ #===Examples
30
+ # lock.wsync do
31
+ # #do something within lock.
32
+ # end
33
+ def wsync
34
+ tid = Thread.current.__id__
35
+ raise ThreadError, "Deadlock: Writing is not allowed while reading." if @reading_threads.key?(tid)
36
+
37
+ begin
38
+ @wlock_by = tid
39
+ @lock.write_lock.lock
40
+ yield
41
+ ensure
42
+ @lock.write_lock.unlock
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,63 @@
1
+ # This module can be included in order to painlessly make a thread-safe multi-reader-single-writer thread-safe copy of a class.
2
+ #===Examples
3
+ # class Tsafe::MonHash < ::Hash
4
+ # @@tsafe_mrswlock_w_methods = [:[]=, :clear, :delete, :delete_if, :keep_if, :merge!, :rehash, :reject!, :replace, :select!, :shift, :store, :update, :values_at]
5
+ # @@tsafe_mrswlock_r_methods = [:each, :each_key, :each_pair, :each_value]
6
+ # include Tsafe::Mrswlock::SynModule
7
+ # end
8
+ module Tsafe::Mrswlock_synmodule
9
+ def self.included(base)
10
+ base.to_s.split("::").inject(Object, :const_get).class_eval do
11
+ #Yields the given block within the read-lock.
12
+ #===Examples
13
+ # obj._tsafe_rsync do
14
+ # #do something within read-lock.
15
+ # end
16
+ def _tsafe_rsync(&block)
17
+ @tsafe_mrswlock.rsync(&block)
18
+ end
19
+
20
+ #Yields the given block within the write-lock (and read-lock).
21
+ #===Examples
22
+ # obj._tsafe_wsync do
23
+ # #do something within write-lock.
24
+ # end
25
+ def _tsafe_wsync(&block)
26
+ @tsafe_mrswlock.rsync(&block)
27
+ end
28
+
29
+ #Rename initialize.
30
+ alias_method(:initialize_mrswlock, :initialize)
31
+
32
+ #Make another initialize-method that spawns the lock and then calls the original initialize.
33
+ define_method(:initialize) do |*args, &block|
34
+ @tsafe_mrswlock = Tsafe::Mrswlock.new
35
+ return initialize_mrswlock(*args, &block)
36
+ end
37
+
38
+ #Makes reader methods go through reader-lock.
39
+ base.class_variable_get(:@@tsafe_mrswlock_r_methods).each do |mname|
40
+ newmname = "tsafe_mrswlock_#{mname}".to_sym
41
+ alias_method(newmname, mname)
42
+
43
+ define_method(mname) do |*args, &block|
44
+ @tsafe_mrswlock.rsync do
45
+ return self.__send__(newmname, *args, &block)
46
+ end
47
+ end
48
+ end
49
+
50
+ #Makes writer methods go through writer-lock.
51
+ base.class_variable_get(:@@tsafe_mrswlock_w_methods).each do |mname|
52
+ newmname = "tsafe_mrswlock_#{mname}".to_sym
53
+ alias_method(newmname, mname)
54
+
55
+ define_method(mname) do |*args, &block|
56
+ @tsafe_mrswlock.wsync do
57
+ return self.__send__(newmname, *args, &block)
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{tsafe}
8
- s.version = "0.0.6"
8
+ s.version = "0.0.9"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kasper Johansen"]
12
- s.date = %q{2012-07-25}
12
+ s.date = %q{2012-07-27}
13
13
  s.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.}
14
14
  s.email = %q{k@spernj.org}
15
15
  s.extra_rdoc_files = [
@@ -30,6 +30,8 @@ Gem::Specification.new do |s|
30
30
  "lib/tsafe_monhash.rb",
31
31
  "lib/tsafe_monitored.rb",
32
32
  "lib/tsafe_mrswlock.rb",
33
+ "lib/tsafe_mrswlock_jruby.rb",
34
+ "lib/tsafe_mrswlock_synmodule.rb",
33
35
  "lib/tsafe_mutexed.rb",
34
36
  "lib/tsafe_proxy.rb",
35
37
  "spec/mrswlock_spec.rb",
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: tsafe
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.6
5
+ version: 0.0.9
6
6
  platform: ruby
7
7
  authors:
8
8
  - Kasper Johansen
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-07-25 00:00:00 +02:00
13
+ date: 2012-07-27 00:00:00 +02:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -80,6 +80,8 @@ files:
80
80
  - lib/tsafe_monhash.rb
81
81
  - lib/tsafe_monitored.rb
82
82
  - lib/tsafe_mrswlock.rb
83
+ - lib/tsafe_mrswlock_jruby.rb
84
+ - lib/tsafe_mrswlock_synmodule.rb
83
85
  - lib/tsafe_mutexed.rb
84
86
  - lib/tsafe_proxy.rb
85
87
  - spec/mrswlock_spec.rb
@@ -100,7 +102,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
100
102
  requirements:
101
103
  - - ">="
102
104
  - !ruby/object:Gem::Version
103
- hash: 1466962052017061704
105
+ hash: 3863386299653534485
104
106
  segments:
105
107
  - 0
106
108
  version: "0"