""" Lockable(value, lock = ReentrantLock()) Creates a `Lockable` object that wraps `value` and associates it with the provided `lock`. """ struct Lockable{T, L <: Base.AbstractLock} value::T lock::L end Lockable(value) = Lockable(value, ReentrantLock()) Base.getindex(l::Lockable) = l.value """ lock(f::Function, l::Lockable) Acquire the lock associated with `l`, execute `f` with the lock held, and release the lock when `f` returns. `f` will receive one positional argument: the value wrapped by `l`. If the lock is already locked by a different task/thread, wait for it to become available. When this function returns, the `lock` has been released, so the caller should not attempt to `unlock` it. """ function Base.lock(f, l::Lockable) lock(l.lock) do f(l.value) end end # implement the rest of the Lock interface on Lockable Base.islocked(l::Lockable) = islocked(l.lock) Base.lock(l::Lockable) = lock(l.lock) Base.trylock(l::Lockable) = trylock(l.lock) Base.unlock(l::Lockable) = unlock(l.lock)