mirror of
https://github.com/rclone/rclone.git
synced 2024-12-04 14:26:42 +01:00
60 lines
1.4 KiB
Go
60 lines
1.4 KiB
Go
|
// Copyright (C) 2020 Storj Labs, Inc.
|
||
|
// See LICENSE for copying information
|
||
|
|
||
|
package sync2
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"sync"
|
||
|
)
|
||
|
|
||
|
// ParentLimiter limits the concurrent goroutines that children run.
|
||
|
// See Child method.
|
||
|
type ParentLimiter struct {
|
||
|
limiter *Limiter
|
||
|
}
|
||
|
|
||
|
// NewParentLimiter creates a new ParentLimiter with limit set to n.
|
||
|
func NewParentLimiter(n int) *ParentLimiter {
|
||
|
return &ParentLimiter{
|
||
|
limiter: NewLimiter(n),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Child create a new parent's child.
|
||
|
func (parent *ParentLimiter) Child() *ChildLimiter {
|
||
|
return &ChildLimiter{
|
||
|
parentLimiter: parent.limiter,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Wait waits for all the children's running goroutines to finish.
|
||
|
func (parent *ParentLimiter) Wait() {
|
||
|
parent.limiter.Wait()
|
||
|
}
|
||
|
|
||
|
// ChildLimiter limits concurrent goroutines by its parent limit
|
||
|
// (ParentLimiter).
|
||
|
type ChildLimiter struct {
|
||
|
parentLimiter *Limiter
|
||
|
working sync.WaitGroup
|
||
|
}
|
||
|
|
||
|
// Go tries to start fn as a goroutine.
|
||
|
// When the parent limit is reached it will wait until it can run it or the
|
||
|
// context is canceled.
|
||
|
// Cancel the context only interrupt the child goroutines waiting to run.
|
||
|
func (child *ChildLimiter) Go(ctx context.Context, fn func()) bool {
|
||
|
child.working.Add(1)
|
||
|
|
||
|
return child.parentLimiter.Go(ctx, func() {
|
||
|
defer child.working.Done()
|
||
|
fn()
|
||
|
})
|
||
|
}
|
||
|
|
||
|
// Wait waits for all the child's running goroutines to finish.
|
||
|
func (child *ChildLimiter) Wait() {
|
||
|
child.working.Wait()
|
||
|
}
|