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
-
#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.
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 |
# File 'lib/ffmprb/util/thread.rb', line 44 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 Ffmprb.logger.debug{"about to launch #{name}"} sync_q = Queue.new super() do @parent.proc_vis_node self if @parent.respond_to? :proc_vis_node if @parent.respond_to? :child_lives @parent.child_lives self 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.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 fail $! # XXX 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
#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})" logged_timeouts = timeouts end current.live! retry end end |
Instance Method Details
#child_dies(thr) ⇒ Object
94 95 96 97 98 99 100 101 |
# File 'lib/ffmprb/util/thread.rb', line 94 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
86 87 88 89 90 91 92 |
# File 'lib/ffmprb/util/thread.rb', line 86 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
103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/ffmprb/util/thread.rb', line 103 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
82 83 84 |
# File 'lib/ffmprb/util/thread.rb', line 82 def live! fail ParentError if @parent.status.nil? end |