Skip to content

Instantly share code, notes, and snippets.

@ismasan
Last active January 20, 2018 20:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ismasan/5d2b8b54167f10691de6a17f4eeb333e to your computer and use it in GitHub Desktop.
Save ismasan/5d2b8b54167f10691de6a17f4eeb333e to your computer and use it in GitHub Desktop.
# Simple thread-safe IoC container
# Example
#
# DEPS = Container.new
# # db singleton is lazily initialized if needed
# DEPS.register(:db) do
# require 'sequel'
# Sequel.connect ENV.fetch('DATABASE_URL')
# end
# database-backed repo depends on :db
# DEPS.register(:db_repo) do
# DBRepo.new(DEPS.get(:db))
# end
# in-memory repo does not depend on :db
# DEPS.register(:mem_repo) do
# MemRepo.new
# end
# # abstract repo will initialize either :db_repo or :mem_repo
# # depending on configuration
# DEPS.register(:repo) do
# DEPS.get(ENV.fetch(:repo_type, :mem_repo).to_sym)
# end
#
# # App will :get what it needs from DEPS
# # only used dependencies will be initialized
# app = SomeApp.new(repo: DEPS.get(:repo))
class Container
def initialize
@definitions = {}
@cache = {}
@mutex = Mutex.new
@locked = false
end
def register(name, &block)
@definitions[name] = block
end
def get(name)
with_lock do
if v = @cache[name]
return v
else
d = @definitions[name]
return nil unless d
@cache[name] = d.call
end
end
end
private
def with_lock(&block)
if @locked
yield
else
@mutex.synchronize {
@locked = true
result = yield
@locked = false
result
}
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment