github.com/la5nta/wl2k-go@v0.11.8/transport/ardop/lock.go (about)

     1  // Copyright 2015 Martin Hebnes Pedersen (LA5NTA). All rights reserved.
     2  // Use of this source code is governed by the MIT-license that can be
     3  // found in the LICENSE file.
     4  
     5  package ardop
     6  
     7  import "sync"
     8  
     9  // Lock is like a sync.Mutex, except:
    10  //   * Lock of locked is noop
    11  //   * Unlock of unlocked is noop
    12  //   * Wait() is used to block until Lock is unlocked.
    13  // The zero-value is an unlocked lock.
    14  type lock struct {
    15  	mu   sync.Mutex
    16  	wait chan struct{}
    17  }
    18  
    19  // Locks if unlocked, noop otherwise.
    20  func (l *lock) Lock() {
    21  	l.mu.Lock()
    22  	defer l.mu.Unlock()
    23  
    24  	if l.wait != nil {
    25  		return // Already locked
    26  	}
    27  
    28  	l.wait = make(chan struct{})
    29  }
    30  
    31  // Unlocks if locked, noop otherwise.
    32  func (l *lock) Unlock() {
    33  	l.mu.Lock()
    34  	defer l.mu.Unlock()
    35  
    36  	if l.wait == nil {
    37  		return // Already unlocked
    38  	}
    39  
    40  	close(l.wait)
    41  	l.wait = nil
    42  }
    43  
    44  // Blocks until lock is released. Returns immediately if it's unlocked.
    45  func (l *lock) Wait() {
    46  	<-l.WaitChan()
    47  }
    48  
    49  func (l *lock) WaitChan() <-chan struct{} {
    50  	l.mu.Lock()
    51  
    52  	wait := l.wait
    53  	if l.wait == nil {
    54  		wait = make(chan struct{})
    55  		close(wait)
    56  	}
    57  
    58  	l.mu.Unlock()
    59  	return wait
    60  }