mirror of https://github.com/harness/drone.git
76 lines
1.2 KiB
Go
76 lines
1.2 KiB
Go
package lock
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"sync"
|
|
)
|
|
|
|
// Mutex is basic locker implementation
|
|
// do not use it in prod and distributed environment.
|
|
type Mutex struct {
|
|
mux sync.RWMutex
|
|
locks map[string]*Lock
|
|
}
|
|
|
|
func (c *Mutex) AcquireLock(ctx context.Context, key string) (*Lock, error) {
|
|
if c == nil {
|
|
return nil, errors.New("mutex not initialized")
|
|
}
|
|
|
|
if c.locks == nil {
|
|
c.locks = make(map[string]*Lock)
|
|
}
|
|
|
|
c.mux.RLock()
|
|
defer c.mux.RUnlock()
|
|
|
|
lock, ok := c.locks[key]
|
|
if !ok {
|
|
lock = &Lock{
|
|
state: false,
|
|
key: key,
|
|
lockChan: make(chan struct{}, 1),
|
|
}
|
|
}
|
|
select {
|
|
case lock.lockChan <- struct{}{}:
|
|
lock.state = true
|
|
c.locks[key] = lock
|
|
return lock, nil
|
|
case <-ctx.Done():
|
|
return nil, errors.New("deadline exceeded, lock not created")
|
|
}
|
|
}
|
|
|
|
// Lock represents an obtained, app wide lock.
|
|
type Lock struct {
|
|
state bool
|
|
key string
|
|
lockChan chan struct{}
|
|
}
|
|
|
|
// Key returns the redis key used by the lock.
|
|
func (l *Lock) Key() string {
|
|
if l == nil {
|
|
return ""
|
|
}
|
|
return l.key
|
|
}
|
|
|
|
// Locked returns if this key is locked.
|
|
func (l *Lock) Locked() bool {
|
|
if l == nil {
|
|
return false
|
|
}
|
|
return l.state
|
|
}
|
|
|
|
// Release manually releases the lock.
|
|
func (l *Lock) Release() {
|
|
if l == nil {
|
|
return
|
|
}
|
|
<-l.lockChan
|
|
}
|