|
49 | 49 | require 'socket'
|
50 | 50 | require 'io/wait'
|
51 | 51 | require 'monitor'
|
| 52 | +require 'weakref' |
52 | 53 | require_relative 'eq'
|
53 | 54 | require_relative 'version'
|
54 | 55 |
|
@@ -357,27 +358,87 @@ class DRbConnError < DRbError; end
|
357 | 358 | #
|
358 | 359 | # For alternative mechanisms, see DRb::TimerIdConv in drb/timeridconv.rb
|
359 | 360 | # and DRbNameIdConv in sample/name.rb in the full drb distribution.
|
| 361 | + # |
| 362 | + # JRuby Notes: |
| 363 | + # |
| 364 | + # In JRuby, id2ref is tracked manually in a weak hashing structure, |
| 365 | + # which causes it to have a large performance hit and often minor |
| 366 | + # behavioral differences from MRI. As a result, it is normally not |
| 367 | + # enabled unless ObjectSpace is enabled. |
| 368 | + # |
| 369 | + # Instead of using _id2ref directly, we implement a similar mechanism |
| 370 | + # here to localize the performance hit to only those objects being |
| 371 | + # tracked for DRb purposes. |
360 | 372 | class DRbIdConv
|
361 | 373 |
|
362 |
| - # Convert an object reference id to an object. |
363 |
| - # |
364 |
| - # This implementation looks up the reference id in the local object |
365 |
| - # space and returns the object it refers to. |
366 |
| - def to_obj(ref) |
367 |
| - ObjectSpace._id2ref(ref) |
368 |
| - end |
| 374 | + if RUBY_ENGINE == "jruby" |
369 | 375 |
|
370 |
| - # Convert an object into a reference id. |
371 |
| - # |
372 |
| - # This implementation returns the object's __id__ in the local |
373 |
| - # object space. |
374 |
| - def to_id(obj) |
375 |
| - case obj |
376 |
| - when Object |
377 |
| - obj.nil? ? nil : obj.__id__ |
378 |
| - when BasicObject |
| 376 | + def initialize |
| 377 | + @id2ref = {} |
| 378 | + end |
| 379 | + |
| 380 | + # Convert an object reference id to an object. |
| 381 | + # |
| 382 | + # This implementation looks up the reference id in the local object |
| 383 | + # space and returns the object it refers to. |
| 384 | + def to_obj(ref) |
| 385 | + _get(ref) |
| 386 | + end |
| 387 | + |
| 388 | + # Convert an object into a reference id. |
| 389 | + # |
| 390 | + # This implementation returns the object's __id__ in the local |
| 391 | + # object space. |
| 392 | + def to_id(obj) |
| 393 | + _put(obj) unless obj == nil |
| 394 | + end |
| 395 | + |
| 396 | + def _clean |
| 397 | + @id2ref.delete_if {|id,weakref| !weakref.weakref_alive?} |
| 398 | + end |
| 399 | + |
| 400 | + def _put(obj) |
| 401 | + _clean |
| 402 | + @id2ref[obj.__id__] = WeakRef.new(obj) |
379 | 403 | obj.__id__
|
380 | 404 | end
|
| 405 | + |
| 406 | + def _get(id) |
| 407 | + weakref = @id2ref[id] |
| 408 | + if weakref |
| 409 | + result = weakref.__getobj__ rescue nil |
| 410 | + if result |
| 411 | + return result |
| 412 | + else |
| 413 | + @id2ref.delete id |
| 414 | + end |
| 415 | + end |
| 416 | + nil |
| 417 | + end |
| 418 | + private :_clean, :_put, :_get |
| 419 | + |
| 420 | + else |
| 421 | + |
| 422 | + # Convert an object reference id to an object. |
| 423 | + # |
| 424 | + # This implementation looks up the reference id in the local object |
| 425 | + # space and returns the object it refers to. |
| 426 | + def to_obj(ref) |
| 427 | + ObjectSpace._id2ref(ref) |
| 428 | + end |
| 429 | + |
| 430 | + # Convert an object into a reference id. |
| 431 | + # |
| 432 | + # This implementation returns the object's __id__ in the local |
| 433 | + # object space. |
| 434 | + def to_id(obj) |
| 435 | + case obj |
| 436 | + when Object |
| 437 | + obj.nil? ? nil : obj.__id__ |
| 438 | + when BasicObject |
| 439 | + obj.__id__ |
| 440 | + end |
| 441 | + end |
381 | 442 | end
|
382 | 443 | end
|
383 | 444 |
|
|
0 commit comments