######################################################################
# Lockables are simple wrappers around arbitrary data combined with
# a lock/condition/`lock`able. The Lockable itself forwards Base
# sync functions.
# -----
# Licensed under Apache License 2.0
module Lockables
using Base.Threads

export Lockable
mutable struct Lockable{T}
    data::T
    lock
end
Lockable(init::T) where T = Lockable(init, Threads.ReentrantLock())

Base.lock(lockable::Lockable, args...; kwargs...) = lock(lockable.lock, args...; kwargs...)
Base.lock(cb, lockable::Lockable, args...; kwargs...) = lock(cb, lockable.lock, args...; kwargs...)
Base.unlock(lockable::Lockable, args...; kwargs...) = unlock(lockable.lock, args...; kwargs...)
Base.islocked(lockable::Lockable, args...; kwargs...) = islocked(lockable.lock, args...; kwargs...)

Base.notify(lockable::Lockable, args...; kwargs...) = notify(lockable.lock, args...; kwargs...)
Base.wait(lockable::Lockable, args...; kwargs...) = wait(lockable.lock, args...; kwargs...)

Base.getindex(lockable::Lockable) = lockable.data
Base.setindex!(lockable::Lockable{T1}, value::T2) where {T1, T2<:T1} = lockable.data = value
end
