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 }