Metered concurrency: Difference between revisions
Content added Content deleted
(→Buffered channel: clarity) |
(→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 { |
||
int |
|||
sync.Cond |
|||
} |
} |
||
func newCount(n int) *countSem { |
func newCount(n int) *countSem { |
||
return &countSem{ |
return &countSem{n, sync.Cond{L: &sync.Mutex{}}} |
||
} |
} |
||
func (cs *countSem) count() int { |
func (cs *countSem) count() int { |
||
⚫ | |||
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 { |
|||
cs.int-- |
|||
for cs.int < 0 { |
|||
cs.Wait() |
|||
atomic.AddInt32(&cs.c, 1) |
|||
cs.cond.Wait() |
|||
} |
|||
⚫ | |||
} |
} |
||
cs.L.Unlock() |
|||
} |
} |
||
func (cs *countSem) release() { |
func (cs *countSem) release() { |
||
cs.L.Lock() |
|||
cs. |
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. |