https://redmine.ruby-lang.org/https://redmine.ruby-lang.org/favicon.ico?17113305112019-03-13T21:49:16ZRuby Issue Tracking SystemRuby master - Feature #15663: Documenting autoload semanticshttps://redmine.ruby-lang.org/issues/15663?journal_id=770922019-03-13T21:49:16Zshevegen (Robert A. Heiler)shevegen@gmail.com
<ul></ul><p>May explain why matz wants to remove autoload in the long run. :)</p> Ruby master - Feature #15663: Documenting autoload semanticshttps://redmine.ruby-lang.org/issues/15663?journal_id=772142019-03-20T02:48:49Zakr (Akira Tanaka)akr@fsij.org
<ul></ul><p>Eregon (Benoit Daloze) wrote:</p>
<blockquote>
<p>I would have thought <code>require autoload_path</code> would basically do the same as triggering the autoload of the constant (such as <code>Foo</code>). But the results above show they differ.</p>
</blockquote>
<p>Agreed.</p>
<p>I think no one seriously considered about requiring a library used for autoload.</p>
<blockquote>
<p>Who is knowledgeable about <code>autoload</code> and could answer these questions?<br>
Could we start a document specifying the semantics?</p>
</blockquote>
<p>I think we should start to make autoload semantics simpler by introducing "global autoload lock"<br>
as I described in <a href="https://bugs.ruby-lang.org/issues/15598" class="external">https://bugs.ruby-lang.org/issues/15598</a> .<br>
This is needed because ruby doesn't (cannot) know dependencies of autoloaded libraries before loading.<br>
It makes autoload related procedure single threaded which is much simpler than multi threads.</p> Ruby master - Feature #15663: Documenting autoload semanticshttps://redmine.ruby-lang.org/issues/15663?journal_id=772152019-03-20T03:33:25Zakr (Akira Tanaka)akr@fsij.org
<ul></ul><p>akr (Akira Tanaka) wrote:</p>
<blockquote>
<blockquote>
<p>Could we start a document specifying the semantics?</p>
</blockquote>
<p>I think we should start to make autoload semantics simpler by introducing "global autoload lock"<br>
as I described in <a href="https://bugs.ruby-lang.org/issues/15598" class="external">https://bugs.ruby-lang.org/issues/15598</a> .</p>
</blockquote>
<p>Of course, there is no problem to describe the single thread semantics.</p> Ruby master - Feature #15663: Documenting autoload semanticshttps://redmine.ruby-lang.org/issues/15663?journal_id=772222019-03-20T11:03:01ZEregon (Benoit Daloze)
<ul></ul><p>akr (Akira Tanaka) wrote:</p>
<blockquote>
<p>Eregon (Benoit Daloze) wrote:</p>
<blockquote>
<p>I would have thought <code>require autoload_path</code> would basically do the same as triggering the autoload of the constant (such as <code>Foo</code>). But the results above show they differ.</p>
</blockquote>
<p>Agreed.</p>
</blockquote>
<p>It seems tricky implementation-wise, constant resolution (e.g. #const_get) has the constant data structure, and #require has the expanded file path + related lock but none of them has both.</p>
<p>I was thinking maybe the require lock per path should be used for everything, but then since #autoload calls <code>require</code> dynamically, how to keep track which thread is loading the constant and so should observe the autoload constant as "not defined" while loading it, without deadlocks?<br>
Other threads might try to load the constant too, or require the autoload path, and only one thread should be the loading thread for that constant.</p>
<p>I'd be tempted for constant resolution to basically do nothing more than call <code>require</code>, but then we need <code>Kernel#require</code> when it starts loading the file to also mark the autoload constant as being loaded by the current thread (such that the constant looks as "not defined").<br>
How to pass that information (e.g., the constant data structure) from constant resolution down to Kernel#require?<br>
The require <code>feature</code> could be changed by user-defined <code>require</code>. And a user-defined <code>require</code> might very well <code>require</code> other files for its own logic (e.g., rubygems files).</p>
<blockquote>
<p>I think no one seriously considered about requiring a library used for autoload.</p>
</blockquote>
<p><code>lib/net/http.rb</code> has <code>autoload :OpenSSL, 'openssl'</code> and therefore just <code>require "net/http"; require "openssl"</code> produces such a case.</p>
<blockquote>
<p>I think we should start to make autoload semantics simpler by introducing "global autoload lock"<br>
as I described in <a href="https://bugs.ruby-lang.org/issues/15598" class="external">https://bugs.ruby-lang.org/issues/15598</a> .<br>
This is needed because ruby doesn't (cannot) know dependencies of autoloaded libraries before loading.<br>
It makes autoload related procedure single threaded which is much simpler than multi threads.</p>
</blockquote>
<p>That would simplify things, but then I think it would also need to be a global require lock, and I think that can be problematic for compatibility:<br>
e.g., what if a required file starts a server and so the <code>require</code> never ends, and later on another thread wants to <code>require</code> some code?</p> Ruby master - Feature #15663: Documenting autoload semanticshttps://redmine.ruby-lang.org/issues/15663?journal_id=772262019-03-20T13:30:59Zakr (Akira Tanaka)akr@fsij.org
<ul></ul><p>Eregon (Benoit Daloze) wrote:</p>
<blockquote>
<p>I was thinking maybe the require lock per path should be used for everything, but then since #autoload calls <code>require</code> dynamically, how to keep track which thread is loading the constant and so should observe the autoload constant as "not defined" while loading it, without deadlocks?<br>
Other threads might try to load the constant too, or require the autoload path, and only one thread should be the loading thread for that constant.</p>
</blockquote>
<p>I think "lock per path" can cause deadlock with "mutual require" similar to<br>
<a href="https://bugs.ruby-lang.org/issues/15598" class="external">https://bugs.ruby-lang.org/issues/15598</a> .</p>
<blockquote>
<p>That would simplify things, but then I think it would also need to be a global require lock, and I think that can be problematic for compatibility:<br>
e.g., what if a required file starts a server and so the <code>require</code> never ends, and later on another thread wants to <code>require</code> some code?</p>
</blockquote>
<p>Why "it would also need to be a global require lock"?</p> Ruby master - Feature #15663: Documenting autoload semanticshttps://redmine.ruby-lang.org/issues/15663?journal_id=776802019-04-20T01:44:02Zfxn (Xavier Noria)fxn@hashref.com
<ul></ul><p>Let me share some thoughts that won't help much, but would like to contribute anyway :).</p>
<p>To me it is a surprise that constants for which there is an autoload are treated as existing by the constants API. My basic observation is that you don't know if the constant will actually be there until you execute the require. Since the require could fail, from non-existing files, to syntax errors, to files not actually defining the constants. The constant may never materialize.</p>
<p>For me the semantics would be easier if autoloads were treated separately. For example, if <code>const_defined?</code> or <code>defined?</code> returned <code>false</code> for autoloads, <code>constants</code> would not include them, etc. You have <em>actually existing constants</em>, and autoloads, you have <code>autoload?</code> for autoloads if you need to introspect them. You would need <code>remove_autoload</code> perhaps... you see the mental model: two separate collections.</p>
<p>Of course, nothing of this is backwards compatible, so of no practical value for this thread surely.</p>