Feature #5788
closedThread#at_exit
Description
=begin
I propose a new method Thread#at_exit.
It is to register a block which will be called when the thread ends.
p Thread.main #=> #<Thread:0x007f828fa97fe0 run>
p t = Thread.new{ # do something } #=> #<Thread:0x007f828fc9e500 run>
t.at_exit{ p Thread.current }
t.join #=> #<Thread:0x007f828fc9e500 run>
Thread.main.at_exit is equal to Kernel.at_exit.
I think this method is useful for waiting plural running threads end.
Without Thread#at_exit:
t1 = Thread.new{ sleep 1 }
t2 = Thread.new{ sleep 2 }
[t1, t2].each do |t|
Thread.new do
t.join
puts "Thread ended!"
end
end
[t1, t2].each(&:join)
To handle threads' end immediately, the same number of threads as ones to wait is needed.
For example, Ruby's standard library thwait.rb does so.
With Thread#at_exit:
t1 = Thread.new{ sleep 1 }
t2 = Thread.new{ sleep 2 }
[t1, t2].each do |t|
It runs when interpreter ends.¶
t.at_exit{ puts "Thread ended!" }
end
New threads are not necessary.
I made a patch.
Patched ruby passes test-all.
=end
Files
Updated by nobu (Nobuyoshi Nakada) over 12 years ago
- Status changed from Open to Feedback
=begin
Just reviewed briefly.
- (({th->at_exit})) needs to be marked,
- (({th->at_exit})) should be hidden, and
- a hook registered to the main thread seems to be executed in a child
process forked in a sub-thread too.
Second, what will happen if the thread has terminated already? Also,
it might be useful if the thread or its value is passed to the hook.
=end
Updated by sorah (Sorah Fukumori) over 12 years ago
i don't think the name of this method is good… are there any more suitable name for this method?
Updated by kosaki (Motohiro KOSAKI) over 12 years ago
I don't think ruby impl w/o GVL can implement this feature.
Updated by Glass_saga (Masaki Matsushita) over 12 years ago
- File patch2.diff patch2.diff added
=begin
Nakada-san, thank you for your reviewing.
I improved the patch at some points.
- th->at_exit is to be marked.
- If the thread is dead, Thread#at_exit returns nil.
- The thread is passed to the hooks(including hooks on main thread).
- Registered hooks are executed in reverse order of registration(same as END or Kernel.at_exit).
=end
Updated by nobu (Nobuyoshi Nakada) over 12 years ago
=begin
Calling (({rb_gc_mark()})) only once at the hook definition makes no sense.
You have to mark it in (({rb_thread_mark()})).
=end
Updated by normalperson (Eric Wong) over 12 years ago
Motohiro KOSAKI kosaki.motohiro@gmail.com wrote:
I don't think ruby impl w/o GVL can implement this feature.
pthread_key_create() can be used to register a destructor function.
I don't know about other thread APIs, though.
Updated by kosaki (Motohiro KOSAKI) over 12 years ago
2011/12/27 Eric Wong normalperson@yhbt.net:
Motohiro KOSAKI kosaki.motohiro@gmail.com wrote:
I don't think ruby impl w/o GVL can implement this feature.
pthread_key_create() can be used to register a destructor function.
I don't know about other thread APIs, though.
No.
The proposal API can replace with another thread's exiting hook. It's
racy be definition.
pthread_key_create() can't help.
Moreover, the proposal syntax may accelerate careless racy code.
That's bad. We sould
only encourage good custom.
Updated by Glass_saga (Masaki Matsushita) about 12 years ago
- File patch3.diff patch3.diff added
=begin
I modified the patch.
- use mutex on define_at_exit to avoid race.
- mark th->at_exit and th->at_exit_lock in rb_thread_mark().
=end
Updated by mame (Yusuke Endoh) over 11 years ago
- Target version set to 2.6
Updated by Glass_saga (Masaki Matsushita) almost 6 years ago
- Status changed from Feedback to Closed
Updated by Glass_saga (Masaki Matsushita) almost 6 years ago
- Status changed from Closed to Rejected