Open sqweek opened 6 years ago
I had issue like that with passing uintptr to slice data when I was working on my go-powered hypervisor. So I think that
uintptr(unsafe.Pointer(&lpvBits[0]))
also could be changed to:
uintptr(([3]unsafe.Pointer)(unsafe.Pointer(&lpvBits))[0])
so we resolve the array field instead of first slice index
Hrm, thanks. Can you elaborate on the difference between the two and why it caused problems? Logically they appear to represent the same thing to me, and a quick test gives me the same value for both:
package main
import "unsafe"
func main() {
a := make([]int, 5)
println(uintptr(unsafe.Pointer(&a[0])))
println(uintptr((*[3]unsafe.Pointer)(unsafe.Pointer(&a))[0]))
}
(this is all something of a tangent since this cast happens in the AllenDang/w32 package rather than go.wde)
sorry for the delay
basically, in normal case it should give the same value, but my way to do that will work even if
package main
import "unsafe"
func main() {
a := make([]int, 0)
// println(uintptr(unsafe.Pointer(&a[0]))) // uncomment to break the program
println(uintptr((*[3]unsafe.Pointer)(unsafe.Pointer(&a))[0])) // works like a charm
}
let's look into evaluation stages to see the difference:
println(uintptr(unsafe.Pointer(&a[0])))
stage 1. breaks if a.array len == 0.
println(uintptr(unsafe.Pointer(&a.array[0])))
stage 2. optimize, round 1
println(uintptr(unsafe.Pointer(a.array)))
stage 3. opimize, round 2. unnecessary unsafe.Pointer to unsafe.Pointer conversion
println(uintptr(a.array))
println(uintptr((*[3]unsafe.Pointer)(unsafe.Pointer(&a))[0]))
let's just make it simple to read
package main
import (
"unsafe"
"github.com/gramework/runtimer"
)
func main() {
a := make([]int, 0)
println(uintptr((*runtimer.SliceType2)(unsafe.Pointer(&a)).Array))
}
split on stages:
package main
import (
"unsafe"
"github.com/gramework/runtimer"
)
func main() {
a := make([]int, 0)
aPtr := unsafe.Pointer(&a)
runtimeSlice := (*runtimer.SliceType2)(aPtr)
aArrayPtr := runtimeSlice.Array
println(uintptr(aArrayPtr))
}
Ah I see... I guess the Array field resolves to nil in the zero length slice case? Anyway I think we should just avoid calling SetDIBitsToDevice with an empty slice here, but thanks for the details!
yep
I've seen it panic once when minimising a window, like so:
It's index 0:
lpvBits
corresponds tobuffer.Pix
inWindow.blitImage
, indicating that we have a zero-length pixel array.FlushImage
tries to avoid this scenario (since #46):So I guess
this.buffer
must be changing concurrently. I'm callingFlushImage
from a different goroutine than the one handlingEventChan
but I think it's racy even without that sinceWindow.buffer
is changed whenWndProc
handles aWM_SIZE
message, before theResizeEvent
is posted. Even the EventChan thread may observe the change to buffer before seeing the ResizeEvent.