tudo pronto
[3hU9fRjo95.git] / pc_monitor_cond.go~
blobe128825b4e13c906e25b150b8c7075e5b35aeddd
1 /* pc_monitor.go */
3 package main
5 import (
6         . "fmt"
7         "crypto/rand"
8         "time"
9         . "sync"
12 func random_between (begin, end int64) int64 {
13         random_byte := make([]byte, 1)
14         rand.Read(random_byte)
15         return int64(random_byte[0]) % (end - begin + 1) + begin
18 func random_sleep () {
19         time.Sleep(random_between(0, MAX_SLEEP_TIME) * 10e7)
22 func signal (channel chan int) {
23         if len(channel) < cap(channel) || cap(channel) == 0 {
24                 channel <- 0
25         }
28 func wait (channel chan int) {
29         <-channel
32 // tenta simular a atomicidade necessária para o bom funcionamento da variável de condição
33 func wait_cond (channel chan int, mutex *Mutex) {
34         c := make(chan int)             // canal síncrono
35         go waiter(channel, c) // tentativa de simular a atomicidade - não funciona!!!
36         mutex.Unlock()
37         wait(c)                                                         // em vez de wait(channel)
38         mutex.Lock()
41 // espera pelo canal in e então sinaliza no canal out
42 func waiter (in, out chan int) {
43         wait(in)
44         signal(out)
47 // envia assincronamente um valor qualquer para o canal channel
48 func trysignal (channel chan int) {
49         _ = channel <- 0
52 const (
53         MAX_SLEEP_TIME = 1
54         BUFFER_SIZE = 1
57 type Monitor struct {
58         mutex *Mutex
59         empty, full chan int
60         buffer []int
61         front, rear, count int
64 var monitor *Monitor
66 func newMonitor () *Monitor {
67         return &Monitor {
68                 new(Mutex),
69                 make(chan int), // variável de condição
70                 make(chan int), // variável de condição
71                 make([]int, BUFFER_SIZE),
72                 0, 0, 0 }
75 func (m *Monitor) produce (i int) {
76         m.mutex.Lock()
77                 for m.count == BUFFER_SIZE { // buffer cheio?
78                         wait_cond(m.empty, m.mutex)
79                 }
80                 Println("producing:", i)
81                 m.buffer[m.rear] = i
82                 m.rear = (m.rear + 1) % BUFFER_SIZE
83                 m.count++
84                 trysignal(m.full)
85         m.mutex.Unlock()
88 func (m *Monitor) consume () {
89         m.mutex.Lock()
90                 for m.count == 0 { // buffer vazio?
91                         wait_cond(m.full, m.mutex)
92                 }
93                 v := m.buffer[m.front]
94                 m.front = (m.front + 1) % BUFFER_SIZE
95                 m.count--
96                 Println("\t\t\tconsuming:", v)
97                 trysignal(m.empty)
98         m.mutex.Unlock()
101 func producer () {
102         for i := 0; ; i++ { // laço infinito
103                 monitor.produce(i)
104                 random_sleep()
105         }
108 func consumer () {
109         for { // laço infinito
110                 monitor.consume()
111                 random_sleep()
112         }
115 func main () {
116         monitor = newMonitor()
117         go producer()
118         go consumer()
119         wait(make(chan int)) // espera indefinidamente