package main import ( "log" "sync" "time" ) type SuperLock struct { self *sync.Mutex lock *sync.RWMutex sem chan struct{} } func NewSuperLock() *SuperLock { return &SuperLock{ sem: make(chan struct{}, 100), self: &sync.Mutex{}, lock: &sync.RWMutex{}, } } func (sl *SuperLock) RLock() { log.Println("sl.rlock...") sl.lock.RLock() } func (sl *SuperLock) RUnlock() { log.Println("sl.runlock") sl.lock.RUnlock() } func (sl *SuperLock) Lock() { log.Println("sl.lock...") sl.lock.Lock() } func (sl *SuperLock) Unlock() { log.Println("sl.unlock") sl.lock.Unlock() } func (sl *SuperLock) StartStream() { log.Println("sl.startstream") sl.self.Lock() defer sl.self.Unlock() select { case sl.sem <- struct{}{}: case <-time.After(time.Second * 3): log.Println("timed out getting semaphore to start stream") return } log.Println("CONT STREAM", len(sl.sem)) startStream() } func (sl *SuperLock) StopStream() { log.Println("sl.stopstream") sl.self.Lock() defer sl.self.Unlock() select { case <-sl.sem: case <-time.After(time.Second * 3): log.Println("timed out getting semaphore to stop stream") return } log.Println("STOP STREAM", len(sl.sem)) if len(sl.sem) > 0 { return } log.Println("REALLY DO STOP STREAM", len(sl.sem)) stopStream() }