Thanks for comments. The status00 should be not-buffered (status00 = 
make(chan *Data)); was rate limiting on two channels.

On Sunday, August 28, 2016 at 8:16:50 PM UTC+4:30, Henrik Johansson wrote:
>
> 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.sh...@gmail.com <javascript:>> 
> 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...@googlegroups.com <javascript:>.
>> 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