The race is between the len call and the use of the channel. Entries can have been added in between.
On Sun, Aug 28, 2016, 17:40 dc0d <kaveh.shahbaz...@gmail.com> wrote: > Would you please elaborate on that? > > As I understand it there is no concurrent use of len happening here. It's > a for loop and all calling to len is happening sequentially. Unless the > channels make the code inside cases of one select statement concurrent - > which will be super confusing for me. > > > On Sunday, August 28, 2016 at 8:03:10 PM UTC+4:30, Jan Mercl wrote: > >> Using len(ch) like this in a concurrency scenario is a big no because >> then the value you get carries 0 bits of useful information. It's not a >> data race, it's worse, the race is semantic and not fixable without >> removing the use of len(ch). >> >> On Sun, Aug 28, 2016, 17:26 dc0d <kaveh.sh...@gmail.com> wrote: >> > TL;DR >>> >>> Does assigning a (buffered) channel, already in a variable, to a second >>> variable, affects the result of len function? >>> >>> Long version: >>> What is happening here? - Code at the end; Go 1.7. >>> >>> *Output 1*: >>> >>> Nine times: >>> [ info ] 2016/08/28 19:51:28 LEN_BEFORE=0 >>> >>> [ info ] 2016/08/28 19:51:28 LEN=7 >>> >>> [ info ] 2016/08/28 19:51:28 S00=7 >>> >>> But if the second case gets commented like this: >>> >>> case <-limiter.C: >>> // if len(actualBuffer) > 0 { >>> // buffer = actualBuffer >>> // } else { >>> // buffer = nil >>> // } >>> >>> It works as expected; *Output2*: >>> >>> [ info ] 2016/08/28 19:54:28 LEN_BEFORE=0 >>> >>> [ info ] 2016/08/28 19:54:28 LEN=7 >>> >>> [ info ] 2016/08/28 19:54:28 S00=7 >>> >>> [ info ] 2016/08/28 19:54:29 LEN_BEFORE=7 >>> >>> [ info ] 2016/08/28 19:54:30 LEN_BEFORE=7 >>> >>> [ info ] 2016/08/28 19:54:31 LEN_BEFORE=7 >>> >>> [ info ] 2016/08/28 19:54:32 LEN_BEFORE=7 >>> >>> [ info ] 2016/08/28 19:54:33 LEN_BEFORE=7 >>> >>> [ info ] 2016/08/28 19:54:34 LEN_BEFORE=7 >>> >>> [ info ] 2016/08/28 19:54:35 LEN_BEFORE=7 >>> >>> [ info ] 2016/08/28 19:54:36 LEN_BEFORE=7 >>> ... >>> >>> Code: >>> >>> package main >>> >>> >>> import ( >>> "log" >>> "time" >>> >>> >>> "github.com/comail/colog" >>> ) >>> >>> >>> func status00Channeler() { >>> <-start >>> >>> >>> limiter := time.NewTicker(time.Second / maxMsgPerSec) >>> fetchLimiter := time.NewTicker(time.Second) >>> >>> >>> var buffer chan *Data >>> actualBuffer := make(chan *Data, maxMsgPerSec) >>> db, err := newDB() >>> if err != nil { >>> log.Panic(err) >>> } >>> >>> >>> FIRST: >>> for { >>> select { >>> case <-interrupted: >>> break FIRST >>> case <-limiter.C: >>> // if len(actualBuffer) > 0 { >>> // buffer = actualBuffer >>> // } else { >>> // buffer = nil >>> // } >>> case i := <-buffer: >>> select { >>> case status00 <- i: // will block here >>> case <-interrupted: >>> break FIRST >>> } >>> case <-fetchLimiter.C: >>> log.Printf("LEN_BEFORE=%d", len(actualBuffer)) >>> if len(actualBuffer) > 0 { >>> continue >>> } >>> >>> >>> s00, err := db.GetIncomings() >>> if err != nil { >>> log.Println(`error:`, err) >>> time.Sleep(time.Second) >>> continue >>> } >>> if s00 == nil || len(s00) == 0 { >>> continue >>> } >>> >>> >>> FILL_BUFFER: >>> for _, v := range s00 { >>> select { >>> case actualBuffer <- v: >>> default: >>> break FILL_BUFFER >>> } >>> } >>> >>> >>> log.Printf("LEN=%d", len(actualBuffer)) >>> log.Printf("S00=%d", len(s00)) >>> } >>> } >>> } >>> >>> >>> func main() { >>> go status00Channeler() >>> close(start) >>> >>> >>> <-time.After(time.Second * 30) >>> } >>> >>> >>> var ( >>> status00 = make(chan *Data, maxMsgPerSec) >>> ) >>> >>> >>> type Data struct{} >>> >>> >>> const ( >>> maxMsgPerSec = 60 >>> ) >>> >>> >>> func newDB() (*DB, error) { >>> res := new(DB) >>> return res, nil >>> } >>> >>> >>> func (db *DB) GetIncomings() ([]*Data, error) { >>> var res []*Data >>> res = append(res, &Data{}) >>> res = append(res, &Data{}) >>> res = append(res, &Data{}) >>> res = append(res, &Data{}) >>> res = append(res, &Data{}) >>> res = append(res, &Data{}) >>> res = append(res, &Data{}) >>> >>> >>> return res, nil >>> } >>> >>> >>> type DB struct{} >>> >>> >>> func init() { >>> colog.Register() >>> } >>> >>> >>> var ( >>> start = make(chan struct{}) >>> interrupted = make(chan struct{}) // comes from sys interrupts SIGINT, >>> SIGTERM, etc >>> ) >>> >>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "golang-nuts" group. >>> >> To unsubscribe from this group and stop receiving emails from it, send an >>> email to golang-nuts...@googlegroups.com. >> >> >>> For more options, visit https://groups.google.com/d/optout. >>> >> -- >> >> -j >> > -- > You received this message because you are subscribed to the Google Groups > "golang-nuts" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-nuts+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.