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.

Reply via email to