And is there actually a way to access the buffer memory directly?
Ellie
Eleanor McHugh
Games With Brains
http://feyeleanor.tel
----
if _, ok := reality.(Reasonable); !ok { panic(reality) }
The most obvious reason is because it's not thread safe.
Peeking at an item that may not be there when you actually go to read
it, isn't very useful.
You could always read items off the channel and put them back on
again. If you're not interested in the them.
- jessta
--
=====================
http://jessta.id.au
a synchronous channel has no head (it's like a zero-length slice)
>> And is there actually a way to access the buffer memory directly?
> The most obvious reason is because it's not thread safe.
> Peeking at an item that may not be there when you actually go to read
> it, isn't very useful.
that's true, but is also true of len of a channel.
> You could always read items off the channel and put them back on
> again. If you're not interested in the them.
you can't do that because a) it gets put back at the tail
of the queue rather than the end and b) a writer may have
got there first, so the put may block.
i have wanted a feature like this in the past. it can make
sense when there is only one consumer of the channel
(i wanted it to peek at the first mouse event to do hit
testing before deciding whether to consume it)
you can simulate it with a process acting as intermediary, but
you'd have to do it for each channel type or lose type safety.
on balance i think the need for this is small enough, and the
potential for abuse large enough that it's not a feature that
should be added.
True, but conceptually there's still either a value which can be read or there isn't so there's a dimensionality there - at least enough for a Head() call which on asynchronous channels would be At(0) and on synchronous channels wouldn't.
>>> And is there actually a way to access the buffer memory directly?
>
>> The most obvious reason is because it's not thread safe.
>> Peeking at an item that may not be there when you actually go to read
>> it, isn't very useful.
>
> that's true, but is also true of len of a channel.
>
>> You could always read items off the channel and put them back on
>> again. If you're not interested in the them.
>
> you can't do that because a) it gets put back at the tail
> of the queue rather than the end and b) a writer may have
> got there first, so the put may block.
>
> i have wanted a feature like this in the past. it can make
> sense when there is only one consumer of the channel
> (i wanted it to peek at the first mouse event to do hit
> testing before deciding whether to consume it)
My use case also has one consumer which is why my code's naturally pushing in this direction.
> you can simulate it with a process acting as intermediary, but
> you'd have to do it for each channel type or lose type safety.
>
> on balance i think the need for this is small enough, and the
> potential for abuse large enough that it's not a feature that
> should be added.
I agree it has great potential for abuse (it seems most of the things I'm interested in do lol) but there is an occasional need and I don't think it's unreasonable that reflection should support this in some way - even if there are lots of restrictions and caveats.
not really - there's can be a select at the other end of the channel;
whether there's a value or not depends on which arm of the select
is chosen.
remember there is no buffering, so if you peek at a value,
you'd have to get the value from the other side, which would
be equivalent to reading it - but that's wrong because peeking should
have no side
effects.
> I agree it has great potential for abuse (it seems most of the things I'm interested in do lol) but there is an occasional need and I don't think it's unreasonable that reflection should support this in some way - even if there are lots of restrictions and caveats.
if it's supported by reflection, it should be supported in non-reflection code.
out of interest, how would you wish to use this feature?
I hadn't thought that one through properly :)
>> I agree it has great potential for abuse (it seems most of the things I'm interested in do lol) but there is an occasional need and I don't think it's unreasonable that reflection should support this in some way - even if there are lots of restrictions and caveats.
>
> if it's supported by reflection, it should be supported in non-reflection code.
>
> out of interest, how would you wish to use this feature?
Well today specifically I'm testing whether or not a channel is the same as its embedded, reflected ChanValue - which obviously it is, but I just want some way of confirming that. Being able to directly compare the values queued at equivalent positions via the two access mechanisms would be a way of doing that without slightly fewer hardwire constants. This is certainly not a good reason for changing the language but it did set my mind thinking and now my unconscious mind is intimating that being able to do a peek might also be handy in my VM architecture work.
And yes, my unconscious mind is probably wrong.
type PeekChanInt struct {
in <-chan int
out chan int
}
func NewPeekChanInt(in <-chan int) *PeekChanInt {
pch := PeekChanInt{in, make(chan int, 1)}
go forwardVal(pch.out, pch.in)
return &pch
}
func (pch *PeekChanInt) Peek() (val int, ok bool) {
val, ok = <-pch.out
if ok {
pch.out <- val
}
return
}
func (pch *PeekChanInt) Get() (val int, ok bool) {
val, ok = <-pch.out
if ok {
go forwardVal(pch.out, pch.in)
}
return
}
func forwardVal(dst chan<- int, src <-chan int) {
val, ok := <-src
if ok {
dst <- val
} else {
close(dst)
}
}
--
.o. | Sterling (Chip) Camden | http://camdensoftware.com
..o | ster...@camdensoftware.com | http://chipsquips.com
ooo | 2048R/D6DBAF91 | http://chipstips.com
I quite like that bit of code. Hadn't really thought of the easy-fit pipe connector but if it works in plumbing it should work in software as well :)
the principle is sound, but i'm not sure it's necessary to
start a goroutine for every channel send.
how about something like this (untested)?
a deeper objection to this API is that you can no longer use
the channel in a select, although a more sophisticated piece
of code could enable it.
type PeekChanInt struct {
in <-chan int
v int
ok bool
}
func NewPeekChanInt(in <-chan int) *PeekChanInt {
return &PeekChanInt{in: in}
}
func (p *PeekChanInt) Peek() (int, bool) {
if !p.ok {
p.v, p.ok = <-p.in
}
return p.v, p.ok
}
func (p *PeekChanInt) Get() (int, bool) {
if p.ok {
p.ok = false
return p.v, true
}
v, ok := <-p.in
return v, ok
}
I thought of this too, but I was concerned about checking p.ok, and
then a couple instructions later, retrieving it's value, by when it
might not be okay. Of course, the peek might not be useful if there
are multiple readers anyway, for the reasons previously discussed, so
this may have been an unnecessary concern. I suppose you could use a
mutex to protect it without a go routine if necessary.
if there are multiple readers of the channel, then your original
code will exhibit the same behaviour.
if there are multiple users of the PeekChanInt, that's another matter - it
doesn't make sense to use it concurrently.