github.com/10XDev/rclone@v1.52.3-0.20200626220027-16af9ab76b2a/backend/sftp/stringlock.go (about) 1 // +build !plan9 2 3 package sftp 4 5 import "sync" 6 7 // stringLock locks for string IDs passed in 8 type stringLock struct { 9 mu sync.Mutex // mutex to protect below 10 locks map[string]chan struct{} // map of locks 11 } 12 13 // newStringLock creates a stringLock 14 func newStringLock() *stringLock { 15 return &stringLock{ 16 locks: make(map[string]chan struct{}), 17 } 18 } 19 20 // Lock locks on the id passed in 21 func (l *stringLock) Lock(ID string) { 22 l.mu.Lock() 23 for { 24 ch, ok := l.locks[ID] 25 if !ok { 26 break 27 } 28 // Wait for the channel to be closed 29 l.mu.Unlock() 30 // fs.Logf(nil, "Waiting for stringLock on %q", ID) 31 <-ch 32 l.mu.Lock() 33 } 34 l.locks[ID] = make(chan struct{}) 35 l.mu.Unlock() 36 } 37 38 // Unlock unlocks on the id passed in. Will panic if Lock with the 39 // given id wasn't called first. 40 func (l *stringLock) Unlock(ID string) { 41 l.mu.Lock() 42 ch, ok := l.locks[ID] 43 if !ok { 44 panic("stringLock: Unlock before Lock") 45 } 46 close(ch) 47 delete(l.locks, ID) 48 l.mu.Unlock() 49 }