Class: Ffmprb::Util::Thread
- Inherits:
-
Thread
- Object
- Thread
- Ffmprb::Util::Thread
- Includes:
- ProcVis::Node
- Defined in:
- lib/ffmprb/util/thread.rb
Direct Known Subclasses
Defined Under Namespace
Classes: Error, ParentError
Class Attribute Summary collapse
-
.timeout ⇒ Object
Returns the value of attribute timeout.
Instance Attribute Summary collapse
-
#backtrace ⇒ Object
readonly
Returns the value of attribute backtrace.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
Attributes included from ProcVis::Node
Class Method Summary collapse
- .join_children!(limit = nil, timeout: self.timeout) ⇒ Object
- .timeout_or_live(limit = nil, log: "while doing this", timeout: self.timeout, &blk) ⇒ Object
Instance Method Summary collapse
- #child_dies(thr) ⇒ Object
- #child_lives(thr) ⇒ Object
-
#initialize(name = "some", main: false, &blk) ⇒ Thread
constructor
A new instance of Thread.
- #join_children!(limit = nil, timeout: Thread.timeout) ⇒ Object
-
#live! ⇒ Object
TODO protected: none of these methods should be called by a user code, the only public methods are above.
Methods included from ProcVis::Node
#proc_vis_edge, #proc_vis_name, #proc_vis_node
Constructor Details
#initialize(name = "some", main: false, &blk) ⇒ Thread
Returns a new instance of Thread.
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 |
# File 'lib/ffmprb/util/thread.rb', line 45 def initialize(name="some", main: false, &blk) orig_caller = caller @name = name @parent = Thread.current @live_children = [] @children_mon = Monitor.new @dead_children_q = Queue.new @backtrace = (@parent.respond_to?(:backtrace)? @parent.backtrace : []) + caller Ffmprb.logger.debug{"about to launch #{'main ' if main}#{name}"} sync_q = Queue.new super() do self.report_on_exception = false @parent.proc_vis_node self if @parent.respond_to? :proc_vis_node if @parent.respond_to? :child_lives @parent.child_lives self Ffmprb.logger.warn "Not the main: false thread run by a #{self.class.name} thread" if main else Ffmprb.logger.warn "Not the main: true thread run by a not #{self.class.name} thread" unless main end sync_q.enq :ok Ffmprb.logger.debug{"#{name} thread launched"} begin blk.call.tap do Ffmprb.logger.debug{"#{name} thread done"} end rescue Exception Ffmprb.logger.warn "#{$!.class.name} raised in #{name} thread: #{$!.}\nBacktrace:\n\t#{($!.backtrace + backtrace ).join("\n\t")}" cause = $! Ffmprb.logger.warn "...caused by #{cause.class.name}: #{cause.}\nBacktrace:\n\t#{cause.backtrace.join("\n\t")}" while cause = cause.cause raise $! # TODO? I have no idea why I need to give it `$!` -- the docs say I need not ensure @parent.child_dies self if @parent.respond_to? :child_dies @parent.proc_vis_node self, :remove if @parent.respond_to? :proc_vis_node end end sync_q.deq end |
Class Attribute Details
.timeout ⇒ Object
Returns the value of attribute timeout.
13 14 15 |
# File 'lib/ffmprb/util/thread.rb', line 13 def timeout @timeout end |
Instance Attribute Details
#backtrace ⇒ Object (readonly)
Returns the value of attribute backtrace.
43 44 45 |
# File 'lib/ffmprb/util/thread.rb', line 43 def backtrace @backtrace end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
42 43 44 |
# File 'lib/ffmprb/util/thread.rb', line 42 def name @name end |
Class Method Details
.join_children!(limit = nil, timeout: self.timeout) ⇒ Object
36 37 38 |
# File 'lib/ffmprb/util/thread.rb', line 36 def join_children!(limit=nil, timeout: self.timeout) Thread.current.join_children! limit, timeout: timeout end |
.timeout_or_live(limit = nil, log: "while doing this", timeout: self.timeout, &blk) ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/ffmprb/util/thread.rb', line 15 def timeout_or_live(limit=nil, log: "while doing this", timeout: self.timeout, &blk) started_at = Time.now timeouts = 0 logged_timeouts = 1 begin timeouts += 1 time = Time.now - started_at fail TimeLimitError if limit && time > limit Timeout.timeout timeout do blk.call time end rescue Timeout::Error if timeouts > 2 * logged_timeouts Ffmprb.logger.info "A little bit of timeout #{log.respond_to?(:call)? log.call : log} (##{timeouts}x#{timeout})" logged_timeouts = timeouts end current.live! retry end end |
Instance Method Details
#child_dies(thr) ⇒ Object
99 100 101 102 103 104 105 106 107 |
# File 'lib/ffmprb/util/thread.rb', line 99 def child_dies(thr) @children_mon.synchronize do Ffmprb.logger.debug{"releasing #{thr.name} thread"} @dead_children_q.enq thr fail "System Error" unless @live_children.delete thr end proc_vis_edge self, thr, :remove end |
#child_lives(thr) ⇒ Object
91 92 93 94 95 96 97 |
# File 'lib/ffmprb/util/thread.rb', line 91 def child_lives(thr) @children_mon.synchronize do Ffmprb.logger.debug{"picking up #{thr.name} thread"} @live_children << thr end proc_vis_edge self, thr end |
#join_children!(limit = nil, timeout: Thread.timeout) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/ffmprb/util/thread.rb', line 109 def join_children!(limit=nil, timeout: Thread.timeout) timeout = [timeout, limit].compact.min Ffmprb.logger.debug "joining threads: #{@live_children.size} live, #{@dead_children_q.size} dead" until @live_children.empty? && @dead_children_q.empty? thr = self.class.timeout_or_live limit, log: "joining threads: #{@live_children.size} live, #{@dead_children_q.size} dead", timeout: timeout do @dead_children_q.deq end Ffmprb.logger.debug "joining the late #{thr.name} thread" fail "System Error" unless thr.join(timeout) # NOTE should not block end end |
#live! ⇒ Object
TODO protected: none of these methods should be called by a user code, the only public methods are above
87 88 89 |
# File 'lib/ffmprb/util/thread.rb', line 87 def live! fail ParentError if @parent.status.nil? end |