awesome-patterns/concurrency/n_barrier/main.go

95 lines
1.3 KiB
Go
Raw Normal View History

2019-05-06 11:00:16 +03:00
package main
import (
"log"
"sync"
)
type IBarrier interface {
2019-05-10 09:57:25 +03:00
// error for timeout if need
2019-05-06 11:00:16 +03:00
Await() error
}
2019-05-10 09:57:25 +03:00
// once
type ChanBarrier struct {
2019-05-10 10:11:04 +03:00
waitCh chan struct{}
sign chan struct{}
2019-05-06 11:00:16 +03:00
}
2019-05-10 09:57:25 +03:00
func NewChanBarrier(gos int)*ChanBarrier{
2019-05-10 10:11:04 +03:00
b := &ChanBarrier{
waitCh:make(chan struct{} ,gos-1),
sign:make(chan struct{}),
2019-05-06 11:00:16 +03:00
}
2019-05-10 10:11:04 +03:00
for i:=0;i<gos-1;i++{
b.waitCh <- struct{}{}
}
return b
2019-05-06 11:00:16 +03:00
}
2019-05-10 10:11:04 +03:00
func (b *ChanBarrier) Await() error {
select {
case <- b.waitCh:
<- b.sign
default:
close(b.sign)
close(b.waitCh)
2019-05-06 11:00:16 +03:00
}
return nil
}
2019-05-10 09:57:25 +03:00
//type Barrier struct {
// cond *sync.Cond
// gos uint
// curgos uint
//}
//
//func NewBarrier(syncGos uint)*Barrier{
// if syncGos < 1{
// panic("min 1")
// }
// l := &sync.Mutex{}
// c := sync.NewCond(l)
// return &Barrier{
// cond:c,
// gos:syncGos,
// }
//}
//
//func (b *Barrier)Await() error{
// b.cond.L.Lock()
// defer b.cond.L.Unlock()
// b.curgos++
// if b.gos != b.curgos{
// b.cond.Wait()
// }else{
// b.curgos = 0
// b.cond.Broadcast()
// }
// return nil
//}
2019-05-06 11:00:16 +03:00
func main(){
var b IBarrier
wg := &sync.WaitGroup{}
gos := 10
wg.Add(gos)
2019-05-10 09:57:25 +03:00
//b = NewBarrier(uint(gos))
b = NewChanBarrier(gos)
2019-05-06 11:00:16 +03:00
for i:=0;i<gos ;i++ {
2019-05-10 10:11:04 +03:00
go func(n int) {
log.Println(n ,"await")
2019-05-06 11:00:16 +03:00
if err := b.Await();err != nil{
log.Println(err)
}
2019-05-10 10:11:04 +03:00
log.Println(n ,"pass")
2019-05-06 11:00:16 +03:00
wg.Done()
2019-05-10 10:11:04 +03:00
}(i)
2019-05-06 11:00:16 +03:00
}
wg.Wait()
}