lib/tsafe_mrswlock.rb in tsafe-0.0.6 vs lib/tsafe_mrswlock.rb in tsafe-0.0.9

- old
+ new

@@ -1,9 +1,9 @@ -#A class that allows many simultanious read-synchronizations but locks both reading and writing while calling the write-synchronzie-method. +# A class that allows many simultanious read-synchronizations but locks both reading and writing while calling the write-synchronzie-method. +# This version does not work in JRuby! 'const_missing'-autoloader should automatically load the JRuby-version. +# 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. class Tsafe::Mrswlock - @@debug = false - # Sets various variables. def initialize @reads = 0 @w_mutex = Mutex.new @@ -16,19 +16,13 @@ # Runs the given block through the read-synchronization. def rsync begin tid = Thread.current.__id__ - - while @w_mutex.locked? and @locked_by != tid - Thread.pass - print "Passed because lock.\n" if @@debug - end - + Thread.pass while @w_mutex.locked? and @locked_by != tid @reading_threads[tid] = true @reads += 1 - print "Reading more than one at a time! (#{@reads})\n" if @@debug and @reads >= 2 yield ensure @reading_threads.delete(tid) @reads -= 1 end @@ -46,84 +40,16 @@ @locked_by = tid #Wait for any reads to finish that might have started while we were getting the lock. #Also allow write if there is only one reading thread and that reading thread is the current thread. while @reads > 0 - if @reading_threads.key?(tid) - raise ThreadError, "Deadlock: Writing is not allowed while reading." - end - + raise ThreadError, "Deadlock: Writing is not allowed while reading." if @reading_threads.key?(tid) Thread.pass - print "Passed because reading.\n" if @@debug end yield ensure @locked_by = nil - end - end - end - - #This module can be included in order to painlessly make a thread-safe multi-reader-single-writer thread-safe copy of a class. - #===Examples - # class Tsafe::MonHash < ::Hash - # @@tsafe_mrswlock_w_methods = [:[]=, :clear, :delete, :delete_if, :keep_if, :merge!, :rehash, :reject!, :replace, :select!, :shift, :store, :update, :values_at] - # @@tsafe_mrswlock_r_methods = [:each, :each_key, :each_pair, :each_value] - # include Tsafe::Mrswlock::SynModule - # end - module SynModule - def self.included(base) - base.to_s.split("::").inject(Object, :const_get).class_eval do - #Yields the given block within the read-lock. - #===Examples - # obj._tsafe_rsync do - # #do something within read-lock. - # end - def _tsafe_rsync(&block) - @tsafe_mrswlock.rsync(&block) - end - - #Yields the given block within the write-lock (and read-lock). - #===Examples - # obj._tsafe_wsync do - # #do something within write-lock. - # end - def _tsafe_wsync(&block) - @tsafe_mrswlock.rsync(&block) - end - - #Rename initialize. - alias_method(:initialize_mrswlock, :initialize) - - #Make another initialize-method that spawns the lock and then calls the original initialize. - define_method(:initialize) do |*args, &block| - @tsafe_mrswlock = Tsafe::Mrswlock.new - return initialize_mrswlock(*args, &block) - end - - #Makes reader methods go through reader-lock. - base.class_variable_get(:@@tsafe_mrswlock_r_methods).each do |mname| - newmname = "tsafe_mrswlock_#{mname}".to_sym - alias_method(newmname, mname) - - define_method(mname) do |*args, &block| - @tsafe_mrswlock.rsync do - return self.__send__(newmname, *args, &block) - end - end - end - - #Makes writer methods go through writer-lock. - base.class_variable_get(:@@tsafe_mrswlock_w_methods).each do |mname| - newmname = "tsafe_mrswlock_#{mname}".to_sym - alias_method(newmname, mname) - - define_method(mname) do |*args, &block| - @tsafe_mrswlock.wsync do - return self.__send__(newmname, *args, &block) - end - end - end end end end end \ No newline at end of file