1
0
mirror of https://github.com/minio/mc.git synced 2025-11-13 12:22:45 +03:00
Files
mc/pkg/countlock/lock.go
2015-05-27 04:10:51 -07:00

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
}