Loading presentation...

Present Remotely

Send the link below via email or IM


Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in our knowledge base article

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.


Making autoload thread-safe

Prezi for Asakusa.rb meetup #114 at 2011-07-19

Hiroshi Nakamura

on 19 July 2011

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of Making autoload thread-safe

Making autoload thread-safe Feature loading in Ruby
Concurrency issues
How autoload works
Making autoload thread-safe 2 ways of feature loading
(find, load and exec a file) require ... loads feature w/ double loading protection

autoload ... calls 'require' at the first constant lookup for lazy feature loading Concurrency issues require

autoload Thread-safe (serialized) (OK)
circular require is warned but (OK)
deadlock by cross require (!)

Thread-unsafe (!) autoload concurrency issue safe: accessing the constant itself

unsafe: accesing inner resources autoload |module Gem
| VERSION = ''
| ...
| autoload :Version, 'rubygems/version'
| autoload :Requirement, 'rubygems/requirement'
| autoload :Dependency, 'rubygems/dependency'
| autoload :Specification, 'rubygems/specification'
| ... require 'rubygems' # it runs at startup

require 'httpclient' # user code
-> custom 'require' in rubygems/custom_require.rb
-> spec = Gem::Specification.find {...}
-> require "rubygems/specification" autoload :C, "c"
t1 = Thread.new { C }
t2 = Thread.new { C }
[t1, t2].each(&:join) autoload :D, "d"
t1 = Thread.new { D::X }
t2 = Thread.new { D.d }
[t1, t2].each(&:join) What's happened? |class Module
| def autoload(symbol, feature)
| self.autoload[symbol] = feature
| self.const[symbol] = UNDEF
| nil
| end
| def _get_constant(symbol)
| obj = self.const[symbol]
| return obj if obj != UNDEF
| require(self.autoload.delete(symbol))
| self.const[symbol]
| end
| ... What's wrong? p D::X

(const[:D] == UNDEF)

(start require "d")

module D # const[:D] = newmod

def D.d # Too late p D.d

(const[:D] != UNDEF)

(call newmod.d) Thread: t1 Thread: t2 Making autoload thread-safe Here's my try;
let Module keep 'UNDEF' in constant map until the end of autoloading
let Module keep actual object in another map (autoloading map)
add extra check for constant lookup JRuby: http://jira.codehaus.org/browse/JRUBY-3194 by @wycats 2008-11-28
CRuby: http://redmine.ruby-lang.org/issues/921 by @headius 2008-12-23 Sample implementation Summary autoload is not thread-safe ATM

Would be fixed in JRuby > Tom?

Might be fixed in CRuby? > Sasada-san?

Rubinius? > ? "Thread"
th-re'd | def _get_constant(symbol)
| if self.const[symbol] == UNDEF
| autoloading = self.autoloading[symbol]
| if autoloading.thread == Thread.current
| return autoloading.value
| end
| require(self.autoload.delete(symbol))
| ... In JRuby only

No perf drop CRuby prefer processes/MVMs rather than threads so we may remove 'autoload'?
JRuby goes with threads so autoload must be thread-safe.

Extra-checks are needed only while autoloading.
General constant lookups are not affected. We need a training Overrides UNDEF! https://github.com/jruby/jruby/tree/autoload-threadsafe How autoload works Accessing 'D' should be allowed only from the current thread NoMethodError! DEMO DEMO DEMO Hiroshi Nakamura
C/JRuby committer
This slide => http://bit.ly/autoload
Full transcript