mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Update Godeps
Signed-off-by: Jana Radhakrishnan <mrjana@docker.com>
This commit is contained in:
parent
ff59f1baab
commit
c69d42d6b8
3 changed files with 182 additions and 0 deletions
5
libnetwork/Godeps/Godeps.json
generated
5
libnetwork/Godeps/Godeps.json
generated
|
@ -120,6 +120,11 @@
|
|||
"Comment": "docs-v1.12.0-rc4-2016-07-15-1316-g426a0af",
|
||||
"Rev": "426a0af0759798d8e3332b38236ee40df6d14798"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/docker/docker/pkg/locker",
|
||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-1316-g426a0af",
|
||||
"Rev": "426a0af0759798d8e3332b38236ee40df6d14798"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/docker/docker/pkg/longpath",
|
||||
"Comment": "docs-v1.12.0-rc4-2016-07-15-1316-g426a0af",
|
||||
|
|
65
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/locker/README.md
generated
vendored
Normal file
65
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/locker/README.md
generated
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
Locker
|
||||
=====
|
||||
|
||||
locker provides a mechanism for creating finer-grained locking to help
|
||||
free up more global locks to handle other tasks.
|
||||
|
||||
The implementation looks close to a sync.Mutex, however the user must provide a
|
||||
reference to use to refer to the underlying lock when locking and unlocking,
|
||||
and unlock may generate an error.
|
||||
|
||||
If a lock with a given name does not exist when `Lock` is called, one is
|
||||
created.
|
||||
Lock references are automatically cleaned up on `Unlock` if nothing else is
|
||||
waiting for the lock.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
package important
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/locker"
|
||||
)
|
||||
|
||||
type important struct {
|
||||
locks *locker.Locker
|
||||
data map[string]interface{}
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func (i *important) Get(name string) interface{} {
|
||||
i.locks.Lock(name)
|
||||
defer i.locks.Unlock(name)
|
||||
return data[name]
|
||||
}
|
||||
|
||||
func (i *important) Create(name string, data interface{}) {
|
||||
i.locks.Lock(name)
|
||||
defer i.locks.Unlock(name)
|
||||
|
||||
i.createImportant(data)
|
||||
|
||||
s.mu.Lock()
|
||||
i.data[name] = data
|
||||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
func (i *important) createImportant(data interface{}) {
|
||||
time.Sleep(10 * time.Second)
|
||||
}
|
||||
```
|
||||
|
||||
For functions dealing with a given name, always lock at the beginning of the
|
||||
function (or before doing anything with the underlying state), this ensures any
|
||||
other function that is dealing with the same name will block.
|
||||
|
||||
When needing to modify the underlying data, use the global lock to ensure nothing
|
||||
else is modfying it at the same time.
|
||||
Since name lock is already in place, no reads will occur while the modification
|
||||
is being performed.
|
||||
|
112
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/locker/locker.go
generated
vendored
Normal file
112
libnetwork/Godeps/_workspace/src/github.com/docker/docker/pkg/locker/locker.go
generated
vendored
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
Package locker provides a mechanism for creating finer-grained locking to help
|
||||
free up more global locks to handle other tasks.
|
||||
|
||||
The implementation looks close to a sync.Mutex, however the user must provide a
|
||||
reference to use to refer to the underlying lock when locking and unlocking,
|
||||
and unlock may generate an error.
|
||||
|
||||
If a lock with a given name does not exist when `Lock` is called, one is
|
||||
created.
|
||||
Lock references are automatically cleaned up on `Unlock` if nothing else is
|
||||
waiting for the lock.
|
||||
*/
|
||||
package locker
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// ErrNoSuchLock is returned when the requested lock does not exist
|
||||
var ErrNoSuchLock = errors.New("no such lock")
|
||||
|
||||
// Locker provides a locking mechanism based on the passed in reference name
|
||||
type Locker struct {
|
||||
mu sync.Mutex
|
||||
locks map[string]*lockCtr
|
||||
}
|
||||
|
||||
// lockCtr is used by Locker to represent a lock with a given name.
|
||||
type lockCtr struct {
|
||||
mu sync.Mutex
|
||||
// waiters is the number of waiters waiting to acquire the lock
|
||||
// this is int32 instead of uint32 so we can add `-1` in `dec()`
|
||||
waiters int32
|
||||
}
|
||||
|
||||
// inc increments the number of waiters waiting for the lock
|
||||
func (l *lockCtr) inc() {
|
||||
atomic.AddInt32(&l.waiters, 1)
|
||||
}
|
||||
|
||||
// dec decrements the number of waiters waiting on the lock
|
||||
func (l *lockCtr) dec() {
|
||||
atomic.AddInt32(&l.waiters, -1)
|
||||
}
|
||||
|
||||
// count gets the current number of waiters
|
||||
func (l *lockCtr) count() int32 {
|
||||
return atomic.LoadInt32(&l.waiters)
|
||||
}
|
||||
|
||||
// Lock locks the mutex
|
||||
func (l *lockCtr) Lock() {
|
||||
l.mu.Lock()
|
||||
}
|
||||
|
||||
// Unlock unlocks the mutex
|
||||
func (l *lockCtr) Unlock() {
|
||||
l.mu.Unlock()
|
||||
}
|
||||
|
||||
// New creates a new Locker
|
||||
func New() *Locker {
|
||||
return &Locker{
|
||||
locks: make(map[string]*lockCtr),
|
||||
}
|
||||
}
|
||||
|
||||
// Lock locks a mutex with the given name. If it doesn't exist, one is created
|
||||
func (l *Locker) Lock(name string) {
|
||||
l.mu.Lock()
|
||||
if l.locks == nil {
|
||||
l.locks = make(map[string]*lockCtr)
|
||||
}
|
||||
|
||||
nameLock, exists := l.locks[name]
|
||||
if !exists {
|
||||
nameLock = &lockCtr{}
|
||||
l.locks[name] = nameLock
|
||||
}
|
||||
|
||||
// increment the nameLock waiters while inside the main mutex
|
||||
// this makes sure that the lock isn't deleted if `Lock` and `Unlock` are called concurrently
|
||||
nameLock.inc()
|
||||
l.mu.Unlock()
|
||||
|
||||
// Lock the nameLock outside the main mutex so we don't block other operations
|
||||
// once locked then we can decrement the number of waiters for this lock
|
||||
nameLock.Lock()
|
||||
nameLock.dec()
|
||||
}
|
||||
|
||||
// Unlock unlocks the mutex with the given name
|
||||
// If the given lock is not being waited on by any other callers, it is deleted
|
||||
func (l *Locker) Unlock(name string) error {
|
||||
l.mu.Lock()
|
||||
nameLock, exists := l.locks[name]
|
||||
if !exists {
|
||||
l.mu.Unlock()
|
||||
return ErrNoSuchLock
|
||||
}
|
||||
|
||||
if nameLock.count() == 0 {
|
||||
delete(l.locks, name)
|
||||
}
|
||||
nameLock.Unlock()
|
||||
|
||||
l.mu.Unlock()
|
||||
return nil
|
||||
}
|
Loading…
Reference in a new issue