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  }