90 lines
1.6 KiB
Go
90 lines
1.6 KiB
Go
package solver
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
|
|
"github.com/moby/buildkit/cache"
|
|
)
|
|
|
|
// SharedRef is a wrapper around releasable that allows you to make new
|
|
// releasable child objects
|
|
type SharedRef struct {
|
|
mu sync.Mutex
|
|
refs map[*sharedRefInstance]struct{}
|
|
main Ref
|
|
Ref
|
|
}
|
|
|
|
func NewSharedRef(main Ref) *SharedRef {
|
|
mr := &SharedRef{
|
|
refs: make(map[*sharedRefInstance]struct{}),
|
|
Ref: main,
|
|
}
|
|
mr.main = mr.Clone()
|
|
return mr
|
|
}
|
|
|
|
func (mr *SharedRef) Clone() Ref {
|
|
mr.mu.Lock()
|
|
r := &sharedRefInstance{SharedRef: mr}
|
|
mr.refs[r] = struct{}{}
|
|
mr.mu.Unlock()
|
|
return r
|
|
}
|
|
|
|
func (mr *SharedRef) Release(ctx context.Context) error {
|
|
return mr.main.Release(ctx)
|
|
}
|
|
|
|
func (mr *SharedRef) Sys() Ref {
|
|
sys := mr.Ref
|
|
if s, ok := sys.(interface {
|
|
Sys() Ref
|
|
}); ok {
|
|
return s.Sys()
|
|
}
|
|
return sys
|
|
}
|
|
|
|
type sharedRefInstance struct {
|
|
*SharedRef
|
|
}
|
|
|
|
func (r *sharedRefInstance) Release(ctx context.Context) error {
|
|
r.SharedRef.mu.Lock()
|
|
defer r.SharedRef.mu.Unlock()
|
|
delete(r.SharedRef.refs, r)
|
|
if len(r.SharedRef.refs) == 0 {
|
|
return r.SharedRef.Ref.Release(ctx)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func OriginRef(ref Ref) Ref {
|
|
sysRef := ref
|
|
if sys, ok := ref.(interface {
|
|
Sys() Ref
|
|
}); ok {
|
|
sysRef = sys.Sys()
|
|
}
|
|
return sysRef
|
|
}
|
|
|
|
func ToImmutableRef(ref Ref) (cache.ImmutableRef, bool) {
|
|
immutable, ok := OriginRef(ref).(cache.ImmutableRef)
|
|
if !ok {
|
|
return nil, false
|
|
}
|
|
return &immutableRef{immutable, ref.Release}, true
|
|
}
|
|
|
|
type immutableRef struct {
|
|
cache.ImmutableRef
|
|
release func(context.Context) error
|
|
}
|
|
|
|
func (ir *immutableRef) Release(ctx context.Context) error {
|
|
return ir.release(ctx)
|
|
}
|