ruby-changes:55656
From: Masatoshi <ko1@a...>
Date: Sat, 4 May 2019 19:29:15 +0900 (JST)
Subject: [ruby-changes:55656] Masatoshi SEKI: 8980b53a48 (trunk): add DRb::WeakIdConv (Bug #15711)
https://git.ruby-lang.org/ruby.git/commit/?id=8980b53a48 From 8980b53a48b1f55e09c5223008225e6bfa765405 Mon Sep 17 00:00:00 2001 From: Masatoshi SEKI <m_seki@m...> Date: Sat, 4 May 2019 19:28:57 +0900 Subject: add DRb::WeakIdConv (Bug #15711) diff --git a/lib/drb/weakidconv.rb b/lib/drb/weakidconv.rb new file mode 100644 index 0000000..7f973dc --- /dev/null +++ b/lib/drb/weakidconv.rb @@ -0,0 +1,59 @@ https://github.com/ruby/ruby/blob/trunk/lib/drb/weakidconv.rb#L1 +# frozen_string_literal: false +require_relative 'drb' +require 'monitor' + +module DRb + + # To use WeakIdConv: + # + # DRb.start_service(nil, nil, {:idconv => DRb::WeakIdConv.new}) + + class WeakIdConv < DRbIdConv + class WeakSet + include MonitorMixin + def initialize + super() + @immutable = {} + @map = ObjectSpace::WeakMap.new + end + + def add(obj) + synchronize do + begin + @map[obj] = self + rescue ArgumentError + @immutable[obj.__id__] = obj + end + return obj.__id__ + end + end + + def fetch(ref) + synchronize do + @immutable.fetch(ref) { + @map.each { |key, _| + return key if key.__id__ == ref + } + raise RangeError.new("invalid reference") + } + end + end + end + + def initialize() + super() + @weak_set = WeakSet.new + end + + def to_obj(ref) # :nodoc: + return super if ref.nil? + @weak_set.fetch(ref) + end + + def to_id(obj) # :nodoc: + return @weak_set.add(obj) + end + end +end + +# DRb.install_id_conv(WeakIdConv.new) diff --git a/test/drb/test_drbobject.rb b/test/drb/test_drbobject.rb index 3c7b0c1..6b88087 100644 --- a/test/drb/test_drbobject.rb +++ b/test/drb/test_drbobject.rb @@ -1,6 +1,7 @@ https://github.com/ruby/ruby/blob/trunk/test/drb/test_drbobject.rb#L1 require 'test/unit' require 'drb' require 'drb/timeridconv' +require 'drb/weakidconv' module DRbObjectTest class Foo @@ -45,3 +46,19 @@ class TestDRbObjectTimerIdConv < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/drb/test_drbobject.rb#L46 DRb.start_service(nil, nil, {:idconv => DRb::TimerIdConv.new}) end end + +class TestDRbObjectWeakIdConv < Test::Unit::TestCase + include DRbObjectTest + + def setup + DRb.start_service(nil, nil, {:idconv => DRb::WeakIdConv.new}) + end + + def test_RangeError + proxy = DRbObject.new("string".dup) + GC.start + assert_raise(RangeError) { + DRb.to_obj(proxy.__drbref) + } + end +end -- cgit v0.10.2 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/