Class: Thread
- Inherits:
-
Object
- Object
- Thread
- Defined in:
- lib/rubinius/kernel/common/thread.rb
Overview
– Be very careful about calling raise in here! Thread has its own raise which, if you’re calling raise, you probably don’t want. Use Kernel.raise to call the proper raise. ++
Defined Under Namespace
Classes: InnerRecursionDetected
Instance Attribute Summary collapse
-
#recursive_objects ⇒ Object
readonly
Returns the value of attribute recursive_objects.
Class Method Summary collapse
- .detect_outermost_recursion(obj, paired_obj = undefined, &block) ⇒ Object
-
.detect_recursion(obj, paired_obj = undefined) ⇒ Object
detect_recursion will return if there’s a recursion on obj (or the pair obj+paired_obj).
- .guarding?(obj) ⇒ Boolean
-
.recursion_guard(obj) ⇒ Object
Implementation note: ideally, the recursive_objects lookup table would be different per method call.
Instance Attribute Details
#recursive_objects ⇒ Object (readonly)
Returns the value of attribute recursive_objects.
9 10 11 |
# File 'lib/rubinius/kernel/common/thread.rb', line 9 def recursive_objects @recursive_objects end |
Class Method Details
.detect_outermost_recursion(obj, paired_obj = undefined, &block) ⇒ Object
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/rubinius/kernel/common/thread.rb', line 93 def self.detect_outermost_recursion(obj, paired_obj=undefined, &block) rec = current.recursive_objects if rec[:__detect_outermost_recursion__] if detect_recursion(obj, paired_obj, &block) raise InnerRecursionDetected.new end false else begin rec[:__detect_outermost_recursion__] = true begin detect_recursion(obj, paired_obj, &block) rescue InnerRecursionDetected return true end return nil ensure rec.delete :__detect_outermost_recursion__ end end end |
.detect_recursion(obj, paired_obj = undefined) ⇒ Object
detect_recursion will return if there’s a recursion on obj (or the pair obj+paired_obj). If there is one, it returns true. Otherwise, it will yield once and return false.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/rubinius/kernel/common/thread.rb', line 39 def self.detect_recursion(obj, paired_obj=undefined) id = obj.object_id pair_id = paired_obj.object_id objects = current.recursive_objects case objects[id] # Default case, we haven't seen +obj+ yet, so we add it and run the block. when nil objects[id] = pair_id begin yield ensure objects.delete id end # We've seen +obj+ before and it's got multiple paired objects associated # with it, so check the pair and yield if there is no recursion. when Rubinius::LookupTable return true if objects[id][pair_id] objects[id][pair_id] = true begin yield ensure objects[id].delete pair_id end # We've seen +obj+ with one paired object, so check the stored one for # recursion. # # This promotes the value to a LookupTable since there is another new paired # object. else previous = objects[id] return true if previous == pair_id objects[id] = Rubinius::LookupTable.new(previous => true, pair_id => true) begin yield ensure objects[id] = previous end end false end |
.guarding?(obj) ⇒ Boolean
30 31 32 |
# File 'lib/rubinius/kernel/common/thread.rb', line 30 def self.guarding?(obj) current.recursive_objects[obj.object_id] end |
.recursion_guard(obj) ⇒ Object
Implementation note: ideally, the recursive_objects lookup table would be different per method call. Currently it doesn’t cause problems, but if ever a method :foo calls a method :bar which could recurse back to :foo, it could require making the tables independant.
18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/rubinius/kernel/common/thread.rb', line 18 def self.recursion_guard(obj) id = obj.object_id objects = current.recursive_objects objects[id] = true begin yield ensure objects.delete id end end |