Metered concurrency: Difference between revisions

Content added Content deleted
(→‎Sync.Cond: simplify, meet documented requirements of sync.Cond)
Line 668: Line 668:
"os"
"os"
"sync"
"sync"
"sync/atomic"
"time"
"time"
)
)
Line 675: Line 674:


type countSem struct {
type countSem struct {
c int32
int
cond *sync.Cond
sync.Cond
}
}


func newCount(n int) *countSem {
func newCount(n int) *countSem {
return &countSem{int32(n), sync.NewCond(new(sync.Mutex))}
return &countSem{n, sync.Cond{L: &sync.Mutex{}}}
}
}


func (cs *countSem) count() int {
func (cs *countSem) count() int {
cs.L.Lock()
return int(atomic.LoadInt32(&cs.c))
c := cs.int
cs.L.Unlock()
return c
}
}


func (cs *countSem) acquire() {
func (cs *countSem) acquire() {
cs.L.Lock()
if atomic.AddInt32(&cs.c, -1) < 0 {
atomic.AddInt32(&cs.c, 1)
cs.int--
cs.cond.L.Lock()
for cs.int < 0 {
for atomic.AddInt32(&cs.c, -1) < 0 {
cs.Wait()
atomic.AddInt32(&cs.c, 1)
cs.cond.Wait()
}
cs.cond.L.Unlock()
}
}
cs.L.Unlock()
}
}


func (cs *countSem) release() {
func (cs *countSem) release() {
atomic.AddInt32(&cs.c, 1)
cs.L.Lock()
cs.cond.Signal()
cs.int++
cs.L.Unlock()
cs.Broadcast()
}
}


Line 722: Line 723:
studied.Done()
studied.Done()
}</lang>
}</lang>

===Monitor===
===Monitor===
Monitor-style solution implements counting semaphore as a monitor goroutine encapsulating the count. It implements semaphore operations with separate Go channels.
Monitor-style solution implements counting semaphore as a monitor goroutine encapsulating the count. It implements semaphore operations with separate Go channels.