| 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/moby/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 i.data[name] | |
| } | |
| func (i *important) Create(name string, data interface{}) { | |
| i.locks.Lock(name) | |
| defer i.locks.Unlock(name) | |
| i.createImportant(data) | |
| i.mu.Lock() | |
| i.data[name] = data | |
| i.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 modifying it at the same time. | |
| Since name lock is already in place, no reads will occur while the modification | |
| is being performed. | |