mirror of
https://github.com/minio/mc.git
synced 2025-11-13 12:22:45 +03:00
89 lines
2.1 KiB
Go
89 lines
2.1 KiB
Go
/*
|
|
* Minio Client (C) 2015 Minio, Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
// Package countlock is useful for synchronizing multiple go routines, when
|
|
// one of them has to take a lead. Up() method increments an internal
|
|
// counter. Down() method decrements, but blocks and waits when it
|
|
// reaches zero. One can call Down() only as many times Up() is called.
|
|
package countlock
|
|
|
|
// Locker defines a counting lock
|
|
type Locker interface {
|
|
Up() // Increment the counter.
|
|
Down() // Decrement the counter. When it reaches zero, block and wait.
|
|
Close() // Release all resources and return.
|
|
}
|
|
|
|
// New returns a newly initialized counter lock object.
|
|
func New() Locker {
|
|
upCh := make(chan bool)
|
|
downCh := make(chan bool)
|
|
closeCh := make(chan bool)
|
|
|
|
go func(upCh, downCh, closeCh chan bool) {
|
|
defer close(closeCh)
|
|
defer close(downCh)
|
|
defer close(upCh)
|
|
|
|
var level int64 // Keeps track of Up and Down count.
|
|
for {
|
|
|
|
if level == 0 {
|
|
// Up() has neven been called or may
|
|
// be Down() has been called equal number
|
|
// of times.
|
|
|
|
select {
|
|
case <-upCh:
|
|
level++
|
|
case <-closeCh: // We are done.
|
|
return
|
|
}
|
|
}
|
|
|
|
// Up is called at least once. It is safe to also listen on down.
|
|
select {
|
|
case <-upCh:
|
|
level++
|
|
case <-downCh:
|
|
level--
|
|
case <-closeCh:
|
|
return
|
|
}
|
|
}
|
|
}(upCh, downCh, closeCh)
|
|
|
|
return &lock{upCh: upCh, downCh: downCh, closeCh: closeCh}
|
|
}
|
|
|
|
type lock struct {
|
|
upCh chan bool
|
|
downCh chan bool
|
|
closeCh chan bool
|
|
}
|
|
|
|
func (l lock) Up() {
|
|
l.upCh <- true
|
|
}
|
|
|
|
func (l lock) Down() {
|
|
l.downCh <- true
|
|
}
|
|
|
|
func (l lock) Close() {
|
|
l.closeCh <- true
|
|
}
|