Last active
January 20, 2018 20:14
-
-
Save ismasan/5d2b8b54167f10691de6a17f4eeb333e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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