Uhm, I just actually looked at the code.
You still use `r.start %= N`, which is a non-atomic access to r.start.
AIUI, SPSC stands for "single producer, single consumer", i.e. you know
that Get and Put will only be called from a single goroutine, respectively?
In that case, you wouldn't even need atomics to manipulate r.start/r.end.
Of course, you can't have a guarantee that your ringbuffer does not
overflow, that way.
But ISTM to make the conceptual code work with the race detector, you
should use atomic.Values for the elements of the slice and then can use
non-atomic accesses to r.start/r.end.

On Fri, Mar 11, 2022 at 7:45 AM Axel Wagner <axel.wagner...@googlemail.com>
wrote:

> You probably want to make the element type of the slice an atomic.Value,
> instead of an interface{}. You shouldn't need a mutex then.
>
> On Fri, Mar 11, 2022 at 7:31 AM Cameron Elliott <gara...@gmail.com> wrote:
>
>>
>>
>> Ian, thank you very much for the suggestion to use atomics.
>> Unfortunately, for a standard SPSC ring buffer, I don't think it does the
>> trick.
>>
>>
>> I am attaching a simple ring buffer program at the end.
>>
>> If you run 'go run -race main.go' on the example,
>> a race will occur.
>> The race that occurs is a write, then read to the
>> same element of a slice on two different goroutines.
>>
>> Of course a race-detected is expected.
>>
>> This can be fixed by mutexing Put() and Get(),
>> because through some magic, mutexs affect the tables/tags
>> the race detector maintains in order to catch races.
>>
>> Using sync.atomic on the ring buffer indexes doesn't
>> affect the race-detector state for read and writes.
>>
>> I spent more time investigating, it seems there are
>> two ways to make a traditional ring buffer compatible
>> with the race detector:
>>
>> 1. Use build tags to conditionally Lock/Unlock mutexes
>> where you would not actually need them, in order to reset
>> the race detector on the object crossing goroutines.
>>
>> 2. Use the pragma //go:linkname to get access to the 'runtime.race'
>> functions, in order to call Enable()/Disable/ReleaseMerge/Aquire
>> as sync.Pool does in order to make the race detector happy.
>>
>> If there are other methods, please let me know!
>> Thanks for any feedback!
>>
>> Cameron/Seattle
>>
>>
>>
>>
>>
>>
>>
>> package main
>>
>> import (
>>         "sync/atomic"
>>         "time"
>> )
>>
>> type RB struct {
>>     //mu sync.Mutex
>>         buf        []interface{}
>>         start, end int64
>> }
>>
>>
>> const N = 10
>>
>> func NewRB() *RB {
>>         return &RB{buf: make([]interface{}, N)}
>> }
>>
>> func (r *RB) Put(x interface{}) {
>> //    mu.Lock()
>> //    defer mu.Unlock()
>>
>>         r.buf[r.end] = x
>>         atomic.AddInt64(&r.end,1)
>>         //r.end++
>>         r.end %= N
>>
>> }
>>
>> func (r *RB) Get() interface{} {
>> //    mu.Lock()
>> //    defer mu.Unlock()
>>
>>         v := r.buf[r.start]
>>         atomic.AddInt64(&r.start,1)
>>         //r.start++
>>         r.start %= N
>>
>>         return v
>> }
>>
>> func main() {
>>
>>         r := NewRB()
>>
>>         go func() {
>>                 r.Put(12345)
>>         }()
>>
>>         time.Sleep(time.Millisecond)
>>
>>         a := r.Get().(int)
>>         println(a)
>> }
>>
>>
>> --
>> 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.
>> To view this discussion on the web visit
>> https://groups.google.com/d/msgid/golang-nuts/d7cc3410-c0bb-40d6-bf75-5e655ba3136en%40googlegroups.com
>> <https://groups.google.com/d/msgid/golang-nuts/d7cc3410-c0bb-40d6-bf75-5e655ba3136en%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>

-- 
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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAEkBMfGQU3E%3DaAO71%3DjaauEY_S8JFCLUAucc3RaaB3PB2XeRrg%40mail.gmail.com.

Reply via email to