Robert Klemme wrote:
> 2008/12/21 Charles Oliver Nutter <charles.nutter / sun.com>:
>> Gary Wright wrote:
>>> I admit to not thinking about this too much but shouldn't there be a
>>> global lock on things like require and load?  If it isn't enforced by Ruby
>>> itself, I would think that a properly designed multi-threaded application
>>> shouldn't have multiple threads contending for access to global state
>>> without proper locking.
>> It certainly could, but that is a behavioral change; there's no way to
>> require files in separate threads at the same time. Of course, maybe it's a
>> bad idea to allow that in the first place.
> 
> I don't think there should be locking involved for "load" as that
> loads a file unconditionally. When using "load" one must be aware of
> the fact that the file can be loaded multiple times - including
> concurrently.

I tend to agree. Load explicitly bypasses things like $" population so 
you can load the same file repeatedly if you want to. So I think load 
should be the lock-free low-level "always execute target file" version. 
And in truth, require is largely implemented in terms of load.

> For "require" the story looks a bit different.  If I am not mistaken
> you would need a reentrant lock per (case insensitive? - probably
> depending on file system) string after "require" as the smallest
> granularity.  Hm...  The longer I think about it the more I believe
> that a single reentrant lock for "require" is probably the most robust
> solution...

I think it has to be a single lock or nothing, due to the deadlock 
possibilities of a lock-per-resources.

So I'll summarize my position here:

- requires cannot safely be done concurrently because they will cause 
resources (classes, modules) to be accessed before they are completely 
loaded and initialized.
- The simplest solution for this is to not require resources 
concurrently, which is certainly a valid solution which requires no 
locks and no behavioral changes.
- A lock per resources or per name is broken, due to deadlock potential, 
and so is not the right solution
- A single global lock would fix require concurrency (and almost be 
enough to fix autoload concurrency) but would introduce the behavioral 
change that only one require can execute at a time.
- I'm not strongly leaning toward either "no fix" or a global require 
lock. It doesn't bother me terrible that require isn't thread-safe, 
since the simple fix of "don't do that" solve the problem without 
complication.

> While we're at it: what happens to "require" in light of changes to $:
> and current directory?

I don't think it would make any difference; both just change how it 
searches for files, and should not affect concurrency characteristics.

- Charlie