From: Evan Phoenix Date: 2009-01-01T06:33:24+09:00 Subject: [ruby-core:21027] Re: Supporting Thread.critical=with native threads On Dec 31, 2008, at 1:19 PM, David Flanagan wrote: > Charlie, Evan, Shri: > > Just to be clear here, would you all agree that Thread.critical= is > a deprecated feature--removed in Ruby 1.9, and that your discussion > of it is limited to compatibility for Ruby 1.8 programs? None of > you are proposing to revive it as a non-deprecated feature in your > implementations, are you? Matz has pretty clearly stated that Thread.critical was an implementation specific feature of 1.8 that is deprecated/removed in 1.9. I whole heartedly agree with this, since we have sufficient replacements to use (Mutex, Sync, etc) that are easily implemented on all implementations. - Evan > > > David Flanagan > > Evan Phoenix wrote: >> On Dec 30, 2008, at 11:55 PM, Charles Oliver Nutter wrote: >>> Shri Borde wrote: >>>> Yes, Thread#kill and Thread#raise can be implemented in IronRuby >>>> by using System.Threading.Thread.Abort (http://msdn.microsoft.com/en-us/library/system.threading.thread.abort.aspx >>>> ). It is fragile (like you say, its impossible to support such >>>> operations reliably on native threads), and can be deferred >>>> indefinitely under some circumstances. So I think we ideally need >>>> to use both Thread.Abort and checkpoints. >>> >>> As under the JVM (and under any system with parallel-executing >>> threads) System.Threading.Thread.Abort is provably unsafe, so if >>> that's a concern you'll definitely need to checkpoint to support >>> Ruby's Thread#raise and Thread#kill. >>> >>>> About Thread.critical, you said: >>>>> Scripts that use critical= tend to expect that they're >>>>> guaranteeing more >>>>> than just the code in the critical section. For example, if >>>>> they're >>>>> initializing an instance variable they expect nobody else will >>>>> access it >>>>> during initialization >>>> It would seem such code will not work even with MRI. If thread 1 >>>> sets Thread.critical=true and starts initializing the instance >>>> variable, and if thread 2 is accessing the instance variable >>>> without setting Thread.critical=true, then couldn't thread 2 run >>>> into a problem even if its not scheduled, since it could be >>>> anywhere in the middle of accessing the instance variable? To be >>>> fully correct, wouldn't thread 2 have to set >>>> Thread.critical=true, even on MRI? >>> >>> Once critical=true is set in a thread, all current threads will be >>> taken out of scheduling, so in theory they would not even get the >>> opportunity to access any instance variables. >> The way that I talk about what Thread.critical does is manipulate >> the preemptive Thread scheduler. So, it inhibits Threads from >> switching "randomly" at any point. Instead, Threads can only be >> scheduled explicitly. This means via Thread methods (inspect, >> value, join, run), as well as some IO methods that explicitly >> switch Threads. >> So, to use terms that people working with green threads use: >> "Thread.critical = false" == preemptive scheduling enabled >> "Thread.critical = true" == cooperative scheduling enabled >> Obviously the idea with using cooperative scheduling is that the >> user knows what operations cause Threads to switch. Sadly in MRI, >> that knowledge completely known. >>> >>> >>> I'll grant that it's pretty fuzzy; I think people use >>> Thread.critical= in a lot of cases simply because they don't >>> really know what they're doing. If critical= could be specified as >>> simply a thread-reentrant lock against a special global mutex, it >>> would probably be reasonable. As it is, the implications are far >>> greater than simply a critical section, since it not only prevents >>> other existing threads from running that given piece of code, but >>> also from running *at all*, and code has been written, released, >>> and tested with that assumption. >>> >>>> By the way, what is the level of atomicity supported by MRI? For >>>> example, CPython uses the global interpreter lock (GIL) for each >>>> bytecode. However, since MRI does not compile to bytecode, is the >>>> AST nodes the correct level of atomicity? >>> >>> The AST node is not a fine enough measure of atomicity; for >>> example, for a += b, there's a couple levels of node granularity, >>> but obviously the outermose "op assignment" can't be atomic. And >>> when it comes down to that, a large number of nodes are dependent >>> on making method calls, which usually can't be guaranteed atomic. >>> I think it needs to be considered on a case-by-case basis. JRuby >>> guarantees instance vars can be accessed and modified >>> concurrently, for example, but makes no guarantees about @a += b >>> producing the result you expect in a multi-threaded environment. >>> >>> - Charlie >>> > >