On Friday, 27 May 2016 12:00:52 UTC+3, Peter Mogensen wrote:

On 2016-04-26 21:17, Ian Lance Taylor wrote:
On Tue, Apr 26, 2016 at 11:47 AM, Travis Keep <kee...@gmail.com
<javascript:>> wrote:
Been reading about cgo and all the rules about passing go pointers in C
memory and C pointers in go memory.

onfeof my data types is a []struct {ts float64, value interface{}} and
I am
trying to overlay this on a simple []byte. Since interfaces{} can
contain up
to two go pointers (one for the itable and one for the value), I am
go pointers in memory that is supposed to contain only non-pointers. I
wonder if this act is messing up the GC and causing the data corruption
I am seeing. Indeed the data corruption always happens in the
value, not the float64.
Your suspicions are correct: you can not do that.

The current docs for the unsafe package explain when it is safe to
convert a pointer value to uintptr (https://golang.org/pkg/unsafe/).
I think I have a use case which (for the foolish, but brave) could end
up in similar considerations about using unsafe and/or CGO.

I have an (almost) lock-free FIFO queue of many writers and one reader
in a hot path.

It's based on a datastructure like this:

type event struct {
seq uint64 // running sequence number of the value.
val int64
// val interface{}

type FifoQueue [queueSize]event

Simplified... the idea is that it's a ring-buffer and there's only used
locks when the writer catches up with the reader or the "seq" number is
about to wrap.

Anyway... The "val" field is supposed to be any *numerical* type. But if
I use an interface{}, I run into escape-analysis causing an extra
unnecessary allocation for boxing the numerical in an interface (and
some additional runtime cost).
The allocation unnecessary because I really don't need the full
interface{} generality. I only need numerical types. Something like:

type Value union {

type event struct {
seq uint64 // running sequence number of the value.
val Value

Now ... I could of course just duplicate all the code for the lock-free
FIFO queue in a copy for each of the needed types. :(

But not doing that would AFAICS involve fiddling with "unsafe".
See: https://github.com/egonelbre/exp/blob/master/ring/buffer.go

Convert the cell struct into

type Tag uint32
const (
     TagInt64 = Tag(iota)
type Cell struct {
sequence int64
tag Tag
data uint64

use: https://golang.org/pkg/math/#Float64bits to convert from64 float to
uint64, use tag to distinguish between the types.

If necessary add some methods such as:

func (cell *Cell) Set(v interface{}) { ... }
func (cell *Cell) Get() interface{} { ... }

That hides the tag and usage of Float64bits.

If the calling func with interface adds too much overhead, you can use:
func (cell *Cell) Tag() Tag { ... }
func (cell *Cell) SetInt64(v int64) { ... }
func (cell *Cell) GetInt64() int64 { ... }

Of course, if that is a problem, then you probably should start batching
anyways e.g.
type Tag int16
type Cell struct {
sequence int64
tag Tag
         count int16
data [32]uint64

+ Egon

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+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

Discussion Posts


Follow ups

Related Discussions

Discussion Navigation
viewthread | post
posts ‹ prev | 12 of 14 | next ›
Discussion Overview
groupgolang-nuts @
postedApr 26, '16 at 12:44a
activeMay 27, '16 at 10:57a



site design / logo © 2021 Grokbase