From: David Flanagan Date: 2009-01-01T06:19:51+09:00 Subject: [ruby-core:21026] Re: Supporting Thread.critical=with native threads 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? 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 >> > > >