Improve Message.Reset API
lthibault opened this issue · comments
It's not immediately obvious how to use Message.Reset
to reuse a message from application code. At a glance, I would expect to have to do the following:
foo.Message().Reset(capnp.SingleSegment(nil))
foo, _ = NewRootFoo(foo.Segment())
, or some such
The "or some such" in item 2 says it all: it is not immediately clear where the proper segment can be obtained.
An alternative suggested by @zenhack would be to use NewMessage()
, though this will allocate an additional message. Perhaps this can be mitigated with some clever use of sync.Pool
?
Adding this to the 3.0 milestone, so we remember to consider it before locking ourselves in to the current API.
Relatedly, I would expect the following to work, but it produces a panic:
type pointerStore struct {
arena capnp.Arena
msg *capnp.Message
}
func (ps *pointerStore) Store(ptr capnp.Ptr) error {
if ps.msg == nil {
ps.msg = &capnp.Message{}
}
ps.arena = capnp.SingleSegment(nil)
ps.msg.Reset(ps.arena)
return ps.msg.SetRoot(ptr)
}
Another thought: is it possible to have Message.Reset()
call Arena.Reset()
instead of having to call the latter separately, as we do in transport.go
?
release := func() {
if alreadyReleased {
return
}
alreadyReleased = true
msg.Reset(nil)
arena.Release() // fold this into msg.Reset ?
}
Per discussion on matrix, we're going to call this one good; we'd both misunderstood what the API was for, and the docs have been clarified.