Skip to content

Instantly share code, notes, and snippets.

@Sija
Last active May 24, 2023 16:42
Show Gist options
  • Save Sija/b439bb1e590b355ee30f7deb18467439 to your computer and use it in GitHub Desktop.
Save Sija/b439bb1e590b355ee30f7deb18467439 to your computer and use it in GitHub Desktop.
struct Synchronized(T)
protected getter __wrapped__ : T
def initialize(wrapped : T = T.new, protection : Mutex::Protection = :reentrant) forall T
@__wrapped__ = wrapped
@__lock__ = Mutex.new(protection)
end
macro method_missing(call)
@__lock__.synchronize do
@__wrapped__.{{ call }}
end
end
macro synchronized_delegate(*methods, to object, with lock)
{% for method in methods.map(&.id) %}
{% if method.ends_with?('=') || method.ends_with?('~') %}
def {{ method }}(arg)
{{ lock.id }}.synchronize do
{{ object.id }}.{{ method }}(arg)
end
end
{% else %}
def {{ method }}(*args, **options)
{{ lock.id }}.synchronize do
{{ object.id }}.{{ method }}(*args, **options)
end
end
def {{ method }}(*args, **options, &)
{{ lock.id }}.synchronize do
{{ object.id }}.{{ method }}(*args, **options) do |*yield_args|
yield *yield_args
end
end
end
{% end %}
{% end %}
end
synchronized_delegate :try, :not_nil!, :to_s, :hash, :==, :===, :=~,
to: @__wrapped__, with: @__lock__
end
class Object
def synchronized(protection : Mutex::Protection = :reentrant)
case self
when Value
self
when Synchronized
Synchronized.new(self.__wrapped__, protection)
else
Synchronized.new(self, protection)
end
end
def unsynchronized
case self
when Synchronized
self.__wrapped__
else
self
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment