Metered concurrency: Difference between revisions

Content deleted Content added
Sonia (talk | contribs)
→‎Sync.Cond: simplify, meet documented requirements of sync.Cond
Sonia (talk | contribs)
→‎{{header|Go}}: Remove poor example. The other two are good. This one was a stretch.
Line 722: Line 722:
studyRoom.release()
studyRoom.release()
studied.Done()
studied.Done()
}</lang>

===Monitor===
Monitor-style solution implements counting semaphore as a monitor goroutine encapsulating the count. It implements semaphore operations with separate Go channels.
<lang go>package main

import (
"log"
"os"
"sync"
"time"
)

var fmt = log.New(os.Stdout, "", 0)

func main() {
// three operations per task description
acquire := make(chan int)
release := make(chan int)
count := make(chan chan int)

// library analogy per WP article
go librarian(acquire, release, count, 10)
nStudents := 20
var studied sync.WaitGroup
studied.Add(nStudents)
for i := 0; i < nStudents; i++ {
go student(acquire, release, count, &studied)
}
// wait until all students have studied before terminating program
studied.Wait()
}

func librarian(a, r chan int, c chan chan int, count int) {
p := a // acquire operation is served or not depending on count
for {
select {
case <-p: // acquire/p/wait operation
count--
if count == 0 {
p = nil
}
case <-r: // release/v operation
count++
p = a
case cc := <-c: // count operation
cc <- count
}
}
}

func student(a, r chan int, c chan chan int, studied *sync.WaitGroup) {
cc := make(chan int)
a <- 0 // acquire
c <- cc // request count
fmt.Printf("Room entered. Count is %d. Studying...\n", <-cc)
time.Sleep(2 * time.Second) // sleep per task description
r <- 0 // release
studied.Done() // signal done
}</lang>
}</lang>