purego: document that NewCallback consumes one table entry per call - #516
purego: document that NewCallback consumes one table entry per call#516kumagi wants to merge 3 commits into
Conversation
Passing a Go func value to C in a loop (e.g. via RegisterFunc's func arguments, which call NewCallback on every invocation) exhausts the fixed 2000-entry callback table and panics. Function values have no comparable identity available to reflect, so automatic deduplication is not possible; document the pitfall and the workaround of resolving the callback once and reusing the pointer.
The callback table size is an internal detail and the guarantee we can actually make on every platform is the one syscall.NewCallback gives on Windows, so document at least 1024 callbacks and drop the concrete table size from the NewCallback pitfall note.
|
Thanks for the review! I dropped the internal 2000 figure from the docs. NewCallback now states the same kind of minimum guarantee as syscall.NewCallback on Windows — at least 1024 callbacks can always be created — and the added note explains that every call creates a new callback (including the func arguments handled by RegisterFunc) without exposing the table size. Happy to adjust if a different wording or number is preferred. |
hajimehoshi
left a comment
There was a problem hiding this comment.
LGTM
@TotallyGamerJet PTAL
purego.NewCallback delegates to syscall.NewCallback on Windows, which also creates a new callback for every call, so the loop pitfall is not Unix specific. Document it there as well and link RegisterFunc from both notes.
|
Thanks again for the review! The docs no longer mention the internal table size: NewCallback now states the same minimum guarantee as syscall.NewCallback on Windows (at least 1024 callbacks), which holds everywhere because purego.NewCallback delegates to the standard library on Windows and the Unix table is larger than that. Since the behavior is not Unix specific — purego.NewCallback on Windows goes straight to syscall.NewCallback, which also creates a brand new callback on every call — I extended the same note to the Windows NewCallback documentation so both platforms describe the loop pitfall and the workaround of creating the callback once and reusing the returned pointer. The notes now link to RegisterFunc, which is where the per-call cost is easiest to hit accidentally. Everything is documentation only; go build, go vet and go test still pass, and the docs were checked for both Unix and Windows. |
What issue is this addressing?
Closes #521
What type of issue is this addressing?
bug
What this PR does | solves
Passing a Go func value to C in a loop (e.g. via RegisterFunc's func arguments, which call NewCallback on every invocation) exhausts the fixed 2000-entry callback table and panics. Function values have no comparable identity available to reflect, so automatic deduplication is not possible; document the pitfall and the workaround of resolving the callback once and reusing the pointer.