[前][次][番号順一覧][スレッド一覧]

ruby-changes:43044

From: seki <ko1@a...>
Date: Sun, 22 May 2016 20:03:50 +0900 (JST)
Subject: [ruby-changes:43044] seki:r55118 (trunk): use finalizer trick instead of thread.

seki	2016-05-22 20:03:43 +0900 (Sun, 22 May 2016)

  New Revision: 55118

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=55118

  Log:
    use finalizer trick instead of thread.

  Modified files:
    trunk/ChangeLog
    trunk/lib/drb/timeridconv.rb
    trunk/test/drb/ut_timerholder.rb
Index: lib/drb/timeridconv.rb
===================================================================
--- lib/drb/timeridconv.rb	(revision 55117)
+++ lib/drb/timeridconv.rb	(revision 55118)
@@ -24,7 +24,7 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/timeridconv.rb#L24
         @gc = {}
         @renew = {}
         @keeping = keeping
-        @expires = Time.now + @keeping
+        @expires = nil
       end
 
       def add(obj)
@@ -32,18 +32,16 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/timeridconv.rb#L32
           rotate
           key = obj.__id__
           @renew[key] = obj
+          invoke_keeper
           return key
         end
       end
 
-      def fetch(key, dv=@sentinel)
+      def fetch(key)
         synchronize do
           rotate
           obj = peek(key)
-          if obj == @sentinel
-            return dv unless dv == @sentinel
-            raise InvalidIndexError
-          end
+          raise InvalidIndexError if obj == @sentinel
           @renew[key] = obj # KeepIt
           return obj
         end
@@ -51,25 +49,28 @@ module DRb https://github.com/ruby/ruby/blob/trunk/lib/drb/timeridconv.rb#L49
 
       private
       def peek(key)
-        synchronize do
-          return @renew.fetch(key) { @gc.fetch(key, @sentinel) }
-        end
+        return @renew.fetch(key) { @gc.fetch(key, @sentinel) }
       end
 
-      def rotate
-        synchronize do
-          return if @expires > Time.now
-          @gc = @renew      # GCed
-          @renew = {}
-          @expires = Time.now + @keeping
-        end
+      def invoke_keeper
+        return if @expires
+        @expires = Time.now + @keeping
+        on_gc
+      end
+
+      def on_gc
+        return unless Thread.main.alive?
+        return if @expires.nil?
+        Thread.new { rotate } if @expires < Time.now
+        ObjectSpace.define_finalizer(Object.new) {on_gc}          
       end
 
-      def keeper
-        Thread.new do
-          loop do
-            rotate
-            sleep(@keeping)
+      def rotate
+        synchronize do
+          if @expires &.< Time.now
+            @gc = @renew      # GCed
+            @renew = {}
+            @expires = @gc.empty? ? nil : Time.now + @keeping
           end
         end
       end
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 55117)
+++ ChangeLog	(revision 55118)
@@ -1,3 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sun May 22 20:01:21 2016  Masatoshi SEKI  <m_seki@m...>
+
+	* lib/drb/timeridconv.rb: use finalizer trick instead of thread.
+
+	* test/drb/ut_timerholder.rb: ditto.
+
 Sun May 22 17:25:18 2016  Martin Duerst  <duerst@i...>
 
         * test/ruby/enc/test_case_options.rb: adjust test class name
Index: test/drb/ut_timerholder.rb
===================================================================
--- test/drb/ut_timerholder.rb	(revision 55117)
+++ test/drb/ut_timerholder.rb	(revision 55118)
@@ -12,7 +12,6 @@ class TimerIdConvTest < Test::Unit::Test https://github.com/ruby/ruby/blob/trunk/test/drb/ut_timerholder.rb#L12
     key = idconv.to_id(self)
     assert_equal(key, self.__id__)
     sleep(keeping)
-
     assert_equal(idconv.to_id(false), false.__id__)
     assert_equal(idconv.to_obj(key), self)
     sleep(keeping)
@@ -24,11 +23,48 @@ class TimerIdConvTest < Test::Unit::Test https://github.com/ruby/ruby/blob/trunk/test/drb/ut_timerholder.rb#L23
     sleep(keeping)
 
     assert_raise do
-      assert_equal(idconv.to_obj(key))
+      assert_equal(idconv.to_obj(key), self)
+    end
+
+    assert_raise do
+      assert_equal(idconv.to_obj(false.__id__), false)
     end
 
+    key = idconv.to_id(self)
+    assert_equal(key, self.__id__)
+    assert_equal(idconv.to_id(true), true.__id__)
+    sleep(keeping)
+    GC.start
+    sleep(keeping)
+    GC.start
+    assert_raise do
+      assert_equal(idconv.to_obj(key), self)
+    end
+  end
+
+  def test_usecase_02
+    keeping = 0.1
+    idconv = DRb::TimerIdConv.new(keeping)
+
+    key = idconv.to_id(self)
+    assert_equal(key, self.__id__)
+    sleep(keeping)
+    GC.start
+    sleep(keeping)
+    GC.start
+    assert_raise do
+      assert_equal(idconv.to_obj(key), self)
+    end
+    GC.start
+
+    key = idconv.to_id(self)
+    assert_equal(key, self.__id__)
+    sleep(keeping)
+    GC.start
+    sleep(keeping)
+    GC.start
     assert_raise do
-      assert_equal(idconv.to_obj(false.__id__))
+      assert_equal(idconv.to_obj(key), self)
     end
   end
 end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]